Merge "Rename View.DragShadowBuilder#onProvideShadowMetrics parameters" into nyc-dev
diff --git a/Android.mk b/Android.mk
index 1469c2c..ae5d67e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -197,7 +197,6 @@
 	core/java/android/net/ICaptivePortal.aidl \
 	core/java/android/net/IConnectivityManager.aidl \
 	core/java/android/net/IConnectivityMetricsLogger.aidl \
-	core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl \
 	core/java/android/net/IEthernetManager.aidl \
 	core/java/android/net/IEthernetServiceListener.aidl \
 	core/java/android/net/INetworkManagementEventObserver.aidl \
@@ -245,6 +244,8 @@
 	core/java/android/service/notification/IConditionListener.aidl \
 	core/java/android/service/notification/IConditionProvider.aidl \
 	core/java/android/service/vr/IVrListener.aidl \
+	core/java/android/service/vr/IVrManager.aidl \
+	core/java/android/service/vr/IVrStateCallbacks.aidl \
 	core/java/android/print/ILayoutResultCallback.aidl \
 	core/java/android/print/IPrinterDiscoveryObserver.aidl \
 	core/java/android/print/IPrintDocumentAdapter.aidl \
diff --git a/api/current.txt b/api/current.txt
index 36dbc40..ed70474 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -71,6 +71,7 @@
     field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
     field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
     field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
+    field public static final java.lang.String GET_PASSWORD_PRIVILEGED = "android.permission.GET_PASSWORD_PRIVILEGED";
     field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";
     field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
     field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
@@ -2484,6 +2485,7 @@
     field public static final int Widget_Material_CompoundButton_CheckBox = 16974435; // 0x1030263
     field public static final int Widget_Material_CompoundButton_RadioButton = 16974436; // 0x1030264
     field public static final int Widget_Material_CompoundButton_Star = 16974437; // 0x1030265
+    field public static final int Widget_Material_CompoundButton_Switch = 16974554; // 0x10302da
     field public static final int Widget_Material_DatePicker = 16974438; // 0x1030266
     field public static final int Widget_Material_DropDownItem = 16974439; // 0x1030267
     field public static final int Widget_Material_DropDownItem_Spinner = 16974440; // 0x1030268
@@ -2518,6 +2520,7 @@
     field public static final int Widget_Material_Light_CompoundButton_CheckBox = 16974500; // 0x10302a4
     field public static final int Widget_Material_Light_CompoundButton_RadioButton = 16974501; // 0x10302a5
     field public static final int Widget_Material_Light_CompoundButton_Star = 16974502; // 0x10302a6
+    field public static final int Widget_Material_Light_CompoundButton_Switch = 16974555; // 0x10302db
     field public static final int Widget_Material_Light_DatePicker = 16974503; // 0x10302a7
     field public static final int Widget_Material_Light_DropDownItem = 16974504; // 0x10302a8
     field public static final int Widget_Material_Light_DropDownItem_Spinner = 16974505; // 0x10302a9
@@ -4912,6 +4915,7 @@
     field public static final int DEFAULT_LIGHTS = 4; // 0x4
     field public static final int DEFAULT_SOUND = 1; // 0x1
     field public static final int DEFAULT_VIBRATE = 2; // 0x2
+    field public static final java.lang.String EXTRA_ALLOW_GENERATED_REPLIES = "android.allowGeneratedReplies";
     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";
@@ -4920,12 +4924,14 @@
     field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
     field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
     field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
+    field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
     field public static final java.lang.String EXTRA_PEOPLE = "android.people";
     field public static final java.lang.String EXTRA_PICTURE = "android.picture";
     field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
     field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
     field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
     field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+    field public static final java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
     field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
     field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
     field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon";
@@ -4934,6 +4940,7 @@
     field public static final java.lang.String EXTRA_TEMPLATE = "android.template";
     field public static final java.lang.String EXTRA_TEXT = "android.text";
     field public static final java.lang.String EXTRA_TEXT_LINES = "android.textLines";
+    field public static final java.lang.String EXTRA_THREAD_TITLE = "android.threadTitle";
     field public static final java.lang.String EXTRA_TITLE = "android.title";
     field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
     field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
@@ -4976,7 +4983,7 @@
     field public int ledARGB;
     field public int ledOffMS;
     field public int ledOnMS;
-    field public int number;
+    field public deprecated int number;
     field public int priority;
     field public android.app.Notification publicVersion;
     field public android.net.Uri sound;
@@ -5023,11 +5030,13 @@
     method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder);
     method public java.lang.CharSequence getCancelLabel();
     method public java.lang.CharSequence getConfirmLabel();
+    method public boolean getHintContentIntentLaunchesActivity();
     method public java.lang.CharSequence getInProgressLabel();
     method public boolean isAvailableOffline();
     method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean);
     method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence);
     method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence);
+    method public android.app.Notification.Action.WearableExtender setHintContentIntentLaunchesActivity(boolean);
     method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
   }
 
@@ -5069,7 +5078,7 @@
     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);
+    method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setContentText(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
@@ -5086,7 +5095,7 @@
     method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
     method public android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
-    method public android.app.Notification.Builder setNumber(int);
+    method public deprecated android.app.Notification.Builder setNumber(int);
     method public android.app.Notification.Builder setOngoing(boolean);
     method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
     method public android.app.Notification.Builder setPriority(int);
@@ -5171,6 +5180,32 @@
     method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...);
   }
 
+  public static class Notification.MessagingStyle extends android.app.Notification.Style {
+    ctor public Notification.MessagingStyle(java.lang.CharSequence);
+    method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+    method public android.app.Notification.MessagingStyle addMessage(android.app.Notification.MessagingStyle.Message);
+    method public boolean getAllowGeneratedReplies();
+    method public java.lang.CharSequence getConversationTitle();
+    method public java.util.List<android.app.Notification.MessagingStyle.Message> getMessages();
+    method public java.lang.CharSequence getUserDisplayName();
+    method public android.app.Notification.MessagingStyle setAllowGeneratedReplies(boolean);
+    method public android.app.Notification.MessagingStyle setConversationTitle(java.lang.CharSequence);
+    field public static final int MAXIMUM_RETAINED_MESSAGES = 25; // 0x19
+  }
+
+  public static final class Notification.MessagingStyle.Message implements android.os.Parcelable {
+    ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+    method public int describeContents();
+    method public java.lang.String getDataMimeType();
+    method public android.net.Uri getDataUri();
+    method public java.lang.CharSequence getSender();
+    method public java.lang.CharSequence getText();
+    method public long getTimestamp();
+    method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.Notification.MessagingStyle.Message> CREATOR;
+  }
+
   public static abstract class Notification.Style {
     ctor public Notification.Style();
     method public android.app.Notification build();
@@ -5204,6 +5239,7 @@
     method public android.app.PendingIntent getDisplayIntent();
     method public int getGravity();
     method public boolean getHintAvoidBackgroundClipping();
+    method public boolean getHintContentIntentLaunchesActivity();
     method public boolean getHintHideIcon();
     method public int getHintScreenTimeout();
     method public boolean getHintShowBackgroundOnly();
@@ -5219,6 +5255,7 @@
     method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
     method public android.app.Notification.WearableExtender setGravity(int);
     method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
+    method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean);
     method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
     method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
     method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
@@ -5900,6 +5937,7 @@
     method public boolean isCallerApplicationRestrictionsManagingPackage();
     method public boolean isDeviceOwnerApp(java.lang.String);
     method public boolean isLockTaskPermitted(java.lang.String);
+    method public boolean isManagedProfile(android.content.ComponentName);
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean isProfileOwnerApp(java.lang.String);
@@ -5917,7 +5955,7 @@
     method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
     method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
-    method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
+    method public void setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException;
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -7881,6 +7919,7 @@
     method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
     method public void notifyChange(android.net.Uri, android.database.ContentObserver);
     method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
+    method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
     method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -7911,6 +7950,8 @@
     field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
     field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
     field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+    field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
+    field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
     field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
     field public static final java.lang.String SCHEME_CONTENT = "content";
     field public static final java.lang.String SCHEME_FILE = "file";
@@ -8519,8 +8560,9 @@
     field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
     field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
-    field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED = "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+    field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABLE = "android.intent.action.MANAGED_PROFILE_AVAILABLE";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
+    field public static final java.lang.String ACTION_MANAGED_PROFILE_UNAVAILABLE = "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
     field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
@@ -9915,6 +9957,7 @@
     field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80
     field public static final int PROTECTION_FLAG_PREINSTALLED = 1024; // 0x400
     field public static final int PROTECTION_FLAG_PRIVILEGED = 16; // 0x10
+    field public static final int PROTECTION_FLAG_SETUP = 2048; // 0x800
     field public static final deprecated int PROTECTION_FLAG_SYSTEM = 16; // 0x10
     field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200
     field public static final int PROTECTION_MASK_BASE = 15; // 0xf
@@ -13503,6 +13546,7 @@
   public final class Sensor {
     method public int getFifoMaxEventCount();
     method public int getFifoReservedEventCount();
+    method public int getId();
     method public int getMaxDelay();
     method public float getMaximumRange();
     method public int getMinDelay();
@@ -13512,9 +13556,10 @@
     method public float getResolution();
     method public java.lang.String getStringType();
     method public int getType();
-    method public java.util.UUID getUuid();
     method public java.lang.String getVendor();
     method public int getVersion();
+    method public boolean isAdditionalInfoSupported();
+    method public boolean isDynamicSensor();
     method public boolean isWakeUpSensor();
     field public static final int REPORTING_MODE_CONTINUOUS = 0; // 0x0
     field public static final int REPORTING_MODE_ONE_SHOT = 2; // 0x2
@@ -13633,8 +13678,9 @@
     method public static void getRotationMatrixFromVector(float[], float[]);
     method public java.util.List<android.hardware.Sensor> getSensorList(int);
     method public deprecated int getSensors();
-    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
-    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback, android.os.Handler);
+    method public boolean isDynamicSensorDiscoverySupported();
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorCallback);
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorCallback, android.os.Handler);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
@@ -13643,7 +13689,7 @@
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
     method public static boolean remapCoordinateSystem(float[], int, int, float[]);
     method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
-    method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
+    method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorCallback);
     method public deprecated void unregisterListener(android.hardware.SensorListener);
     method public deprecated void unregisterListener(android.hardware.SensorListener, int);
     method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -13708,8 +13754,8 @@
     field public static final float STANDARD_GRAVITY = 9.80665f;
   }
 
-  public static abstract class SensorManager.DynamicSensorConnectionCallback {
-    ctor public SensorManager.DynamicSensorConnectionCallback();
+  public static abstract class SensorManager.DynamicSensorCallback {
+    ctor public SensorManager.DynamicSensorCallback();
     method public void onDynamicSensorConnected(android.hardware.Sensor);
     method public void onDynamicSensorDisconnected(android.hardware.Sensor);
   }
@@ -19205,7 +19251,7 @@
     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 int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
-    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
     field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
     field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
     field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
@@ -19225,21 +19271,20 @@
   }
 
   public final class GnssMeasurementsEvent implements android.os.Parcelable {
-    ctor public GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]);
     method public int describeContents();
     method public android.location.GnssClock getClock();
     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_GNSS_LOCATION_DISABLED = 2; // 0x2
-    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
-    field public static final int STATUS_READY = 1; // 0x1
   }
 
   public static abstract class GnssMeasurementsEvent.Callback {
     ctor public GnssMeasurementsEvent.Callback();
     method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
     method public void onStatusChanged(int);
+    field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
   }
 
   public final class GnssNavigationMessage implements android.os.Parcelable {
@@ -19267,36 +19312,24 @@
     field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
-  public final class GnssNavigationMessageEvent implements android.os.Parcelable {
-    ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
-    method public int describeContents();
-    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_GNSS_LOCATION_DISABLED = 2; // 0x2
+  public static abstract class GnssNavigationMessage.Callback {
+    ctor public GnssNavigationMessage.Callback();
+    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
+    method public void onStatusChanged(int);
+    field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract class GnssNavigationMessageEvent.Callback {
-    ctor public GnssNavigationMessageEvent.Callback();
-    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
-    method public void onStatusChanged(int);
-  }
-
-  public abstract interface GnssNmeaListener {
-    method public abstract void onNmeaReceived(long, java.lang.String);
-  }
-
   public final class GnssStatus {
     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 int getSatelliteCount();
     method public int getSvid(int);
-    method public boolean hasAlmanac(int);
-    method public boolean hasEphemeris(int);
+    method public boolean hasAlmanacData(int);
+    method public boolean hasEphemerisData(int);
     method public boolean usedInFix(int);
     field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
     field public static final int CONSTELLATION_GALILEO = 6; // 0x6
@@ -19307,15 +19340,15 @@
     field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
   }
 
-  public abstract class GnssStatusCallback {
-    ctor public GnssStatusCallback();
+  public static abstract class GnssStatus.Callback {
+    ctor public GnssStatus.Callback();
     method public void onFirstFix(int);
     method public void onSatelliteStatusChanged(android.location.GnssStatus);
     method public void onStarted();
     method public void onStopped();
   }
 
-  public final class GpsSatellite {
+  public final deprecated class GpsSatellite {
     method public float getAzimuth();
     method public float getElevation();
     method public int getPrn();
@@ -19325,7 +19358,7 @@
     method public boolean usedInFix();
   }
 
-  public final class GpsStatus {
+  public final deprecated class GpsStatus {
     method public int getMaxSatellites();
     method public java.lang.Iterable<android.location.GpsSatellite> getSatellites();
     method public int getTimeToFirstFix();
@@ -19335,11 +19368,11 @@
     field public static final int GPS_EVENT_STOPPED = 2; // 0x2
   }
 
-  public static abstract interface GpsStatus.Listener {
+  public static abstract deprecated interface GpsStatus.Listener {
     method public abstract void onGpsStatusChanged(int);
   }
 
-  public static abstract interface GpsStatus.NmeaListener {
+  public static abstract deprecated interface GpsStatus.NmeaListener {
     method public abstract void onNmeaReceived(long, java.lang.String);
   }
 
@@ -19401,8 +19434,8 @@
   public class LocationManager {
     method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener);
     method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
-    method public boolean addNmeaListener(android.location.GnssNmeaListener);
-    method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
+    method public boolean addNmeaListener(android.location.OnNmeaMessageListener);
+    method public boolean addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler);
     method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
     method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
     method public void clearTestProviderEnabled(java.lang.String);
@@ -19418,13 +19451,13 @@
     method public boolean isProviderEnabled(java.lang.String);
     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);
-    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+    method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+    method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback, android.os.Handler);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback, android.os.Handler);
     method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener);
     method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener);
-    method public void removeNmeaListener(android.location.GnssNmeaListener);
+    method public void removeNmeaListener(android.location.OnNmeaMessageListener);
     method public void removeProximityAlert(android.app.PendingIntent);
     method public void removeTestProvider(java.lang.String);
     method public void removeUpdates(android.location.LocationListener);
@@ -19443,8 +19476,8 @@
     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 unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
-    method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+    method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
     field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
     field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -19473,6 +19506,10 @@
     field public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
   }
 
+  public abstract interface OnNmeaMessageListener {
+    method public abstract void onNmeaMessage(java.lang.String, long);
+  }
+
   public abstract class SettingInjectorService extends android.app.Service {
     ctor public SettingInjectorService(java.lang.String);
     method public final android.os.IBinder onBind(android.content.Intent);
@@ -19806,7 +19843,7 @@
 
   public static abstract class AudioManager.AudioRecordingCallback {
     ctor public AudioManager.AudioRecordingCallback();
-    method public void onRecordConfigChanged(android.media.AudioRecordingConfiguration[]);
+    method public void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]);
   }
 
   public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -20064,7 +20101,6 @@
   }
 
   public abstract class DrmInitData {
-    ctor public DrmInitData();
     method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
   }
 
@@ -20319,8 +20355,8 @@
 
   public class MediaActionSound {
     ctor public MediaActionSound();
-    method public synchronized void load(int);
-    method public synchronized void play(int);
+    method public void load(int);
+    method public void play(int);
     method public void release();
     field public static final int FOCUS_COMPLETE = 1; // 0x1
     field public static final int SHUTTER_CLICK = 0; // 0x0
@@ -20575,12 +20611,13 @@
     field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
     field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
     field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
-    field public static final int DolbyVisionProfileDvavDen = 2; // 0x2
-    field public static final int DolbyVisionProfileDvavDer = 1; // 0x1
-    field public static final int DolbyVisionProfileDvheDen = 4; // 0x4
-    field public static final int DolbyVisionProfileDvheDer = 3; // 0x3
-    field public static final int DolbyVisionProfileDvheDtr = 5; // 0x5
-    field public static final int DolbyVisionProfileDvheStn = 6; // 0x6
+    field public static final int DolbyVisionProfileDvavPen = 2; // 0x2
+    field public static final int DolbyVisionProfileDvavPer = 1; // 0x1
+    field public static final int DolbyVisionProfileDvheDen = 8; // 0x8
+    field public static final int DolbyVisionProfileDvheDer = 4; // 0x4
+    field public static final int DolbyVisionProfileDvheDth = 64; // 0x40
+    field public static final int DolbyVisionProfileDvheDtr = 16; // 0x10
+    field public static final int DolbyVisionProfileDvheStn = 32; // 0x20
     field public static final int H263Level10 = 1; // 0x1
     field public static final int H263Level20 = 2; // 0x2
     field public static final int H263Level30 = 4; // 0x4
@@ -23442,6 +23479,7 @@
     method public boolean isActiveNetworkMetered();
     method public boolean isDefaultNetworkActive();
     method public static deprecated boolean isNetworkTypeValid(int);
+    method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
     method public void releaseNetworkRequest(android.app.PendingIntent);
@@ -29067,6 +29105,7 @@
     method public boolean isInteractive();
     method public boolean isPowerSaveMode();
     method public deprecated boolean isScreenOn();
+    method public boolean isSustainedPerformanceModeSupported();
     method public boolean isWakeLockLevelSupported(int);
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
     method public void reboot(java.lang.String);
@@ -29693,7 +29732,6 @@
     method protected void onClick();
     method protected android.view.View onCreateView(android.view.ViewGroup);
     method public void onDependencyChanged(android.preference.Preference, boolean);
-    method protected void onDetachedFromActivity();
     method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
     method public void onParentChanged(android.preference.Preference, boolean);
     method protected void onPrepareForRemoval();
@@ -34675,6 +34713,7 @@
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onInterruptionFilterChanged(int);
     method public void onListenerConnected();
+    method public void onListenerDisconnected();
     method public void onListenerHintsChanged(int);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
@@ -36611,7 +36650,6 @@
     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 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);
@@ -36723,6 +36761,7 @@
     field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
     field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
     field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+    field public static final java.lang.String KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL = "carrier_wfc_supports_wifi_only_bool";
     field public static final java.lang.String KEY_CDMA_DTMF_TONE_DELAY_INT = "cdma_dtmf_tone_delay_int";
     field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
     field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
@@ -37299,7 +37338,8 @@
     method public java.lang.String getDeviceSoftwareVersion();
     method public java.lang.String getGroupIdLevel1();
     method public java.lang.String getGroupIdLevel1(int);
-    method public java.lang.String getIccSimChallengeResponse(int, java.lang.String);
+    method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+    method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
     method public java.lang.String getLine1AlphaTag(int);
     method public java.lang.String getLine1Number();
     method public java.lang.String getLine1Number(int);
@@ -37368,6 +37408,13 @@
     field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+    field public static final int APPTYPE_CSIM = 4; // 0x4
+    field public static final int APPTYPE_ISIM = 5; // 0x5
+    field public static final int APPTYPE_RUIM = 3; // 0x3
+    field public static final int APPTYPE_SIM = 1; // 0x1
+    field public static final int APPTYPE_USIM = 2; // 0x2
+    field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
+    field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
     field public static final int CALL_STATE_IDLE = 0; // 0x0
     field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
     field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -42265,6 +42312,7 @@
     method public boolean dispatchDragEvent(android.view.DragEvent);
     method protected void dispatchDraw(android.graphics.Canvas);
     method public void dispatchDrawableHotspotChanged(float, float);
+    method public void dispatchFinishTemporaryDetach();
     method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
     method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
     method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
@@ -42284,6 +42332,7 @@
     method protected void dispatchSetActivated(boolean);
     method protected void dispatchSetPressed(boolean);
     method protected void dispatchSetSelected(boolean);
+    method public void dispatchStartTemporaryDetach();
     method public void dispatchSystemUiVisibilityChanged(int);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
@@ -42496,6 +42545,7 @@
     method public boolean isSelected();
     method public boolean isShown();
     method public boolean isSoundEffectsEnabled();
+    method public final boolean isTemporarilyDetached();
     method public boolean isTextAlignmentResolved();
     method public boolean isTextDirectionResolved();
     method public boolean isVerticalFadingEdgeEnabled();
@@ -44080,8 +44130,6 @@
     method public void setVisibleToUser(boolean);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
-    field public static final java.lang.String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
-    field public static final java.lang.String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
     field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
     field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
     field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -44252,6 +44300,7 @@
 
   public final class AccessibilityWindowInfo implements android.os.Parcelable {
     method public int describeContents();
+    method public android.view.accessibility.AccessibilityNodeInfo getAnchor();
     method public void getBoundsInScreen(android.graphics.Rect);
     method public android.view.accessibility.AccessibilityWindowInfo getChild(int);
     method public int getChildCount();
@@ -44259,6 +44308,7 @@
     method public int getLayer();
     method public android.view.accessibility.AccessibilityWindowInfo getParent();
     method public android.view.accessibility.AccessibilityNodeInfo getRoot();
+    method public java.lang.CharSequence getTitle();
     method public int getType();
     method public boolean isAccessibilityFocused();
     method public boolean isActive();
@@ -46250,7 +46300,7 @@
     method public long getMinDate();
     method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
     method public deprecated int getSelectedWeekBackgroundColor();
-    method public boolean getShowWeekNumber();
+    method public deprecated boolean getShowWeekNumber();
     method public deprecated int getShownWeekCount();
     method public deprecated int getUnfocusedMonthDateColor();
     method public int getWeekDayTextAppearance();
@@ -46267,7 +46317,7 @@
     method public deprecated void setSelectedDateVerticalBar(int);
     method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
     method public deprecated void setSelectedWeekBackgroundColor(int);
-    method public void setShowWeekNumber(boolean);
+    method public deprecated void setShowWeekNumber(boolean);
     method public deprecated void setShownWeekCount(int);
     method public deprecated void setUnfocusedMonthDateColor(int);
     method public void setWeekDayTextAppearance(int);
@@ -46414,21 +46464,21 @@
     ctor public DatePicker(android.content.Context, android.util.AttributeSet);
     ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
     ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
-    method public android.widget.CalendarView getCalendarView();
-    method public boolean getCalendarViewShown();
+    method public deprecated android.widget.CalendarView getCalendarView();
+    method public deprecated boolean getCalendarViewShown();
     method public int getDayOfMonth();
     method public int getFirstDayOfWeek();
     method public long getMaxDate();
     method public long getMinDate();
     method public int getMonth();
-    method public boolean getSpinnersShown();
+    method public deprecated boolean getSpinnersShown();
     method public int getYear();
     method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
-    method public void setCalendarViewShown(boolean);
+    method public deprecated void setCalendarViewShown(boolean);
     method public void setFirstDayOfWeek(int);
     method public void setMaxDate(long);
     method public void setMinDate(long);
-    method public void setSpinnersShown(boolean);
+    method public deprecated void setSpinnersShown(boolean);
     method public void updateDate(int, int, int);
   }
 
@@ -50000,6 +50050,10 @@
     method public static int compare(boolean, boolean);
     method public int compareTo(java.lang.Boolean);
     method public static boolean getBoolean(java.lang.String);
+    method public static int hashCode(boolean);
+    method public static boolean logicalAnd(boolean, boolean);
+    method public static boolean logicalOr(boolean, boolean);
+    method public static boolean logicalXor(boolean, boolean);
     method public static boolean parseBoolean(java.lang.String);
     method public static java.lang.String toString(boolean);
     method public static java.lang.Boolean valueOf(boolean);
@@ -50017,6 +50071,7 @@
     method public static java.lang.Byte decode(java.lang.String) throws java.lang.NumberFormatException;
     method public double doubleValue();
     method public float floatValue();
+    method public static int hashCode(byte);
     method public int intValue();
     method public long longValue();
     method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50025,6 +50080,7 @@
     method public static java.lang.Byte valueOf(byte);
     method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Byte valueOf(java.lang.String) throws java.lang.NumberFormatException;
+    field public static final int BYTES = 1; // 0x1
     field public static final byte MAX_VALUE = 127; // 0x7f
     field public static final byte MIN_VALUE = -128; // 0xffffff80
     field public static final int SIZE = 8; // 0x8
@@ -50062,6 +50118,7 @@
     method public static int getNumericValue(int);
     method public static int getType(char);
     method public static int getType(int);
+    method public static int hashCode(char);
     method public static char highSurrogate(int);
     method public static boolean isAlphabetic(int);
     method public static boolean isBmpCodePoint(int);
@@ -50122,6 +50179,7 @@
     method public static char toUpperCase(char);
     method public static int toUpperCase(int);
     method public static java.lang.Character valueOf(char);
+    field public static final int BYTES = 2; // 0x2
     field public static final byte COMBINING_SPACING_MARK = 8; // 0x8
     field public static final byte CONNECTOR_PUNCTUATION = 23; // 0x17
     field public static final byte CONTROL = 15; // 0xf
@@ -50748,6 +50806,7 @@
     method public static int floatToIntBits(float);
     method public static int floatToRawIntBits(float);
     method public float floatValue();
+    method public static int hashCode(float);
     method public static float intBitsToFloat(int);
     method public int intValue();
     method public static boolean isFinite(float);
@@ -50756,11 +50815,15 @@
     method public static boolean isNaN(float);
     method public boolean isNaN();
     method public long longValue();
+    method public static float max(float, float);
+    method public static float min(float, float);
     method public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
+    method public static float sum(float, float);
     method public static java.lang.String toHexString(float);
     method public static java.lang.String toString(float);
     method public static java.lang.Float valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Float valueOf(float);
+    field public static final int BYTES = 4; // 0x4
     field public static final int MAX_EXPONENT = 127; // 0x7f
     field public static final float MAX_VALUE = 3.4028235E38f;
     field public static final int MIN_EXPONENT = -126; // 0xffffff82
@@ -50940,6 +51003,7 @@
     method public static java.lang.Long valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Long valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Long valueOf(long);
+    field public static final int BYTES = 8; // 0x8
     field public static final long MAX_VALUE = 9223372036854775807L; // 0x7fffffffffffffffL
     field public static final long MIN_VALUE = -9223372036854775808L; // 0x8000000000000000L
     field public static final int SIZE = 64; // 0x40
@@ -50953,6 +51017,8 @@
     method public static float abs(float);
     method public static double abs(double);
     method public static double acos(double);
+    method public static int addExact(int, int);
+    method public static long addExact(long, long);
     method public static double asin(double);
     method public static double atan(double);
     method public static double atan2(double, double);
@@ -50962,12 +51028,20 @@
     method public static float copySign(float, float);
     method public static double cos(double);
     method public static double cosh(double);
+    method public static int decrementExact(int);
+    method public static long decrementExact(long);
     method public static double exp(double);
     method public static double expm1(double);
     method public static double floor(double);
+    method public static int floorDiv(int, int);
+    method public static long floorDiv(long, long);
+    method public static int floorMod(int, int);
+    method public static long floorMod(long, long);
     method public static int getExponent(float);
     method public static int getExponent(double);
     method public static double hypot(double, double);
+    method public static int incrementExact(int);
+    method public static long incrementExact(long);
     method public static double log(double);
     method public static double log10(double);
     method public static double log1p(double);
@@ -50979,8 +51053,14 @@
     method public static long min(long, long);
     method public static float min(float, float);
     method public static double min(double, double);
+    method public static int multiplyExact(int, int);
+    method public static long multiplyExact(long, long);
+    method public static int negateExact(int);
+    method public static long negateExact(long);
     method public static double nextAfter(double, double);
     method public static float nextAfter(float, double);
+    method public static double nextDown(double);
+    method public static float nextDown(float);
     method public static double nextUp(double);
     method public static float nextUp(float);
     method public static double pow(double, double);
@@ -50995,9 +51075,12 @@
     method public static double sin(double);
     method public static double sinh(double);
     method public static double sqrt(double);
+    method public static int subtractExact(int, int);
+    method public static long subtractExact(long, long);
     method public static double tan(double);
     method public static double tanh(double);
     method public static double toDegrees(double);
+    method public static int toIntExact(long);
     method public static double toRadians(double);
     method public static double ulp(double);
     method public static float ulp(float);
@@ -51243,6 +51326,7 @@
     method public static java.lang.Short decode(java.lang.String) throws java.lang.NumberFormatException;
     method public double doubleValue();
     method public float floatValue();
+    method public static int hashCode(short);
     method public int intValue();
     method public long longValue();
     method public static short parseShort(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -51252,6 +51336,7 @@
     method public static java.lang.Short valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Short valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Short valueOf(short);
+    field public static final int BYTES = 2; // 0x2
     field public static final short MAX_VALUE = 32767; // 0x7fff
     field public static final short MIN_VALUE = -32768; // 0xffff8000
     field public static final int SIZE = 16; // 0x10
@@ -51279,6 +51364,8 @@
     method public static float abs(float);
     method public static double abs(double);
     method public static double acos(double);
+    method public static int addExact(int, int);
+    method public static long addExact(long, long);
     method public static double asin(double);
     method public static double atan(double);
     method public static double atan2(double, double);
@@ -51291,6 +51378,10 @@
     method public static double exp(double);
     method public static double expm1(double);
     method public static double floor(double);
+    method public static int floorDiv(int, int);
+    method public static long floorDiv(long, long);
+    method public static int floorMod(int, int);
+    method public static long floorMod(long, long);
     method public static int getExponent(float);
     method public static int getExponent(double);
     method public static double hypot(double, double);
@@ -51305,8 +51396,12 @@
     method public static long min(long, long);
     method public static float min(float, float);
     method public static double min(double, double);
+    method public static int multiplyExact(int, int);
+    method public static long multiplyExact(long, long);
     method public static double nextAfter(double, double);
     method public static float nextAfter(float, double);
+    method public static double nextDown(double);
+    method public static float nextDown(float);
     method public static double nextUp(double);
     method public static float nextUp(float);
     method public static double pow(double, double);
@@ -51321,9 +51416,12 @@
     method public static double sin(double);
     method public static double sinh(double);
     method public static double sqrt(double);
+    method public static int subtractExact(int, int);
+    method public static long subtractExact(long, long);
     method public static double tan(double);
     method public static double tanh(double);
     method public static double toDegrees(double);
+    method public static int toIntExact(long);
     method public static double toRadians(double);
     method public static double ulp(double);
     method public static float ulp(float);
@@ -57371,6 +57469,14 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
+    method public static void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
+    method public static void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
+    method public static void parallelPrefix(long[], java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(double[], java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(int[], java.util.function.IntBinaryOperator);
+    method public static void parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator);
     method public static void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
     method public static void parallelSetAll(int[], java.util.function.IntUnaryOperator);
     method public static void parallelSetAll(long[], java.util.function.IntToLongFunction);
diff --git a/api/removed.txt b/api/removed.txt
index 3f16bca..8c6abdc 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -84,6 +84,67 @@
 
 }
 
+package android.location {
+
+  public final class GnssMeasurement implements android.os.Parcelable {
+    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+  }
+
+  public final class GnssMeasurementsEvent implements android.os.Parcelable {
+    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
+  }
+
+  public final class GnssNavigationMessageEvent implements android.os.Parcelable {
+    ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
+    method public int describeContents();
+    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_GNSS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
+  }
+
+  public static abstract class GnssNavigationMessageEvent.Callback {
+    ctor public GnssNavigationMessageEvent.Callback();
+    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
+    method public void onStatusChanged(int);
+  }
+
+  public abstract interface GnssNmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public final class GnssStatus {
+    method public int getNumSatellites();
+    method public boolean hasAlmanac(int);
+    method public boolean hasEphemeris(int);
+  }
+
+  public abstract class GnssStatusCallback {
+    ctor public GnssStatusCallback();
+    method public void onFirstFix(int);
+    method public void onSatelliteStatusChanged(android.location.GnssStatus);
+    method public void onStarted();
+    method public void onStopped();
+  }
+
+  public class LocationManager {
+    method public boolean addNmeaListener(android.location.GnssNmeaListener);
+    method public boolean addNmeaListener(android.location.GnssNmeaListener, 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);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+    method public void removeNmeaListener(android.location.GnssNmeaListener);
+    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
+    method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 96f2b06..0896214 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -103,6 +103,7 @@
     field public static final java.lang.String GET_APP_OPS_STATS = "android.permission.GET_APP_OPS_STATS";
     field public static final java.lang.String GET_PACKAGE_IMPORTANCE = "android.permission.GET_PACKAGE_IMPORTANCE";
     field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
+    field public static final java.lang.String GET_PASSWORD_PRIVILEGED = "android.permission.GET_PASSWORD_PRIVILEGED";
     field public static final java.lang.String GET_PROCESS_STATE_AND_OOM_SCORE = "android.permission.GET_PROCESS_STATE_AND_OOM_SCORE";
     field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";
     field public static final java.lang.String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
@@ -2587,6 +2588,7 @@
     field public static final int Widget_Material_CompoundButton_CheckBox = 16974435; // 0x1030263
     field public static final int Widget_Material_CompoundButton_RadioButton = 16974436; // 0x1030264
     field public static final int Widget_Material_CompoundButton_Star = 16974437; // 0x1030265
+    field public static final int Widget_Material_CompoundButton_Switch = 16974554; // 0x10302da
     field public static final int Widget_Material_DatePicker = 16974438; // 0x1030266
     field public static final int Widget_Material_DropDownItem = 16974439; // 0x1030267
     field public static final int Widget_Material_DropDownItem_Spinner = 16974440; // 0x1030268
@@ -2621,6 +2623,7 @@
     field public static final int Widget_Material_Light_CompoundButton_CheckBox = 16974500; // 0x10302a4
     field public static final int Widget_Material_Light_CompoundButton_RadioButton = 16974501; // 0x10302a5
     field public static final int Widget_Material_Light_CompoundButton_Star = 16974502; // 0x10302a6
+    field public static final int Widget_Material_Light_CompoundButton_Switch = 16974555; // 0x10302db
     field public static final int Widget_Material_Light_DatePicker = 16974503; // 0x10302a7
     field public static final int Widget_Material_Light_DropDownItem = 16974504; // 0x10302a8
     field public static final int Widget_Material_Light_DropDownItem_Spinner = 16974505; // 0x10302a9
@@ -5045,6 +5048,7 @@
     field public static final int DEFAULT_LIGHTS = 4; // 0x4
     field public static final int DEFAULT_SOUND = 1; // 0x1
     field public static final int DEFAULT_VIBRATE = 2; // 0x2
+    field public static final java.lang.String EXTRA_ALLOW_GENERATED_REPLIES = "android.allowGeneratedReplies";
     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";
@@ -5053,12 +5057,14 @@
     field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
     field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
     field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
+    field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
     field public static final java.lang.String EXTRA_PEOPLE = "android.people";
     field public static final java.lang.String EXTRA_PICTURE = "android.picture";
     field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
     field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
     field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
     field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+    field public static final java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
     field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
     field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
     field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon";
@@ -5067,6 +5073,7 @@
     field public static final java.lang.String EXTRA_TEMPLATE = "android.template";
     field public static final java.lang.String EXTRA_TEXT = "android.text";
     field public static final java.lang.String EXTRA_TEXT_LINES = "android.textLines";
+    field public static final java.lang.String EXTRA_THREAD_TITLE = "android.threadTitle";
     field public static final java.lang.String EXTRA_TITLE = "android.title";
     field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
     field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
@@ -5109,7 +5116,7 @@
     field public int ledARGB;
     field public int ledOffMS;
     field public int ledOnMS;
-    field public int number;
+    field public deprecated int number;
     field public int priority;
     field public android.app.Notification publicVersion;
     field public android.net.Uri sound;
@@ -5156,11 +5163,13 @@
     method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder);
     method public java.lang.CharSequence getCancelLabel();
     method public java.lang.CharSequence getConfirmLabel();
+    method public boolean getHintContentIntentLaunchesActivity();
     method public java.lang.CharSequence getInProgressLabel();
     method public boolean isAvailableOffline();
     method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean);
     method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence);
     method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence);
+    method public android.app.Notification.Action.WearableExtender setHintContentIntentLaunchesActivity(boolean);
     method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
   }
 
@@ -5202,7 +5211,7 @@
     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);
+    method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setContentText(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
@@ -5219,7 +5228,7 @@
     method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
     method public android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
-    method public android.app.Notification.Builder setNumber(int);
+    method public deprecated android.app.Notification.Builder setNumber(int);
     method public android.app.Notification.Builder setOngoing(boolean);
     method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
     method public android.app.Notification.Builder setPriority(int);
@@ -5304,6 +5313,32 @@
     method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...);
   }
 
+  public static class Notification.MessagingStyle extends android.app.Notification.Style {
+    ctor public Notification.MessagingStyle(java.lang.CharSequence);
+    method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+    method public android.app.Notification.MessagingStyle addMessage(android.app.Notification.MessagingStyle.Message);
+    method public boolean getAllowGeneratedReplies();
+    method public java.lang.CharSequence getConversationTitle();
+    method public java.util.List<android.app.Notification.MessagingStyle.Message> getMessages();
+    method public java.lang.CharSequence getUserDisplayName();
+    method public android.app.Notification.MessagingStyle setAllowGeneratedReplies(boolean);
+    method public android.app.Notification.MessagingStyle setConversationTitle(java.lang.CharSequence);
+    field public static final int MAXIMUM_RETAINED_MESSAGES = 25; // 0x19
+  }
+
+  public static final class Notification.MessagingStyle.Message implements android.os.Parcelable {
+    ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+    method public int describeContents();
+    method public java.lang.String getDataMimeType();
+    method public android.net.Uri getDataUri();
+    method public java.lang.CharSequence getSender();
+    method public java.lang.CharSequence getText();
+    method public long getTimestamp();
+    method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.Notification.MessagingStyle.Message> CREATOR;
+  }
+
   public static abstract class Notification.Style {
     ctor public Notification.Style();
     method public android.app.Notification build();
@@ -5337,6 +5372,7 @@
     method public android.app.PendingIntent getDisplayIntent();
     method public int getGravity();
     method public boolean getHintAvoidBackgroundClipping();
+    method public boolean getHintContentIntentLaunchesActivity();
     method public boolean getHintHideIcon();
     method public int getHintScreenTimeout();
     method public boolean getHintShowBackgroundOnly();
@@ -5352,6 +5388,7 @@
     method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
     method public android.app.Notification.WearableExtender setGravity(int);
     method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
+    method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean);
     method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
     method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
     method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
@@ -6047,6 +6084,7 @@
     method public boolean isCallerApplicationRestrictionsManagingPackage();
     method public boolean isDeviceOwnerApp(java.lang.String);
     method public boolean isLockTaskPermitted(java.lang.String);
+    method public boolean isManagedProfile(android.content.ComponentName);
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean isProfileOwnerApp(java.lang.String);
@@ -6066,7 +6104,7 @@
     method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException;
-    method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
+    method public void setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException;
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -8179,6 +8217,7 @@
     method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
     method public void notifyChange(android.net.Uri, android.database.ContentObserver);
     method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
+    method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
     method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -8209,6 +8248,8 @@
     field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
     field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
     field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+    field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
+    field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
     field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
     field public static final java.lang.String SCHEME_CONTENT = "content";
     field public static final java.lang.String SCHEME_FILE = "file";
@@ -8835,8 +8876,9 @@
     field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
     field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
-    field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED = "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+    field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABLE = "android.intent.action.MANAGED_PROFILE_AVAILABLE";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
+    field public static final java.lang.String ACTION_MANAGED_PROFILE_UNAVAILABLE = "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
     field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
@@ -10314,6 +10356,7 @@
     field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80
     field public static final int PROTECTION_FLAG_PREINSTALLED = 1024; // 0x400
     field public static final int PROTECTION_FLAG_PRIVILEGED = 16; // 0x10
+    field public static final int PROTECTION_FLAG_SETUP = 2048; // 0x800
     field public static final deprecated int PROTECTION_FLAG_SYSTEM = 16; // 0x10
     field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200
     field public static final int PROTECTION_MASK_BASE = 15; // 0xf
@@ -13902,6 +13945,7 @@
   public final class Sensor {
     method public int getFifoMaxEventCount();
     method public int getFifoReservedEventCount();
+    method public int getId();
     method public int getMaxDelay();
     method public float getMaximumRange();
     method public int getMinDelay();
@@ -13914,7 +13958,9 @@
     method public java.util.UUID getUuid();
     method public java.lang.String getVendor();
     method public int getVersion();
+    method public boolean isAdditionalInfoSupported();
     method public boolean isDataInjectionSupported();
+    method public boolean isDynamicSensor();
     method public boolean isWakeUpSensor();
     field public static final int REPORTING_MODE_CONTINUOUS = 0; // 0x0
     field public static final int REPORTING_MODE_ONE_SHOT = 2; // 0x2
@@ -14039,8 +14085,9 @@
     method public deprecated int getSensors();
     method public boolean initDataInjection(boolean);
     method public boolean injectSensorData(android.hardware.Sensor, float[], int, long);
-    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
-    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback, android.os.Handler);
+    method public boolean isDynamicSensorDiscoverySupported();
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorCallback);
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorCallback, android.os.Handler);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
@@ -14049,7 +14096,7 @@
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
     method public static boolean remapCoordinateSystem(float[], int, int, float[]);
     method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
-    method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
+    method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorCallback);
     method public deprecated void unregisterListener(android.hardware.SensorListener);
     method public deprecated void unregisterListener(android.hardware.SensorListener, int);
     method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -14114,8 +14161,8 @@
     field public static final float STANDARD_GRAVITY = 9.80665f;
   }
 
-  public static abstract class SensorManager.DynamicSensorConnectionCallback {
-    ctor public SensorManager.DynamicSensorConnectionCallback();
+  public static abstract class SensorManager.DynamicSensorCallback {
+    ctor public SensorManager.DynamicSensorCallback();
     method public void onDynamicSensorConnected(android.hardware.Sensor);
     method public void onDynamicSensorDisconnected(android.hardware.Sensor);
   }
@@ -15264,6 +15311,7 @@
     ctor public ContextHubInfo();
     method public int describeContents();
     method public int getId();
+    method public int getMaxPacketLengthBytes();
     method public android.hardware.location.MemoryRegion[] getMemoryRegions();
     method public java.lang.String getName();
     method public float getPeakMips();
@@ -15291,10 +15339,6 @@
     method public int sendMessage(int, int, android.hardware.location.ContextHubMessage);
     method public int unloadNanoApp(int);
     method public int unregisterCallback(android.hardware.location.ContextHubManager.Callback);
-    field public static final int ANY_HUB = -1; // 0xffffffff
-    field public static final int MSG_DATA_SEND = 3; // 0x3
-    field public static final int MSG_LOAD_NANO_APP = 1; // 0x1
-    field public static final int MSG_UNLOAD_NANO_APP = 2; // 0x2
   }
 
   public static abstract class ContextHubManager.Callback {
@@ -15488,7 +15532,7 @@
   public class NanoAppInstanceInfo {
     ctor public NanoAppInstanceInfo();
     method public int describeContents();
-    method public int getAppId();
+    method public long getAppId();
     method public int getAppVersion();
     method public int getContexthubId();
     method public int getHandle();
@@ -15499,17 +15543,6 @@
     method public int getNeededWriteMemBytes();
     method public int[] getOutputEvents();
     method public java.lang.String getPublisher();
-    method public void setAppId(int);
-    method public void setAppVersion(int);
-    method public void setContexthubId(int);
-    method public void setHandle(int);
-    method public void setName(java.lang.String);
-    method public void setNeededExecMemBytes(int);
-    method public void setNeededReadMemBytes(int);
-    method public void setNeededSensors(int[]);
-    method public void setNeededWriteMemBytes(int);
-    method public void setOutputEvents(int[]);
-    method public void setPublisher(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.hardware.location.NanoAppInstanceInfo> CREATOR;
   }
@@ -20378,7 +20411,7 @@
     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 int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
-    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
     field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
     field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
     field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
@@ -20398,21 +20431,20 @@
   }
 
   public final class GnssMeasurementsEvent implements android.os.Parcelable {
-    ctor public GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]);
     method public int describeContents();
     method public android.location.GnssClock getClock();
     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_GNSS_LOCATION_DISABLED = 2; // 0x2
-    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
-    field public static final int STATUS_READY = 1; // 0x1
   }
 
   public static abstract class GnssMeasurementsEvent.Callback {
     ctor public GnssMeasurementsEvent.Callback();
     method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
     method public void onStatusChanged(int);
+    field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
   }
 
   public final class GnssNavigationMessage implements android.os.Parcelable {
@@ -20440,36 +20472,24 @@
     field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
-  public final class GnssNavigationMessageEvent implements android.os.Parcelable {
-    ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
-    method public int describeContents();
-    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_GNSS_LOCATION_DISABLED = 2; // 0x2
+  public static abstract class GnssNavigationMessage.Callback {
+    ctor public GnssNavigationMessage.Callback();
+    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
+    method public void onStatusChanged(int);
+    field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract class GnssNavigationMessageEvent.Callback {
-    ctor public GnssNavigationMessageEvent.Callback();
-    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
-    method public void onStatusChanged(int);
-  }
-
-  public abstract interface GnssNmeaListener {
-    method public abstract void onNmeaReceived(long, java.lang.String);
-  }
-
   public final class GnssStatus {
     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 int getSatelliteCount();
     method public int getSvid(int);
-    method public boolean hasAlmanac(int);
-    method public boolean hasEphemeris(int);
+    method public boolean hasAlmanacData(int);
+    method public boolean hasEphemerisData(int);
     method public boolean usedInFix(int);
     field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
     field public static final int CONSTELLATION_GALILEO = 6; // 0x6
@@ -20480,8 +20500,8 @@
     field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
   }
 
-  public abstract class GnssStatusCallback {
-    ctor public GnssStatusCallback();
+  public static abstract class GnssStatus.Callback {
+    ctor public GnssStatus.Callback();
     method public void onFirstFix(int);
     method public void onSatelliteStatusChanged(android.location.GnssStatus);
     method public void onStarted();
@@ -20713,7 +20733,7 @@
     method public abstract void onStatusChanged(int);
   }
 
-  public final class GpsSatellite {
+  public final deprecated class GpsSatellite {
     method public float getAzimuth();
     method public float getElevation();
     method public int getPrn();
@@ -20723,7 +20743,7 @@
     method public boolean usedInFix();
   }
 
-  public final class GpsStatus {
+  public final deprecated class GpsStatus {
     method public int getMaxSatellites();
     method public java.lang.Iterable<android.location.GpsSatellite> getSatellites();
     method public int getTimeToFirstFix();
@@ -20733,11 +20753,11 @@
     field public static final int GPS_EVENT_STOPPED = 2; // 0x2
   }
 
-  public static abstract interface GpsStatus.Listener {
+  public static abstract deprecated interface GpsStatus.Listener {
     method public abstract void onGpsStatusChanged(int);
   }
 
-  public static abstract interface GpsStatus.NmeaListener {
+  public static abstract deprecated interface GpsStatus.NmeaListener {
     method public abstract void onNmeaReceived(long, java.lang.String);
   }
 
@@ -20821,8 +20841,8 @@
     method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
     method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener);
     method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
-    method public boolean addNmeaListener(android.location.GnssNmeaListener);
-    method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
+    method public boolean addNmeaListener(android.location.OnNmeaMessageListener);
+    method public boolean addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler);
     method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
     method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
     method public void clearTestProviderEnabled(java.lang.String);
@@ -20838,15 +20858,15 @@
     method public boolean isProviderEnabled(java.lang.String);
     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);
-    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+    method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+    method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback, android.os.Handler);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback, android.os.Handler);
     method public deprecated void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
     method public deprecated void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
     method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener);
     method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener);
-    method public void removeNmeaListener(android.location.GnssNmeaListener);
+    method public void removeNmeaListener(android.location.OnNmeaMessageListener);
     method public void removeProximityAlert(android.app.PendingIntent);
     method public void removeTestProvider(java.lang.String);
     method public void removeUpdates(android.location.LocationListener);
@@ -20867,8 +20887,8 @@
     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 unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
-    method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+    method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
     field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
     field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -20931,6 +20951,10 @@
     field public static final int POWER_NONE = 200; // 0xc8
   }
 
+  public abstract interface OnNmeaMessageListener {
+    method public abstract void onNmeaMessage(java.lang.String, long);
+  }
+
   public abstract class SettingInjectorService extends android.app.Service {
     ctor public SettingInjectorService(java.lang.String);
     method public final android.os.IBinder onBind(android.content.Intent);
@@ -21295,7 +21319,7 @@
 
   public static abstract class AudioManager.AudioRecordingCallback {
     ctor public AudioManager.AudioRecordingCallback();
-    method public void onRecordConfigChanged(android.media.AudioRecordingConfiguration[]);
+    method public void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]);
   }
 
   public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -21556,7 +21580,6 @@
   }
 
   public abstract class DrmInitData {
-    ctor public DrmInitData();
     method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
   }
 
@@ -21811,8 +21834,8 @@
 
   public class MediaActionSound {
     ctor public MediaActionSound();
-    method public synchronized void load(int);
-    method public synchronized void play(int);
+    method public void load(int);
+    method public void play(int);
     method public void release();
     field public static final int FOCUS_COMPLETE = 1; // 0x1
     field public static final int SHUTTER_CLICK = 0; // 0x0
@@ -22067,12 +22090,13 @@
     field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
     field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
     field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
-    field public static final int DolbyVisionProfileDvavDen = 2; // 0x2
-    field public static final int DolbyVisionProfileDvavDer = 1; // 0x1
-    field public static final int DolbyVisionProfileDvheDen = 4; // 0x4
-    field public static final int DolbyVisionProfileDvheDer = 3; // 0x3
-    field public static final int DolbyVisionProfileDvheDtr = 5; // 0x5
-    field public static final int DolbyVisionProfileDvheStn = 6; // 0x6
+    field public static final int DolbyVisionProfileDvavPen = 2; // 0x2
+    field public static final int DolbyVisionProfileDvavPer = 1; // 0x1
+    field public static final int DolbyVisionProfileDvheDen = 8; // 0x8
+    field public static final int DolbyVisionProfileDvheDer = 4; // 0x4
+    field public static final int DolbyVisionProfileDvheDth = 64; // 0x40
+    field public static final int DolbyVisionProfileDvheDtr = 16; // 0x10
+    field public static final int DolbyVisionProfileDvheStn = 32; // 0x20
     field public static final int H263Level10 = 1; // 0x1
     field public static final int H263Level20 = 2; // 0x2
     field public static final int H263Level30 = 4; // 0x4
@@ -24624,6 +24648,7 @@
     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(java.lang.CharSequence);
     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);
@@ -25190,6 +25215,7 @@
     method public boolean isDefaultNetworkActive();
     method public static deprecated boolean isNetworkTypeValid(int);
     method public boolean isTetheringSupported();
+    method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
     method public void releaseNetworkRequest(android.app.PendingIntent);
@@ -31312,6 +31338,7 @@
     method public boolean isPowerSaveMode();
     method public boolean isScreenBrightnessBoosted();
     method public deprecated boolean isScreenOn();
+    method public boolean isSustainedPerformanceModeSupported();
     method public boolean isWakeLockLevelSupported(int);
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
     method public void reboot(java.lang.String);
@@ -31327,8 +31354,8 @@
     field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
     field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
     field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
-    field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
     field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
+    field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
     field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
     field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
     field public static final int USER_ACTIVITY_EVENT_TOUCH = 2; // 0x2
@@ -32009,7 +32036,6 @@
     method protected void onClick();
     method protected android.view.View onCreateView(android.view.ViewGroup);
     method public void onDependencyChanged(android.preference.Preference, boolean);
-    method protected void onDetachedFromActivity();
     method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
     method public void onParentChanged(android.preference.Preference, boolean);
     method protected void onPrepareForRemoval();
@@ -32671,7 +32697,6 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract void onConnected();
     method public abstract void onDisconnected();
-    method public final boolean onUnbind(android.content.Intent);
     method public final void updateRecommendations(java.util.List<android.printservice.recommendation.RecommendationInfo>);
   }
 
@@ -37154,6 +37179,7 @@
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onInterruptionFilterChanged(int);
     method public void onListenerConnected();
+    method public void onListenerDisconnected();
     method public void onListenerHintsChanged(int);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
@@ -39293,7 +39319,6 @@
     method public boolean isRinging();
     method public boolean isTtySupported();
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
-    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);
@@ -39412,6 +39437,7 @@
     field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
     field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
     field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+    field public static final java.lang.String KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL = "carrier_wfc_supports_wifi_only_bool";
     field public static final java.lang.String KEY_CDMA_DTMF_TONE_DELAY_INT = "cdma_dtmf_tone_delay_int";
     field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
     field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
@@ -40007,7 +40033,8 @@
     method public java.lang.String getDeviceSoftwareVersion();
     method public java.lang.String getGroupIdLevel1();
     method public java.lang.String getGroupIdLevel1(int);
-    method public java.lang.String getIccSimChallengeResponse(int, java.lang.String);
+    method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+    method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
     method public java.lang.String getLine1AlphaTag(int);
     method public java.lang.String getLine1Number();
     method public java.lang.String getLine1Number(int);
@@ -40097,6 +40124,13 @@
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
     field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
+    field public static final int APPTYPE_CSIM = 4; // 0x4
+    field public static final int APPTYPE_ISIM = 5; // 0x5
+    field public static final int APPTYPE_RUIM = 3; // 0x3
+    field public static final int APPTYPE_SIM = 1; // 0x1
+    field public static final int APPTYPE_USIM = 2; // 0x2
+    field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
+    field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
     field public static final int CALL_STATE_IDLE = 0; // 0x0
     field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
     field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -45018,6 +45052,7 @@
     method public boolean dispatchDragEvent(android.view.DragEvent);
     method protected void dispatchDraw(android.graphics.Canvas);
     method public void dispatchDrawableHotspotChanged(float, float);
+    method public void dispatchFinishTemporaryDetach();
     method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
     method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
     method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
@@ -45037,6 +45072,7 @@
     method protected void dispatchSetActivated(boolean);
     method protected void dispatchSetPressed(boolean);
     method protected void dispatchSetSelected(boolean);
+    method public void dispatchStartTemporaryDetach();
     method public void dispatchSystemUiVisibilityChanged(int);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
@@ -45249,6 +45285,7 @@
     method public boolean isSelected();
     method public boolean isShown();
     method public boolean isSoundEffectsEnabled();
+    method public final boolean isTemporarilyDetached();
     method public boolean isTextAlignmentResolved();
     method public boolean isTextDirectionResolved();
     method public boolean isVerticalFadingEdgeEnabled();
@@ -46836,8 +46873,6 @@
     method public void setVisibleToUser(boolean);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
-    field public static final java.lang.String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
-    field public static final java.lang.String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
     field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
     field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
     field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -47008,6 +47043,7 @@
 
   public final class AccessibilityWindowInfo implements android.os.Parcelable {
     method public int describeContents();
+    method public android.view.accessibility.AccessibilityNodeInfo getAnchor();
     method public void getBoundsInScreen(android.graphics.Rect);
     method public android.view.accessibility.AccessibilityWindowInfo getChild(int);
     method public int getChildCount();
@@ -47015,6 +47051,7 @@
     method public int getLayer();
     method public android.view.accessibility.AccessibilityWindowInfo getParent();
     method public android.view.accessibility.AccessibilityNodeInfo getRoot();
+    method public java.lang.CharSequence getTitle();
     method public int getType();
     method public boolean isAccessibilityFocused();
     method public boolean isActive();
@@ -48650,6 +48687,7 @@
     method public int getPackageId(android.content.res.Resources, java.lang.String);
     method public void invokeDrawGlFunctor(android.view.View, long, boolean);
     method public boolean isTraceTagEnabled();
+    method public java.lang.Runnable setDrawGlFunctionDetachedCallback(android.view.View, java.lang.Runnable);
     method public void setOnTraceEnabledChangeListener(android.webkit.WebViewDelegate.OnTraceEnabledChangeListener);
   }
 
@@ -48855,6 +48893,24 @@
     method public abstract boolean shouldDelayChildPressedState();
   }
 
+  public final class WebViewProviderInfo implements android.os.Parcelable {
+    ctor public WebViewProviderInfo(java.lang.String, java.lang.String, boolean, boolean, java.lang.String[]);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.webkit.WebViewProviderInfo> CREATOR;
+    field public final boolean availableByDefault;
+    field public final java.lang.String description;
+    field public final boolean isFallback;
+    field public final java.lang.String packageName;
+    field public final java.lang.String[] signatures;
+  }
+
+  public final class WebViewUpdateService {
+    method public static android.webkit.WebViewProviderInfo[] getAllWebViewPackages();
+    method public static java.lang.String getCurrentWebViewPackageName();
+    method public static android.webkit.WebViewProviderInfo[] getValidWebViewPackages();
+  }
+
 }
 
 package android.widget {
@@ -49341,7 +49397,7 @@
     method public long getMinDate();
     method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
     method public deprecated int getSelectedWeekBackgroundColor();
-    method public boolean getShowWeekNumber();
+    method public deprecated boolean getShowWeekNumber();
     method public deprecated int getShownWeekCount();
     method public deprecated int getUnfocusedMonthDateColor();
     method public int getWeekDayTextAppearance();
@@ -49358,7 +49414,7 @@
     method public deprecated void setSelectedDateVerticalBar(int);
     method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
     method public deprecated void setSelectedWeekBackgroundColor(int);
-    method public void setShowWeekNumber(boolean);
+    method public deprecated void setShowWeekNumber(boolean);
     method public deprecated void setShownWeekCount(int);
     method public deprecated void setUnfocusedMonthDateColor(int);
     method public void setWeekDayTextAppearance(int);
@@ -49505,21 +49561,21 @@
     ctor public DatePicker(android.content.Context, android.util.AttributeSet);
     ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
     ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
-    method public android.widget.CalendarView getCalendarView();
-    method public boolean getCalendarViewShown();
+    method public deprecated android.widget.CalendarView getCalendarView();
+    method public deprecated boolean getCalendarViewShown();
     method public int getDayOfMonth();
     method public int getFirstDayOfWeek();
     method public long getMaxDate();
     method public long getMinDate();
     method public int getMonth();
-    method public boolean getSpinnersShown();
+    method public deprecated boolean getSpinnersShown();
     method public int getYear();
     method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
-    method public void setCalendarViewShown(boolean);
+    method public deprecated void setCalendarViewShown(boolean);
     method public void setFirstDayOfWeek(int);
     method public void setMaxDate(long);
     method public void setMinDate(long);
-    method public void setSpinnersShown(boolean);
+    method public deprecated void setSpinnersShown(boolean);
     method public void updateDate(int, int, int);
   }
 
@@ -53091,6 +53147,10 @@
     method public static int compare(boolean, boolean);
     method public int compareTo(java.lang.Boolean);
     method public static boolean getBoolean(java.lang.String);
+    method public static int hashCode(boolean);
+    method public static boolean logicalAnd(boolean, boolean);
+    method public static boolean logicalOr(boolean, boolean);
+    method public static boolean logicalXor(boolean, boolean);
     method public static boolean parseBoolean(java.lang.String);
     method public static java.lang.String toString(boolean);
     method public static java.lang.Boolean valueOf(boolean);
@@ -53108,6 +53168,7 @@
     method public static java.lang.Byte decode(java.lang.String) throws java.lang.NumberFormatException;
     method public double doubleValue();
     method public float floatValue();
+    method public static int hashCode(byte);
     method public int intValue();
     method public long longValue();
     method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -53116,6 +53177,7 @@
     method public static java.lang.Byte valueOf(byte);
     method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Byte valueOf(java.lang.String) throws java.lang.NumberFormatException;
+    field public static final int BYTES = 1; // 0x1
     field public static final byte MAX_VALUE = 127; // 0x7f
     field public static final byte MIN_VALUE = -128; // 0xffffff80
     field public static final int SIZE = 8; // 0x8
@@ -53153,6 +53215,7 @@
     method public static int getNumericValue(int);
     method public static int getType(char);
     method public static int getType(int);
+    method public static int hashCode(char);
     method public static char highSurrogate(int);
     method public static boolean isAlphabetic(int);
     method public static boolean isBmpCodePoint(int);
@@ -53213,6 +53276,7 @@
     method public static char toUpperCase(char);
     method public static int toUpperCase(int);
     method public static java.lang.Character valueOf(char);
+    field public static final int BYTES = 2; // 0x2
     field public static final byte COMBINING_SPACING_MARK = 8; // 0x8
     field public static final byte CONNECTOR_PUNCTUATION = 23; // 0x17
     field public static final byte CONTROL = 15; // 0xf
@@ -53839,6 +53903,7 @@
     method public static int floatToIntBits(float);
     method public static int floatToRawIntBits(float);
     method public float floatValue();
+    method public static int hashCode(float);
     method public static float intBitsToFloat(int);
     method public int intValue();
     method public static boolean isFinite(float);
@@ -53847,11 +53912,15 @@
     method public static boolean isNaN(float);
     method public boolean isNaN();
     method public long longValue();
+    method public static float max(float, float);
+    method public static float min(float, float);
     method public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
+    method public static float sum(float, float);
     method public static java.lang.String toHexString(float);
     method public static java.lang.String toString(float);
     method public static java.lang.Float valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Float valueOf(float);
+    field public static final int BYTES = 4; // 0x4
     field public static final int MAX_EXPONENT = 127; // 0x7f
     field public static final float MAX_VALUE = 3.4028235E38f;
     field public static final int MIN_EXPONENT = -126; // 0xffffff82
@@ -54031,6 +54100,7 @@
     method public static java.lang.Long valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Long valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Long valueOf(long);
+    field public static final int BYTES = 8; // 0x8
     field public static final long MAX_VALUE = 9223372036854775807L; // 0x7fffffffffffffffL
     field public static final long MIN_VALUE = -9223372036854775808L; // 0x8000000000000000L
     field public static final int SIZE = 64; // 0x40
@@ -54044,6 +54114,8 @@
     method public static float abs(float);
     method public static double abs(double);
     method public static double acos(double);
+    method public static int addExact(int, int);
+    method public static long addExact(long, long);
     method public static double asin(double);
     method public static double atan(double);
     method public static double atan2(double, double);
@@ -54053,12 +54125,20 @@
     method public static float copySign(float, float);
     method public static double cos(double);
     method public static double cosh(double);
+    method public static int decrementExact(int);
+    method public static long decrementExact(long);
     method public static double exp(double);
     method public static double expm1(double);
     method public static double floor(double);
+    method public static int floorDiv(int, int);
+    method public static long floorDiv(long, long);
+    method public static int floorMod(int, int);
+    method public static long floorMod(long, long);
     method public static int getExponent(float);
     method public static int getExponent(double);
     method public static double hypot(double, double);
+    method public static int incrementExact(int);
+    method public static long incrementExact(long);
     method public static double log(double);
     method public static double log10(double);
     method public static double log1p(double);
@@ -54070,8 +54150,14 @@
     method public static long min(long, long);
     method public static float min(float, float);
     method public static double min(double, double);
+    method public static int multiplyExact(int, int);
+    method public static long multiplyExact(long, long);
+    method public static int negateExact(int);
+    method public static long negateExact(long);
     method public static double nextAfter(double, double);
     method public static float nextAfter(float, double);
+    method public static double nextDown(double);
+    method public static float nextDown(float);
     method public static double nextUp(double);
     method public static float nextUp(float);
     method public static double pow(double, double);
@@ -54086,9 +54172,12 @@
     method public static double sin(double);
     method public static double sinh(double);
     method public static double sqrt(double);
+    method public static int subtractExact(int, int);
+    method public static long subtractExact(long, long);
     method public static double tan(double);
     method public static double tanh(double);
     method public static double toDegrees(double);
+    method public static int toIntExact(long);
     method public static double toRadians(double);
     method public static double ulp(double);
     method public static float ulp(float);
@@ -54334,6 +54423,7 @@
     method public static java.lang.Short decode(java.lang.String) throws java.lang.NumberFormatException;
     method public double doubleValue();
     method public float floatValue();
+    method public static int hashCode(short);
     method public int intValue();
     method public long longValue();
     method public static short parseShort(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -54343,6 +54433,7 @@
     method public static java.lang.Short valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Short valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Short valueOf(short);
+    field public static final int BYTES = 2; // 0x2
     field public static final short MAX_VALUE = 32767; // 0x7fff
     field public static final short MIN_VALUE = -32768; // 0xffff8000
     field public static final int SIZE = 16; // 0x10
@@ -54370,6 +54461,8 @@
     method public static float abs(float);
     method public static double abs(double);
     method public static double acos(double);
+    method public static int addExact(int, int);
+    method public static long addExact(long, long);
     method public static double asin(double);
     method public static double atan(double);
     method public static double atan2(double, double);
@@ -54382,6 +54475,10 @@
     method public static double exp(double);
     method public static double expm1(double);
     method public static double floor(double);
+    method public static int floorDiv(int, int);
+    method public static long floorDiv(long, long);
+    method public static int floorMod(int, int);
+    method public static long floorMod(long, long);
     method public static int getExponent(float);
     method public static int getExponent(double);
     method public static double hypot(double, double);
@@ -54396,8 +54493,12 @@
     method public static long min(long, long);
     method public static float min(float, float);
     method public static double min(double, double);
+    method public static int multiplyExact(int, int);
+    method public static long multiplyExact(long, long);
     method public static double nextAfter(double, double);
     method public static float nextAfter(float, double);
+    method public static double nextDown(double);
+    method public static float nextDown(float);
     method public static double nextUp(double);
     method public static float nextUp(float);
     method public static double pow(double, double);
@@ -54412,9 +54513,12 @@
     method public static double sin(double);
     method public static double sinh(double);
     method public static double sqrt(double);
+    method public static int subtractExact(int, int);
+    method public static long subtractExact(long, long);
     method public static double tan(double);
     method public static double tanh(double);
     method public static double toDegrees(double);
+    method public static int toIntExact(long);
     method public static double toRadians(double);
     method public static double ulp(double);
     method public static float ulp(float);
@@ -60462,6 +60566,14 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
+    method public static void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
+    method public static void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
+    method public static void parallelPrefix(long[], java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(double[], java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(int[], java.util.function.IntBinaryOperator);
+    method public static void parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator);
     method public static void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
     method public static void parallelSetAll(int[], java.util.function.IntUnaryOperator);
     method public static void parallelSetAll(long[], java.util.function.IntToLongFunction);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 03cf8b0..95734c1 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -82,6 +82,67 @@
 
 }
 
+package android.location {
+
+  public final class GnssMeasurement implements android.os.Parcelable {
+    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+  }
+
+  public final class GnssMeasurementsEvent implements android.os.Parcelable {
+    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
+  }
+
+  public final class GnssNavigationMessageEvent implements android.os.Parcelable {
+    ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
+    method public int describeContents();
+    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_GNSS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
+  }
+
+  public static abstract class GnssNavigationMessageEvent.Callback {
+    ctor public GnssNavigationMessageEvent.Callback();
+    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
+    method public void onStatusChanged(int);
+  }
+
+  public abstract interface GnssNmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public final class GnssStatus {
+    method public int getNumSatellites();
+    method public boolean hasAlmanac(int);
+    method public boolean hasEphemeris(int);
+  }
+
+  public abstract class GnssStatusCallback {
+    ctor public GnssStatusCallback();
+    method public void onFirstFix(int);
+    method public void onSatelliteStatusChanged(android.location.GnssStatus);
+    method public void onStarted();
+    method public void onStopped();
+  }
+
+  public class LocationManager {
+    method public boolean addNmeaListener(android.location.GnssNmeaListener);
+    method public boolean addNmeaListener(android.location.GnssNmeaListener, 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);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+    method public void removeNmeaListener(android.location.GnssNmeaListener);
+    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
+    method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 92a466c..a190d95 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -71,6 +71,7 @@
     field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
     field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
     field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
+    field public static final java.lang.String GET_PASSWORD_PRIVILEGED = "android.permission.GET_PASSWORD_PRIVILEGED";
     field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";
     field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
     field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
@@ -2484,6 +2485,7 @@
     field public static final int Widget_Material_CompoundButton_CheckBox = 16974435; // 0x1030263
     field public static final int Widget_Material_CompoundButton_RadioButton = 16974436; // 0x1030264
     field public static final int Widget_Material_CompoundButton_Star = 16974437; // 0x1030265
+    field public static final int Widget_Material_CompoundButton_Switch = 16974554; // 0x10302da
     field public static final int Widget_Material_DatePicker = 16974438; // 0x1030266
     field public static final int Widget_Material_DropDownItem = 16974439; // 0x1030267
     field public static final int Widget_Material_DropDownItem_Spinner = 16974440; // 0x1030268
@@ -2518,6 +2520,7 @@
     field public static final int Widget_Material_Light_CompoundButton_CheckBox = 16974500; // 0x10302a4
     field public static final int Widget_Material_Light_CompoundButton_RadioButton = 16974501; // 0x10302a5
     field public static final int Widget_Material_Light_CompoundButton_Star = 16974502; // 0x10302a6
+    field public static final int Widget_Material_Light_CompoundButton_Switch = 16974555; // 0x10302db
     field public static final int Widget_Material_Light_DatePicker = 16974503; // 0x10302a7
     field public static final int Widget_Material_Light_DropDownItem = 16974504; // 0x10302a8
     field public static final int Widget_Material_Light_DropDownItem_Spinner = 16974505; // 0x10302a9
@@ -4912,6 +4915,7 @@
     field public static final int DEFAULT_LIGHTS = 4; // 0x4
     field public static final int DEFAULT_SOUND = 1; // 0x1
     field public static final int DEFAULT_VIBRATE = 2; // 0x2
+    field public static final java.lang.String EXTRA_ALLOW_GENERATED_REPLIES = "android.allowGeneratedReplies";
     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";
@@ -4920,12 +4924,14 @@
     field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
     field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
     field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
+    field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
     field public static final java.lang.String EXTRA_PEOPLE = "android.people";
     field public static final java.lang.String EXTRA_PICTURE = "android.picture";
     field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
     field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
     field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
     field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+    field public static final java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
     field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
     field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
     field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon";
@@ -4934,6 +4940,7 @@
     field public static final java.lang.String EXTRA_TEMPLATE = "android.template";
     field public static final java.lang.String EXTRA_TEXT = "android.text";
     field public static final java.lang.String EXTRA_TEXT_LINES = "android.textLines";
+    field public static final java.lang.String EXTRA_THREAD_TITLE = "android.threadTitle";
     field public static final java.lang.String EXTRA_TITLE = "android.title";
     field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
     field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
@@ -4976,7 +4983,7 @@
     field public int ledARGB;
     field public int ledOffMS;
     field public int ledOnMS;
-    field public int number;
+    field public deprecated int number;
     field public int priority;
     field public android.app.Notification publicVersion;
     field public android.net.Uri sound;
@@ -5023,11 +5030,13 @@
     method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder);
     method public java.lang.CharSequence getCancelLabel();
     method public java.lang.CharSequence getConfirmLabel();
+    method public boolean getHintContentIntentLaunchesActivity();
     method public java.lang.CharSequence getInProgressLabel();
     method public boolean isAvailableOffline();
     method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean);
     method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence);
     method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence);
+    method public android.app.Notification.Action.WearableExtender setHintContentIntentLaunchesActivity(boolean);
     method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
   }
 
@@ -5069,7 +5078,7 @@
     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);
+    method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setContentText(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
@@ -5086,7 +5095,7 @@
     method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
     method public android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
-    method public android.app.Notification.Builder setNumber(int);
+    method public deprecated android.app.Notification.Builder setNumber(int);
     method public android.app.Notification.Builder setOngoing(boolean);
     method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
     method public android.app.Notification.Builder setPriority(int);
@@ -5171,6 +5180,32 @@
     method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...);
   }
 
+  public static class Notification.MessagingStyle extends android.app.Notification.Style {
+    ctor public Notification.MessagingStyle(java.lang.CharSequence);
+    method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+    method public android.app.Notification.MessagingStyle addMessage(android.app.Notification.MessagingStyle.Message);
+    method public boolean getAllowGeneratedReplies();
+    method public java.lang.CharSequence getConversationTitle();
+    method public java.util.List<android.app.Notification.MessagingStyle.Message> getMessages();
+    method public java.lang.CharSequence getUserDisplayName();
+    method public android.app.Notification.MessagingStyle setAllowGeneratedReplies(boolean);
+    method public android.app.Notification.MessagingStyle setConversationTitle(java.lang.CharSequence);
+    field public static final int MAXIMUM_RETAINED_MESSAGES = 25; // 0x19
+  }
+
+  public static final class Notification.MessagingStyle.Message implements android.os.Parcelable {
+    ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+    method public int describeContents();
+    method public java.lang.String getDataMimeType();
+    method public android.net.Uri getDataUri();
+    method public java.lang.CharSequence getSender();
+    method public java.lang.CharSequence getText();
+    method public long getTimestamp();
+    method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.Notification.MessagingStyle.Message> CREATOR;
+  }
+
   public static abstract class Notification.Style {
     ctor public Notification.Style();
     method public android.app.Notification build();
@@ -5204,6 +5239,7 @@
     method public android.app.PendingIntent getDisplayIntent();
     method public int getGravity();
     method public boolean getHintAvoidBackgroundClipping();
+    method public boolean getHintContentIntentLaunchesActivity();
     method public boolean getHintHideIcon();
     method public int getHintScreenTimeout();
     method public boolean getHintShowBackgroundOnly();
@@ -5219,6 +5255,7 @@
     method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
     method public android.app.Notification.WearableExtender setGravity(int);
     method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
+    method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean);
     method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
     method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
     method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
@@ -5904,6 +5941,7 @@
     method public boolean isCallerApplicationRestrictionsManagingPackage();
     method public boolean isDeviceOwnerApp(java.lang.String);
     method public boolean isLockTaskPermitted(java.lang.String);
+    method public boolean isManagedProfile(android.content.ComponentName);
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isPackageSuspended(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean isProfileOwnerApp(java.lang.String);
@@ -5921,7 +5959,7 @@
     method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
     method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
-    method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
+    method public void setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException;
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -7886,6 +7924,7 @@
     method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
     method public void notifyChange(android.net.Uri, android.database.ContentObserver);
     method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
+    method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
     method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -7916,6 +7955,8 @@
     field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
     field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
     field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
+    field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
+    field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
     field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
     field public static final java.lang.String SCHEME_CONTENT = "content";
     field public static final java.lang.String SCHEME_FILE = "file";
@@ -8526,8 +8567,9 @@
     field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
     field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
-    field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED = "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+    field public static final java.lang.String ACTION_MANAGED_PROFILE_AVAILABLE = "android.intent.action.MANAGED_PROFILE_AVAILABLE";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
+    field public static final java.lang.String ACTION_MANAGED_PROFILE_UNAVAILABLE = "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
     field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
@@ -9925,6 +9967,7 @@
     field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80
     field public static final int PROTECTION_FLAG_PREINSTALLED = 1024; // 0x400
     field public static final int PROTECTION_FLAG_PRIVILEGED = 16; // 0x10
+    field public static final int PROTECTION_FLAG_SETUP = 2048; // 0x800
     field public static final deprecated int PROTECTION_FLAG_SYSTEM = 16; // 0x10
     field public static final int PROTECTION_FLAG_VERIFIER = 512; // 0x200
     field public static final int PROTECTION_MASK_BASE = 15; // 0xf
@@ -13513,6 +13556,7 @@
   public final class Sensor {
     method public int getFifoMaxEventCount();
     method public int getFifoReservedEventCount();
+    method public int getId();
     method public int getMaxDelay();
     method public float getMaximumRange();
     method public int getMinDelay();
@@ -13522,9 +13566,10 @@
     method public float getResolution();
     method public java.lang.String getStringType();
     method public int getType();
-    method public java.util.UUID getUuid();
     method public java.lang.String getVendor();
     method public int getVersion();
+    method public boolean isAdditionalInfoSupported();
+    method public boolean isDynamicSensor();
     method public boolean isWakeUpSensor();
     field public static final int REPORTING_MODE_CONTINUOUS = 0; // 0x0
     field public static final int REPORTING_MODE_ONE_SHOT = 2; // 0x2
@@ -13643,8 +13688,9 @@
     method public static void getRotationMatrixFromVector(float[], float[]);
     method public java.util.List<android.hardware.Sensor> getSensorList(int);
     method public deprecated int getSensors();
-    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
-    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback, android.os.Handler);
+    method public boolean isDynamicSensorDiscoverySupported();
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorCallback);
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorCallback, android.os.Handler);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
@@ -13653,7 +13699,7 @@
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
     method public static boolean remapCoordinateSystem(float[], int, int, float[]);
     method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
-    method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
+    method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorCallback);
     method public deprecated void unregisterListener(android.hardware.SensorListener);
     method public deprecated void unregisterListener(android.hardware.SensorListener, int);
     method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -13718,8 +13764,8 @@
     field public static final float STANDARD_GRAVITY = 9.80665f;
   }
 
-  public static abstract class SensorManager.DynamicSensorConnectionCallback {
-    ctor public SensorManager.DynamicSensorConnectionCallback();
+  public static abstract class SensorManager.DynamicSensorCallback {
+    ctor public SensorManager.DynamicSensorCallback();
     method public void onDynamicSensorConnected(android.hardware.Sensor);
     method public void onDynamicSensorDisconnected(android.hardware.Sensor);
   }
@@ -19260,7 +19306,7 @@
     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 int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
-    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
     field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
     field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
     field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
@@ -19286,15 +19332,15 @@
     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_GNSS_LOCATION_DISABLED = 2; // 0x2
-    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
-    field public static final int STATUS_READY = 1; // 0x1
   }
 
   public static abstract class GnssMeasurementsEvent.Callback {
     ctor public GnssMeasurementsEvent.Callback();
     method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
     method public void onStatusChanged(int);
+    field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
   }
 
   public final class GnssNavigationMessage implements android.os.Parcelable {
@@ -19331,36 +19377,24 @@
     field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
-  public final class GnssNavigationMessageEvent implements android.os.Parcelable {
-    ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
-    method public int describeContents();
-    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_GNSS_LOCATION_DISABLED = 2; // 0x2
+  public static abstract class GnssNavigationMessage.Callback {
+    ctor public GnssNavigationMessage.Callback();
+    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
+    method public void onStatusChanged(int);
+    field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract class GnssNavigationMessageEvent.Callback {
-    ctor public GnssNavigationMessageEvent.Callback();
-    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
-    method public void onStatusChanged(int);
-  }
-
-  public abstract interface GnssNmeaListener {
-    method public abstract void onNmeaReceived(long, java.lang.String);
-  }
-
   public final class GnssStatus {
     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 int getSatelliteCount();
     method public int getSvid(int);
-    method public boolean hasAlmanac(int);
-    method public boolean hasEphemeris(int);
+    method public boolean hasAlmanacData(int);
+    method public boolean hasEphemerisData(int);
     method public boolean usedInFix(int);
     field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
     field public static final int CONSTELLATION_GALILEO = 6; // 0x6
@@ -19371,15 +19405,15 @@
     field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
   }
 
-  public abstract class GnssStatusCallback {
-    ctor public GnssStatusCallback();
+  public static abstract class GnssStatus.Callback {
+    ctor public GnssStatus.Callback();
     method public void onFirstFix(int);
     method public void onSatelliteStatusChanged(android.location.GnssStatus);
     method public void onStarted();
     method public void onStopped();
   }
 
-  public final class GpsSatellite {
+  public final deprecated class GpsSatellite {
     method public float getAzimuth();
     method public float getElevation();
     method public int getPrn();
@@ -19389,7 +19423,7 @@
     method public boolean usedInFix();
   }
 
-  public final class GpsStatus {
+  public final deprecated class GpsStatus {
     method public int getMaxSatellites();
     method public java.lang.Iterable<android.location.GpsSatellite> getSatellites();
     method public int getTimeToFirstFix();
@@ -19399,11 +19433,11 @@
     field public static final int GPS_EVENT_STOPPED = 2; // 0x2
   }
 
-  public static abstract interface GpsStatus.Listener {
+  public static abstract deprecated interface GpsStatus.Listener {
     method public abstract void onGpsStatusChanged(int);
   }
 
-  public static abstract interface GpsStatus.NmeaListener {
+  public static abstract deprecated interface GpsStatus.NmeaListener {
     method public abstract void onNmeaReceived(long, java.lang.String);
   }
 
@@ -19465,8 +19499,8 @@
   public class LocationManager {
     method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener);
     method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
-    method public boolean addNmeaListener(android.location.GnssNmeaListener);
-    method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
+    method public boolean addNmeaListener(android.location.OnNmeaMessageListener);
+    method public boolean addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler);
     method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
     method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
     method public void clearTestProviderEnabled(java.lang.String);
@@ -19483,13 +19517,13 @@
     method public boolean isProviderEnabled(java.lang.String);
     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);
-    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+    method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+    method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback, android.os.Handler);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback, android.os.Handler);
     method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener);
     method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener);
-    method public void removeNmeaListener(android.location.GnssNmeaListener);
+    method public void removeNmeaListener(android.location.OnNmeaMessageListener);
     method public void removeProximityAlert(android.app.PendingIntent);
     method public void removeTestProvider(java.lang.String);
     method public void removeUpdates(android.location.LocationListener);
@@ -19508,8 +19542,8 @@
     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 unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
-    method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+    method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
     field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
     field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -19538,6 +19572,10 @@
     field public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
   }
 
+  public abstract interface OnNmeaMessageListener {
+    method public abstract void onNmeaMessage(java.lang.String, long);
+  }
+
   public abstract class SettingInjectorService extends android.app.Service {
     ctor public SettingInjectorService(java.lang.String);
     method public final android.os.IBinder onBind(android.content.Intent);
@@ -19871,7 +19909,7 @@
 
   public static abstract class AudioManager.AudioRecordingCallback {
     ctor public AudioManager.AudioRecordingCallback();
-    method public void onRecordConfigChanged(android.media.AudioRecordingConfiguration[]);
+    method public void onRecordingConfigChanged(android.media.AudioRecordingConfiguration[]);
   }
 
   public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -20129,7 +20167,6 @@
   }
 
   public abstract class DrmInitData {
-    ctor public DrmInitData();
     method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
   }
 
@@ -20384,8 +20421,8 @@
 
   public class MediaActionSound {
     ctor public MediaActionSound();
-    method public synchronized void load(int);
-    method public synchronized void play(int);
+    method public void load(int);
+    method public void play(int);
     method public void release();
     field public static final int FOCUS_COMPLETE = 1; // 0x1
     field public static final int SHUTTER_CLICK = 0; // 0x0
@@ -20640,12 +20677,13 @@
     field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
     field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
     field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
-    field public static final int DolbyVisionProfileDvavDen = 2; // 0x2
-    field public static final int DolbyVisionProfileDvavDer = 1; // 0x1
-    field public static final int DolbyVisionProfileDvheDen = 4; // 0x4
-    field public static final int DolbyVisionProfileDvheDer = 3; // 0x3
-    field public static final int DolbyVisionProfileDvheDtr = 5; // 0x5
-    field public static final int DolbyVisionProfileDvheStn = 6; // 0x6
+    field public static final int DolbyVisionProfileDvavPen = 2; // 0x2
+    field public static final int DolbyVisionProfileDvavPer = 1; // 0x1
+    field public static final int DolbyVisionProfileDvheDen = 8; // 0x8
+    field public static final int DolbyVisionProfileDvheDer = 4; // 0x4
+    field public static final int DolbyVisionProfileDvheDth = 64; // 0x40
+    field public static final int DolbyVisionProfileDvheDtr = 16; // 0x10
+    field public static final int DolbyVisionProfileDvheStn = 32; // 0x20
     field public static final int H263Level10 = 1; // 0x1
     field public static final int H263Level20 = 2; // 0x2
     field public static final int H263Level30 = 4; // 0x4
@@ -23507,6 +23545,7 @@
     method public boolean isActiveNetworkMetered();
     method public boolean isDefaultNetworkActive();
     method public static deprecated boolean isNetworkTypeValid(int);
+    method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
     method public void releaseNetworkRequest(android.app.PendingIntent);
@@ -29132,6 +29171,7 @@
     method public boolean isInteractive();
     method public boolean isPowerSaveMode();
     method public deprecated boolean isScreenOn();
+    method public boolean isSustainedPerformanceModeSupported();
     method public boolean isWakeLockLevelSupported(int);
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
     method public void reboot(java.lang.String);
@@ -29759,7 +29799,6 @@
     method protected void onClick();
     method protected android.view.View onCreateView(android.view.ViewGroup);
     method public void onDependencyChanged(android.preference.Preference, boolean);
-    method protected void onDetachedFromActivity();
     method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
     method public void onParentChanged(android.preference.Preference, boolean);
     method protected void onPrepareForRemoval();
@@ -34747,6 +34786,7 @@
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onInterruptionFilterChanged(int);
     method public void onListenerConnected();
+    method public void onListenerDisconnected();
     method public void onListenerHintsChanged(int);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
@@ -36683,7 +36723,6 @@
     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 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);
@@ -36795,6 +36834,7 @@
     field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
     field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
     field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+    field public static final java.lang.String KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL = "carrier_wfc_supports_wifi_only_bool";
     field public static final java.lang.String KEY_CDMA_DTMF_TONE_DELAY_INT = "cdma_dtmf_tone_delay_int";
     field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
     field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
@@ -37371,7 +37411,8 @@
     method public java.lang.String getDeviceSoftwareVersion();
     method public java.lang.String getGroupIdLevel1();
     method public java.lang.String getGroupIdLevel1(int);
-    method public java.lang.String getIccSimChallengeResponse(int, java.lang.String);
+    method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+    method public java.lang.String getIccAuthentication(int, int, int, java.lang.String);
     method public java.lang.String getLine1AlphaTag(int);
     method public java.lang.String getLine1Number();
     method public java.lang.String getLine1Number(int);
@@ -37440,6 +37481,13 @@
     field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+    field public static final int APPTYPE_CSIM = 4; // 0x4
+    field public static final int APPTYPE_ISIM = 5; // 0x5
+    field public static final int APPTYPE_RUIM = 3; // 0x3
+    field public static final int APPTYPE_SIM = 1; // 0x1
+    field public static final int APPTYPE_USIM = 2; // 0x2
+    field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
+    field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
     field public static final int CALL_STATE_IDLE = 0; // 0x0
     field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
     field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -42339,6 +42387,7 @@
     method public boolean dispatchDragEvent(android.view.DragEvent);
     method protected void dispatchDraw(android.graphics.Canvas);
     method public void dispatchDrawableHotspotChanged(float, float);
+    method public void dispatchFinishTemporaryDetach();
     method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
     method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
     method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
@@ -42358,6 +42407,7 @@
     method protected void dispatchSetActivated(boolean);
     method protected void dispatchSetPressed(boolean);
     method protected void dispatchSetSelected(boolean);
+    method public void dispatchStartTemporaryDetach();
     method public void dispatchSystemUiVisibilityChanged(int);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
@@ -42570,6 +42620,7 @@
     method public boolean isSelected();
     method public boolean isShown();
     method public boolean isSoundEffectsEnabled();
+    method public final boolean isTemporarilyDetached();
     method public boolean isTextAlignmentResolved();
     method public boolean isTextDirectionResolved();
     method public boolean isVerticalFadingEdgeEnabled();
@@ -44154,8 +44205,6 @@
     method public void setVisibleToUser(boolean);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
-    field public static final java.lang.String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
-    field public static final java.lang.String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT = "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
     field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
     field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
     field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -44326,6 +44375,7 @@
 
   public final class AccessibilityWindowInfo implements android.os.Parcelable {
     method public int describeContents();
+    method public android.view.accessibility.AccessibilityNodeInfo getAnchor();
     method public void getBoundsInScreen(android.graphics.Rect);
     method public android.view.accessibility.AccessibilityWindowInfo getChild(int);
     method public int getChildCount();
@@ -44333,6 +44383,7 @@
     method public int getLayer();
     method public android.view.accessibility.AccessibilityWindowInfo getParent();
     method public android.view.accessibility.AccessibilityNodeInfo getRoot();
+    method public java.lang.CharSequence getTitle();
     method public int getType();
     method public boolean isAccessibilityFocused();
     method public boolean isActive();
@@ -46324,7 +46375,7 @@
     method public long getMinDate();
     method public deprecated android.graphics.drawable.Drawable getSelectedDateVerticalBar();
     method public deprecated int getSelectedWeekBackgroundColor();
-    method public boolean getShowWeekNumber();
+    method public deprecated boolean getShowWeekNumber();
     method public deprecated int getShownWeekCount();
     method public deprecated int getUnfocusedMonthDateColor();
     method public int getWeekDayTextAppearance();
@@ -46341,7 +46392,7 @@
     method public deprecated void setSelectedDateVerticalBar(int);
     method public deprecated void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
     method public deprecated void setSelectedWeekBackgroundColor(int);
-    method public void setShowWeekNumber(boolean);
+    method public deprecated void setShowWeekNumber(boolean);
     method public deprecated void setShownWeekCount(int);
     method public deprecated void setUnfocusedMonthDateColor(int);
     method public void setWeekDayTextAppearance(int);
@@ -46488,21 +46539,21 @@
     ctor public DatePicker(android.content.Context, android.util.AttributeSet);
     ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
     ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
-    method public android.widget.CalendarView getCalendarView();
-    method public boolean getCalendarViewShown();
+    method public deprecated android.widget.CalendarView getCalendarView();
+    method public deprecated boolean getCalendarViewShown();
     method public int getDayOfMonth();
     method public int getFirstDayOfWeek();
     method public long getMaxDate();
     method public long getMinDate();
     method public int getMonth();
-    method public boolean getSpinnersShown();
+    method public deprecated boolean getSpinnersShown();
     method public int getYear();
     method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
-    method public void setCalendarViewShown(boolean);
+    method public deprecated void setCalendarViewShown(boolean);
     method public void setFirstDayOfWeek(int);
     method public void setMaxDate(long);
     method public void setMinDate(long);
-    method public void setSpinnersShown(boolean);
+    method public deprecated void setSpinnersShown(boolean);
     method public void updateDate(int, int, int);
   }
 
@@ -48336,6 +48387,7 @@
     method public android.view.Menu getMenu();
     method public java.lang.CharSequence getNavigationContentDescription();
     method public android.graphics.drawable.Drawable getNavigationIcon();
+    method public android.view.View getNavigationView();
     method public android.graphics.drawable.Drawable getOverflowIcon();
     method public int getPopupTheme();
     method public java.lang.CharSequence getSubtitle();
@@ -50074,6 +50126,10 @@
     method public static int compare(boolean, boolean);
     method public int compareTo(java.lang.Boolean);
     method public static boolean getBoolean(java.lang.String);
+    method public static int hashCode(boolean);
+    method public static boolean logicalAnd(boolean, boolean);
+    method public static boolean logicalOr(boolean, boolean);
+    method public static boolean logicalXor(boolean, boolean);
     method public static boolean parseBoolean(java.lang.String);
     method public static java.lang.String toString(boolean);
     method public static java.lang.Boolean valueOf(boolean);
@@ -50091,6 +50147,7 @@
     method public static java.lang.Byte decode(java.lang.String) throws java.lang.NumberFormatException;
     method public double doubleValue();
     method public float floatValue();
+    method public static int hashCode(byte);
     method public int intValue();
     method public long longValue();
     method public static byte parseByte(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50099,6 +50156,7 @@
     method public static java.lang.Byte valueOf(byte);
     method public static java.lang.Byte valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Byte valueOf(java.lang.String) throws java.lang.NumberFormatException;
+    field public static final int BYTES = 1; // 0x1
     field public static final byte MAX_VALUE = 127; // 0x7f
     field public static final byte MIN_VALUE = -128; // 0xffffff80
     field public static final int SIZE = 8; // 0x8
@@ -50136,6 +50194,7 @@
     method public static int getNumericValue(int);
     method public static int getType(char);
     method public static int getType(int);
+    method public static int hashCode(char);
     method public static char highSurrogate(int);
     method public static boolean isAlphabetic(int);
     method public static boolean isBmpCodePoint(int);
@@ -50196,6 +50255,7 @@
     method public static char toUpperCase(char);
     method public static int toUpperCase(int);
     method public static java.lang.Character valueOf(char);
+    field public static final int BYTES = 2; // 0x2
     field public static final byte COMBINING_SPACING_MARK = 8; // 0x8
     field public static final byte CONNECTOR_PUNCTUATION = 23; // 0x17
     field public static final byte CONTROL = 15; // 0xf
@@ -50822,6 +50882,7 @@
     method public static int floatToIntBits(float);
     method public static int floatToRawIntBits(float);
     method public float floatValue();
+    method public static int hashCode(float);
     method public static float intBitsToFloat(int);
     method public int intValue();
     method public static boolean isFinite(float);
@@ -50830,11 +50891,15 @@
     method public static boolean isNaN(float);
     method public boolean isNaN();
     method public long longValue();
+    method public static float max(float, float);
+    method public static float min(float, float);
     method public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
+    method public static float sum(float, float);
     method public static java.lang.String toHexString(float);
     method public static java.lang.String toString(float);
     method public static java.lang.Float valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Float valueOf(float);
+    field public static final int BYTES = 4; // 0x4
     field public static final int MAX_EXPONENT = 127; // 0x7f
     field public static final float MAX_VALUE = 3.4028235E38f;
     field public static final int MIN_EXPONENT = -126; // 0xffffff82
@@ -51014,6 +51079,7 @@
     method public static java.lang.Long valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Long valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Long valueOf(long);
+    field public static final int BYTES = 8; // 0x8
     field public static final long MAX_VALUE = 9223372036854775807L; // 0x7fffffffffffffffL
     field public static final long MIN_VALUE = -9223372036854775808L; // 0x8000000000000000L
     field public static final int SIZE = 64; // 0x40
@@ -51027,6 +51093,8 @@
     method public static float abs(float);
     method public static double abs(double);
     method public static double acos(double);
+    method public static int addExact(int, int);
+    method public static long addExact(long, long);
     method public static double asin(double);
     method public static double atan(double);
     method public static double atan2(double, double);
@@ -51036,12 +51104,20 @@
     method public static float copySign(float, float);
     method public static double cos(double);
     method public static double cosh(double);
+    method public static int decrementExact(int);
+    method public static long decrementExact(long);
     method public static double exp(double);
     method public static double expm1(double);
     method public static double floor(double);
+    method public static int floorDiv(int, int);
+    method public static long floorDiv(long, long);
+    method public static int floorMod(int, int);
+    method public static long floorMod(long, long);
     method public static int getExponent(float);
     method public static int getExponent(double);
     method public static double hypot(double, double);
+    method public static int incrementExact(int);
+    method public static long incrementExact(long);
     method public static double log(double);
     method public static double log10(double);
     method public static double log1p(double);
@@ -51053,8 +51129,14 @@
     method public static long min(long, long);
     method public static float min(float, float);
     method public static double min(double, double);
+    method public static int multiplyExact(int, int);
+    method public static long multiplyExact(long, long);
+    method public static int negateExact(int);
+    method public static long negateExact(long);
     method public static double nextAfter(double, double);
     method public static float nextAfter(float, double);
+    method public static double nextDown(double);
+    method public static float nextDown(float);
     method public static double nextUp(double);
     method public static float nextUp(float);
     method public static double pow(double, double);
@@ -51069,9 +51151,12 @@
     method public static double sin(double);
     method public static double sinh(double);
     method public static double sqrt(double);
+    method public static int subtractExact(int, int);
+    method public static long subtractExact(long, long);
     method public static double tan(double);
     method public static double tanh(double);
     method public static double toDegrees(double);
+    method public static int toIntExact(long);
     method public static double toRadians(double);
     method public static double ulp(double);
     method public static float ulp(float);
@@ -51317,6 +51402,7 @@
     method public static java.lang.Short decode(java.lang.String) throws java.lang.NumberFormatException;
     method public double doubleValue();
     method public float floatValue();
+    method public static int hashCode(short);
     method public int intValue();
     method public long longValue();
     method public static short parseShort(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -51326,6 +51412,7 @@
     method public static java.lang.Short valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
     method public static java.lang.Short valueOf(java.lang.String) throws java.lang.NumberFormatException;
     method public static java.lang.Short valueOf(short);
+    field public static final int BYTES = 2; // 0x2
     field public static final short MAX_VALUE = 32767; // 0x7fff
     field public static final short MIN_VALUE = -32768; // 0xffff8000
     field public static final int SIZE = 16; // 0x10
@@ -51353,6 +51440,8 @@
     method public static float abs(float);
     method public static double abs(double);
     method public static double acos(double);
+    method public static int addExact(int, int);
+    method public static long addExact(long, long);
     method public static double asin(double);
     method public static double atan(double);
     method public static double atan2(double, double);
@@ -51365,6 +51454,10 @@
     method public static double exp(double);
     method public static double expm1(double);
     method public static double floor(double);
+    method public static int floorDiv(int, int);
+    method public static long floorDiv(long, long);
+    method public static int floorMod(int, int);
+    method public static long floorMod(long, long);
     method public static int getExponent(float);
     method public static int getExponent(double);
     method public static double hypot(double, double);
@@ -51379,8 +51472,12 @@
     method public static long min(long, long);
     method public static float min(float, float);
     method public static double min(double, double);
+    method public static int multiplyExact(int, int);
+    method public static long multiplyExact(long, long);
     method public static double nextAfter(double, double);
     method public static float nextAfter(float, double);
+    method public static double nextDown(double);
+    method public static float nextDown(float);
     method public static double nextUp(double);
     method public static float nextUp(float);
     method public static double pow(double, double);
@@ -51395,9 +51492,12 @@
     method public static double sin(double);
     method public static double sinh(double);
     method public static double sqrt(double);
+    method public static int subtractExact(int, int);
+    method public static long subtractExact(long, long);
     method public static double tan(double);
     method public static double tanh(double);
     method public static double toDegrees(double);
+    method public static int toIntExact(long);
     method public static double toRadians(double);
     method public static double ulp(double);
     method public static float ulp(float);
@@ -57445,6 +57545,14 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
+    method public static void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
+    method public static void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
+    method public static void parallelPrefix(long[], java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(double[], java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(int[], java.util.function.IntBinaryOperator);
+    method public static void parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator);
     method public static void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
     method public static void parallelSetAll(int[], java.util.function.IntUnaryOperator);
     method public static void parallelSetAll(long[], java.util.function.IntToLongFunction);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 3f16bca..8c6abdc 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -84,6 +84,67 @@
 
 }
 
+package android.location {
+
+  public final class GnssMeasurement implements android.os.Parcelable {
+    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+  }
+
+  public final class GnssMeasurementsEvent implements android.os.Parcelable {
+    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
+  }
+
+  public final class GnssNavigationMessageEvent implements android.os.Parcelable {
+    ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
+    method public int describeContents();
+    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_GNSS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
+  }
+
+  public static abstract class GnssNavigationMessageEvent.Callback {
+    ctor public GnssNavigationMessageEvent.Callback();
+    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
+    method public void onStatusChanged(int);
+  }
+
+  public abstract interface GnssNmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public final class GnssStatus {
+    method public int getNumSatellites();
+    method public boolean hasAlmanac(int);
+    method public boolean hasEphemeris(int);
+  }
+
+  public abstract class GnssStatusCallback {
+    ctor public GnssStatusCallback();
+    method public void onFirstFix(int);
+    method public void onSatelliteStatusChanged(android.location.GnssStatus);
+    method public void onStarted();
+    method public void onStopped();
+  }
+
+  public class LocationManager {
+    method public boolean addNmeaListener(android.location.GnssNmeaListener);
+    method public boolean addNmeaListener(android.location.GnssNmeaListener, 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);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+    method public void removeNmeaListener(android.location.GnssNmeaListener);
+    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
+    method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 221b2d3..456be02 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -44,6 +44,7 @@
 import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.content.pm.IPackageManager;
+import android.content.pm.InstrumentationInfo;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
@@ -96,6 +97,7 @@
     private static final int STACK_BOUNDS_INSET = 10;
 
     private IActivityManager mAm;
+    private IPackageManager mPm;
 
     private int mStartFlags = 0;
     private boolean mWaitOption = false;
@@ -224,7 +226,8 @@
                 "    --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
                 "\n" +
                 "am instrument: start an Instrumentation.  Typically this target <COMPONENT>\n" +
-                "  is the form <TEST_PACKAGE>/<RUNNER_CLASS>.  Options are:\n" +
+                "  is the form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there \n" +
+                "  is only one instrumentation.  Options are:\n" +
                 "    -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with\n" +
                 "        [-e perf true] to generate raw output for performance measurements.\n" +
                 "    -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a\n" +
@@ -373,6 +376,12 @@
             throw new AndroidException("Can't connect to activity manager; is the system running?");
         }
 
+        mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+        if (mPm == null) {
+            System.err.println(NO_SYSTEM_ERROR_CODE);
+            throw new AndroidException("Can't connect to package manager; is the system running?");
+        }
+
         String op = nextArgRequired();
 
         if (op.equals("start")) {
@@ -570,13 +579,7 @@
                 if (intent.getComponent() != null) {
                     packageName = intent.getComponent().getPackageName();
                 } else {
-                    IPackageManager pm = IPackageManager.Stub.asInterface(
-                            ServiceManager.getService("package"));
-                    if (pm == null) {
-                        System.err.println("Error: Package manager not running; aborting");
-                        return;
-                    }
-                    List<ResolveInfo> activities = pm.queryIntentActivities(intent, mimeType, 0,
+                    List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
                             mUserId).getList();
                     if (activities == null || activities.size() <= 0) {
                         System.err.println("Error: Intent does not match any activities: "
@@ -813,8 +816,44 @@
         }
 
         String cnArg = nextArgRequired();
-        ComponentName cn = ComponentName.unflattenFromString(cnArg);
-        if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
+
+        ComponentName cn;
+        if (cnArg.contains("/")) {
+            cn = ComponentName.unflattenFromString(cnArg);
+            if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
+        } else {
+            List<InstrumentationInfo> infos = mPm.queryInstrumentation(null, 0).getList();
+
+            final int numInfos = infos == null ? 0: infos.size();
+            List<ComponentName> cns = new ArrayList<>();
+            for (int i = 0; i < numInfos; i++) {
+                InstrumentationInfo info = infos.get(i);
+
+                ComponentName c = new ComponentName(info.packageName, info.name);
+                if (cnArg.equals(info.packageName)) {
+                    cns.add(c);
+                }
+            }
+
+            if (cns.size() == 0) {
+                throw new IllegalArgumentException("No instrumentation found for: " + cnArg);
+            } else if (cns.size() == 1) {
+                cn = cns.get(0);
+            } else {
+                StringBuilder cnsStr = new StringBuilder();
+                final int numCns = cns.size();
+                for (int i = 0; i < numCns; i++) {
+                    cnsStr.append(cns.get(i).flattenToString());
+                    cnsStr.append(", ");
+                }
+
+                // Remove last ", "
+                cnsStr.setLength(cnsStr.length() - 2);
+
+                throw new IllegalArgumentException("Found multiple instrumentations: "
+                        + cnsStr.toString());
+            }
+        }
 
         InstrumentationWatcher watcher = null;
         UiAutomationConnection connection = null;
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index b208e43..d527ad7 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -74,6 +74,8 @@
             runGetPrimaryStorageUuid();
         } else if ("set-force-adoptable".equals(op)) {
             runSetForceAdoptable();
+        } else if ("set-sdcardfs".equals(op)) {
+            runSetSdcardfs();
         } else if ("partition".equals(op)) {
             runPartition();
         } else if ("mount".equals(op)) {
@@ -88,6 +90,8 @@
             runForget();
         } else if ("set-emulate-fbe".equals(op)) {
             runSetEmulateFbe();
+        } else if ("get-fbe-mode".equals(op)) {
+            runGetFbeMode();
         } else {
             throw new IllegalArgumentException();
         }
@@ -139,12 +143,38 @@
                 StorageManager.DEBUG_FORCE_ADOPTABLE);
     }
 
+    public void runSetSdcardfs() throws RemoteException {
+        final int mask = StorageManager.DEBUG_SDCARDFS_FORCE_ON
+                | StorageManager.DEBUG_SDCARDFS_FORCE_OFF;
+        switch (nextArg()) {
+            case "on":
+                mSm.setDebugFlags(StorageManager.DEBUG_SDCARDFS_FORCE_ON, mask);
+                break;
+            case "off":
+                mSm.setDebugFlags(StorageManager.DEBUG_SDCARDFS_FORCE_OFF, mask);
+                break;
+            case "default":
+                mSm.setDebugFlags(0, mask);
+                break;
+        }
+    }
+
     public void runSetEmulateFbe() throws RemoteException {
         final boolean emulateFbe = Boolean.parseBoolean(nextArg());
         mSm.setDebugFlags(emulateFbe ? StorageManager.DEBUG_EMULATE_FBE : 0,
                 StorageManager.DEBUG_EMULATE_FBE);
     }
 
+    public void runGetFbeMode() {
+        if (StorageManager.isFileEncryptedNativeOnly()) {
+            System.out.println("native");
+        } else if (StorageManager.isFileEncryptedEmulatedOnly()) {
+            System.out.println("emulated");
+        } else {
+            System.out.println("none");
+        }
+    }
+
     public void runPartition() throws RemoteException {
         final String diskId = nextArg();
         final String type = nextArg();
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index bf823f8..56728ad 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -600,11 +600,16 @@
      * Dispatch a gesture to the touch screen. Any gestures currently in progress, whether from
      * the user, this service, or another service, will be cancelled.
      * <p>
+     * The gesture will be dispatched as if it were performed directly on the screen by a user, so
+     * the events may be affected by features such as magnification and explore by touch.
+     * </p>
+     * <p>
      * <strong>Note:</strong> In order to dispatch gestures, your service
      * must declare the capability by setting the
      * {@link android.R.styleable#AccessibilityService_canPerformGestures}
      * property in its meta-data. For more information, see
      * {@link #SERVICE_META_DATA}.
+     * </p>
      *
      * @param gesture The gesture to dispatch
      * @param callback The object to call back when the status of the gesture is known. If
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 4019a56..ee03280 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -36,11 +36,11 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import com.android.internal.R;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import com.android.internal.R;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -319,6 +319,9 @@
      */
     public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x00000040;
 
+    /** {@hide} */
+    public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
+
     /**
      * The event types an {@link AccessibilityService} is interested in.
      * <p>
@@ -687,8 +690,9 @@
     }
 
     /** {@hide} */
-    public boolean isEncryptionAware() {
-        return mResolveInfo.serviceInfo.directBootAware;
+    public boolean isDirectBootAware() {
+        return ((flags & FLAG_FORCE_DIRECT_BOOT_AWARE) != 0)
+                || mResolveInfo.serviceInfo.directBootAware;
     }
 
     /**
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
index 7a0c89b..e18a34d 100644
--- a/core/java/android/accessibilityservice/GestureDescription.java
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -36,8 +36,7 @@
  * Accessibility services with the
  * {@link android.R.styleable#AccessibilityService_canPerformGestures} property can dispatch
  * gestures. This class describes those gestures. Gestures are made up of one or more strokes.
- * Gestures are immutable; use the {@code create} methods to get common gesture, or a
- * {@code Builder} to create a new one.
+ * Gestures are immutable once built.
  * <p>
  * Spatial dimensions throughout are in screen pixels. Time is measured in milliseconds.
  */
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index e520b40..7465ed9 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -2798,6 +2798,15 @@
         if (account == null) {
             throw new IllegalArgumentException("account is null");
         }
+
+        // Always include the calling package name. This just makes life easier
+        // down stream.
+        final Bundle optionsIn = new Bundle();
+        if (options != null) {
+            optionsIn.putAll(options);
+        }
+        optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
+
         return new AmsTask(activity, handler, callback) {
             @Override
             public void doWork() throws RemoteException {
@@ -2806,7 +2815,7 @@
                         account,
                         authTokenType,
                         activity != null,
-                        options);
+                        optionsIn);
             }
         }.start();
     }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 33621852..65d48e6 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -95,7 +95,7 @@
         }
         return sSystemReady;
     }
-    static boolean sSystemReady = false;
+    static volatile boolean sSystemReady = false;
 
     static public void broadcastStickyIntent(Intent intent, String permission, int userId) {
         broadcastStickyIntent(intent, permission, AppOpsManager.OP_NONE, userId);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5b94696..14c4fc6 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -91,6 +91,7 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 import android.util.SuperNotCalledException;
+import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.ThreadedRenderer;
 import android.view.View;
@@ -4632,7 +4633,21 @@
             }
 
             if (reportToActivity) {
-                cb.onConfigurationChanged(newConfig);
+                Configuration configToReport = newConfig;
+
+                if (cb instanceof ContextThemeWrapper) {
+                    // ContextThemeWrappers may override the configuration for that context.
+                    // We must check and apply any overrides defined.
+                    ContextThemeWrapper contextThemeWrapper = (ContextThemeWrapper) cb;
+                    final Configuration localOverrideConfig =
+                            contextThemeWrapper.getOverrideConfiguration();
+                    if (localOverrideConfig != null) {
+                        configToReport = new Configuration(newConfig);
+                        configToReport.updateFrom(localOverrideConfig);
+                    }
+                }
+
+                cb.onConfigurationChanged(configToReport);
             }
 
             if (activity != null) {
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index d3ca7ee..4a1aff7 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -239,9 +239,6 @@
     public void onResume(Activity activity, boolean isTopOfTask) {
         // After orientation change, the onResume can come in before the top Activity has
         // left, so if the Activity is not top, wait a second for the top Activity to exit.
-        if (mCalledExitCoordinator == null) {
-            return; // This is the called activity
-        }
         if (isTopOfTask || mEnterTransitionCoordinator == null) {
             restoreExitedViews();
             restoreReenteringViews();
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index cb2130c4..e4fff9d 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -905,10 +905,12 @@
 
         ListenerWrapper wrapper = null;
         synchronized (AlarmManager.class) {
-            final WeakReference<ListenerWrapper> wrapperRef;
-            wrapperRef = sWrappers.get(listener);
-            if (wrapperRef != null) {
-                wrapper = wrapperRef.get();
+            if (sWrappers != null) {
+                final WeakReference<ListenerWrapper> wrapperRef;
+                wrapperRef = sWrappers.get(listener);
+                if (wrapperRef != null) {
+                    wrapper = wrapperRef.get();
+                }
             }
         }
 
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 3a51aff..1e2cc26 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -146,6 +146,10 @@
                     op.removed.add(r);
                 }
             }
+            bse.mEnterAnim = op.enterAnim;
+            bse.mExitAnim = op.exitAnim;
+            bse.mPopEnterAnim = op.popEnterAnim;
+            bse.mPopExitAnim = op.popExitAnim;
             bse.addOp(op);
             num++;
         }
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 83dc506..bd55a06 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -58,7 +58,7 @@
      * @param context the parent context
      */
     public DatePickerDialog(@NonNull Context context) {
-        this(context, 0);
+        this(context, 0, null, Calendar.getInstance(), -1, -1, -1);
     }
 
     /**
@@ -70,24 +70,7 @@
      *                   {@code context}'s default alert dialog theme
      */
     public DatePickerDialog(@NonNull Context context, @StyleRes int themeResId) {
-        super(context, resolveDialogTheme(context, themeResId));
-
-        final Context themeContext = getContext();
-        final LayoutInflater inflater = LayoutInflater.from(themeContext);
-        final View view = inflater.inflate(R.layout.date_picker_dialog, null);
-        setView(view);
-
-        setButton(BUTTON_POSITIVE, themeContext.getString(R.string.ok), this);
-        setButton(BUTTON_NEGATIVE, themeContext.getString(R.string.cancel), this);
-        setButtonPanelLayoutHint(LAYOUT_HINT_SIDE);
-
-        final Calendar calendar = Calendar.getInstance();
-        final int year = calendar.get(Calendar.YEAR);
-        final int monthOfYear = calendar.get(Calendar.MONTH);
-        final int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
-        mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
-        mDatePicker.init(year, monthOfYear, dayOfMonth, this);
-        mDatePicker.setValidationCallback(mValidationCallback);
+        this(context, themeResId, null, Calendar.getInstance(), -1, -1, -1);
     }
 
     /**
@@ -104,7 +87,7 @@
      */
     public DatePickerDialog(@NonNull Context context, @Nullable OnDateSetListener listener,
             int year, int month, int dayOfMonth) {
-        this(context, 0, listener, year, month, dayOfMonth);
+        this(context, 0, listener, null, year, month, dayOfMonth);
     }
 
     /**
@@ -116,16 +99,40 @@
      *                   {@code context}'s default alert dialog theme
      * @param listener the listener to call when the user sets the date
      * @param year the initially selected year
-     * @param month the initially selected month (0-11 for compatibility with
-     *              {@link Calendar#MONTH})
+     * @param monthOfYear the initially selected month of the year (0-11 for
+     *                    compatibility with {@link Calendar#MONTH})
      * @param dayOfMonth the initially selected day of month (1-31, depending
      *                   on month)
      */
     public DatePickerDialog(@NonNull Context context, @StyleRes int themeResId,
-            @Nullable OnDateSetListener listener, int year, int month, int dayOfMonth) {
-        this(context, themeResId);
+            @Nullable OnDateSetListener listener, int year, int monthOfYear, int dayOfMonth) {
+        this(context, themeResId, listener, null, year, monthOfYear, dayOfMonth);
+    }
 
-        mDatePicker.updateDate(year, month, dayOfMonth);
+    private DatePickerDialog(@NonNull Context context, @StyleRes int themeResId,
+            @Nullable OnDateSetListener listener, @Nullable Calendar calendar, int year,
+            int monthOfYear, int dayOfMonth) {
+        super(context, resolveDialogTheme(context, themeResId));
+
+        final Context themeContext = getContext();
+        final LayoutInflater inflater = LayoutInflater.from(themeContext);
+        final View view = inflater.inflate(R.layout.date_picker_dialog, null);
+        setView(view);
+
+        setButton(BUTTON_POSITIVE, themeContext.getString(R.string.ok), this);
+        setButton(BUTTON_NEGATIVE, themeContext.getString(R.string.cancel), this);
+        setButtonPanelLayoutHint(LAYOUT_HINT_SIDE);
+
+        if (calendar != null) {
+            year = calendar.get(Calendar.YEAR);
+            monthOfYear = calendar.get(Calendar.MONTH);
+            dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
+        }
+
+        mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
+        mDatePicker.init(year, monthOfYear, dayOfMonth, this);
+        mDatePicker.setValidationCallback(mValidationCallback);
+
         mDateSetListener = listener;
     }
 
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 0bb1097..85a0403 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -16,6 +16,10 @@
 
 package android.app;
 
+import com.android.internal.R;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.policy.PhoneWindow;
+
 import android.annotation.CallSuper;
 import android.annotation.DrawableRes;
 import android.annotation.IdRes;
@@ -43,7 +47,6 @@
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.KeyEvent;
-import android.view.KeyboardShortcutGroup;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -57,12 +60,7 @@
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 
-import com.android.internal.R;
-import com.android.internal.app.WindowDecorActionBar;
-import com.android.internal.policy.PhoneWindow;
-
 import java.lang.ref.WeakReference;
-import java.util.List;
 
 /**
  * Base class for Dialogs.
@@ -94,11 +92,14 @@
         KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback {
     private static final String TAG = "Dialog";
     private Activity mOwnerActivity;
-    
+
+    private final WindowManager mWindowManager;
+
     final Context mContext;
-    final WindowManager mWindowManager;
-    Window mWindow;
+    final Window mWindow;
+
     View mDecor;
+
     private ActionBar mActionBar;
     /**
      * This field should be made private, so it is hidden from the SDK.
@@ -123,7 +124,7 @@
     private static final int CANCEL = 0x44;
     private static final int SHOW = 0x45;
 
-    private Handler mListenersHandler;
+    private final Handler mListenersHandler;
 
     private SearchEvent mSearchEvent;
 
@@ -131,11 +132,7 @@
 
     private int mActionModeTypeStarting = ActionMode.TYPE_PRIMARY;
 
-    private final Runnable mDismissAction = new Runnable() {
-        public void run() {
-            dismissDialog();
-        }
-    };
+    private final Runnable mDismissAction = this::dismissDialog;
 
     /**
      * Creates a dialog window that uses the default dialog theme.
@@ -198,14 +195,15 @@
      * @hide
      */
     @Deprecated
-    protected Dialog(@NonNull Context context, boolean cancelable, Message cancelCallback) {
+    protected Dialog(@NonNull Context context, boolean cancelable,
+            @Nullable Message cancelCallback) {
         this(context);
         mCancelable = cancelable;
         mCancelMessage = cancelCallback;
     }
 
     protected Dialog(@NonNull Context context, boolean cancelable,
-            OnCancelListener cancelListener) {
+            @Nullable OnCancelListener cancelListener) {
         this(context);
         mCancelable = cancelable;
         setOnCancelListener(cancelListener);
@@ -216,8 +214,7 @@
      * 
      * @return Context The Context used by the Dialog.
      */
-    @NonNull
-    public final Context getContext() {
+    public final @NonNull Context getContext() {
         return mContext;
     }
 
@@ -226,7 +223,7 @@
      *
      * @return The ActionBar attached to the dialog or null if no ActionBar is present.
      */
-    public ActionBar getActionBar() {
+    public @Nullable ActionBar getActionBar() {
         return mActionBar;
     }
 
@@ -236,7 +233,7 @@
      * 
      * @param activity The Activity that owns this dialog.
      */
-    public final void setOwnerActivity(Activity activity) {
+    public final void setOwnerActivity(@NonNull Activity activity) {
         mOwnerActivity = activity;
         
         getWindow().setVolumeControlStream(mOwnerActivity.getVolumeControlStream());
@@ -250,7 +247,7 @@
      * 
      * @return The Activity that owns this Dialog.
      */
-    public final Activity getOwnerActivity() {
+    public final @Nullable Activity getOwnerActivity() {
         return mOwnerActivity;
     }
     
@@ -316,13 +313,10 @@
             l = nl;
         }
 
-        try {
-            mWindowManager.addView(mDecor, l);
-            mShowing = true;
-    
-            sendShowMessage();
-        } finally {
-        }
+        mWindowManager.addView(mDecor, l);
+        mShowing = true;
+
+        sendShowMessage();
     }
     
     /**
@@ -388,7 +382,7 @@
         }
     }
 
-    // internal method to make sure mcreated is set properly without requiring
+    // internal method to make sure mCreated is set properly without requiring
     // users to call through to super in onCreate
     void dispatchOnCreate(Bundle savedInstanceState) {
         if (!mCreated) {
@@ -400,7 +394,7 @@
     /**
      * Similar to {@link Activity#onCreate}, you should initialize your dialog
      * in this method, including calling {@link #setContentView}.
-     * @param savedInstanceState If this dialog is being reinitalized after a
+     * @param savedInstanceState If this dialog is being reinitialized after a
      *     the hosting activity was previously shut down, holds the result from
      *     the most recent call to {@link #onSaveInstanceState}, or null if this
      *     is the first time.
@@ -433,7 +427,7 @@
      * state.
      * @return A bundle with the state of the dialog.
      */
-    public Bundle onSaveInstanceState() {
+    public @NonNull Bundle onSaveInstanceState() {
         Bundle bundle = new Bundle();
         bundle.putBoolean(DIALOG_SHOWING_TAG, mShowing);
         if (mCreated) {
@@ -452,7 +446,7 @@
      * @param savedInstanceState The state of the dialog previously saved by
      *     {@link #onSaveInstanceState()}.
      */
-    public void onRestoreInstanceState(Bundle savedInstanceState) {
+    public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
         final Bundle dialogHierarchyState = savedInstanceState.getBundle(DIALOG_HIERARCHY_TAG);
         if (dialogHierarchyState == null) {
             // dialog has never been shown, or onCreated, nothing to restore.
@@ -473,7 +467,7 @@
      * @return Window The current window, or null if the activity is not
      *         visual.
      */
-    public Window getWindow() {
+    public @Nullable Window getWindow() {
         return mWindow;
     }
 
@@ -486,7 +480,7 @@
      * @see #getWindow
      * @see android.view.Window#getCurrentFocus
      */
-    public View getCurrentFocus() {
+    public @Nullable View getCurrentFocus() {
         return mWindow != null ? mWindow.getCurrentFocus() : null;
     }
 
@@ -498,8 +492,7 @@
      * @param id the identifier of the view to find
      * @return The view with the given id or null.
      */
-    @Nullable
-    public View findViewById(@IdRes int id) {
+    public @Nullable View findViewById(@IdRes int id) {
         return mWindow.findViewById(id);
     }
 
@@ -520,19 +513,19 @@
      * 
      * @param view The desired content to display.
      */
-    public void setContentView(View view) {
+    public void setContentView(@NonNull View view) {
         mWindow.setContentView(view);
     }
 
     /**
      * Set the screen content to an explicit view.  This view is placed
      * directly into the screen's view hierarchy.  It can itself be a complex
-     * view hierarhcy.
+     * view hierarchy.
      * 
      * @param view The desired content to display.
      * @param params Layout parameters for the view.
      */
-    public void setContentView(View view, ViewGroup.LayoutParams params) {
+    public void setContentView(@NonNull View view, @Nullable ViewGroup.LayoutParams params) {
         mWindow.setContentView(view, params);
     }
 
@@ -543,7 +536,7 @@
      * @param view The desired content to display.
      * @param params Layout parameters for the view.
      */
-    public void addContentView(View view, ViewGroup.LayoutParams params) {
+    public void addContentView(@NonNull View view, @Nullable ViewGroup.LayoutParams params) {
         mWindow.addContentView(view, params);
     }
 
@@ -552,7 +545,7 @@
      * 
      * @param title The new text to display in the title.
      */
-    public void setTitle(CharSequence title) {
+    public void setTitle(@Nullable CharSequence title) {
         mWindow.setTitle(title);
         mWindow.getAttributes().setTitle(title);
     }
@@ -578,7 +571,8 @@
      * @see #onKeyUp
      * @see android.view.KeyEvent
      */
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
+    @Override
+    public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_BACK) {
             event.startTracking();
             return true;
@@ -592,7 +586,8 @@
      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
      * the event).
      */
-    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+    @Override
+    public boolean onKeyLongPress(int keyCode, @NonNull KeyEvent event) {
         return false;
     }
 
@@ -605,7 +600,8 @@
      * @see #onKeyDown
      * @see KeyEvent
      */
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
+    @Override
+    public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
                 && !event.isCanceled()) {
             onBackPressed();
@@ -619,7 +615,8 @@
      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
      * the event).
      */
-    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
+    @Override
+    public boolean onKeyMultiple(int keyCode, int repeatCount, @NonNull KeyEvent event) {
         return false;
     }
     
@@ -644,7 +641,7 @@
      * @param event Description of the key event.
      * @return True if the key shortcut was handled.
      */
-    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
+    public boolean onKeyShortcut(int keyCode, @NonNull KeyEvent event) {
         return false;
     }
 
@@ -658,7 +655,7 @@
      *         The default implementation will cancel the dialog when a touch
      *         happens outside of the window bounds.
      */
-    public boolean onTouchEvent(MotionEvent event) {
+    public boolean onTouchEvent(@NonNull MotionEvent event) {
         if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
             cancel();
             return true;
@@ -681,7 +678,7 @@
      * @return Return true if you have consumed the event, false if you haven't.
      * The default implementation always returns false.
      */
-    public boolean onTrackballEvent(MotionEvent event) {
+    public boolean onTrackballEvent(@NonNull MotionEvent event) {
         return false;
     }
 
@@ -710,25 +707,30 @@
      * @return Return true if you have consumed the event, false if you haven't.
      * The default implementation always returns false.
      */
-    public boolean onGenericMotionEvent(MotionEvent event) {
+    public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
         return false;
     }
 
+    @Override
     public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
         if (mDecor != null) {
             mWindowManager.updateViewLayout(mDecor, params);
         }
     }
 
+    @Override
     public void onContentChanged() {
     }
 
+    @Override
     public void onWindowFocusChanged(boolean hasFocus) {
     }
 
+    @Override
     public void onAttachedToWindow() {
     }
 
+    @Override
     public void onDetachedFromWindow() {
     }
 
@@ -747,7 +749,8 @@
      *
      * @return boolean Return true if this event was consumed.
      */
-    public boolean dispatchKeyEvent(KeyEvent event) {
+    @Override
+    public boolean dispatchKeyEvent(@NonNull KeyEvent event) {
         if ((mOnKeyListener != null) && (mOnKeyListener.onKey(this, event.getKeyCode(), event))) {
             return true;
         }
@@ -767,7 +770,8 @@
      * @param event The key shortcut event.
      * @return True if this event was consumed.
      */
-    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+    @Override
+    public boolean dispatchKeyShortcutEvent(@NonNull KeyEvent event) {
         if (mWindow.superDispatchKeyShortcutEvent(event)) {
             return true;
         }
@@ -784,7 +788,8 @@
      * 
      * @return boolean Return true if this event was consumed.
      */
-    public boolean dispatchTouchEvent(MotionEvent ev) {
+    @Override
+    public boolean dispatchTouchEvent(@NonNull MotionEvent ev) {
         if (mWindow.superDispatchTouchEvent(ev)) {
             return true;
         }
@@ -801,7 +806,8 @@
      * 
      * @return boolean Return true if this event was consumed.
      */
-    public boolean dispatchTrackballEvent(MotionEvent ev) {
+    @Override
+    public boolean dispatchTrackballEvent(@NonNull MotionEvent ev) {
         if (mWindow.superDispatchTrackballEvent(ev)) {
             return true;
         }
@@ -818,14 +824,16 @@
      *
      * @return boolean Return true if this event was consumed.
      */
-    public boolean dispatchGenericMotionEvent(MotionEvent ev) {
+    @Override
+    public boolean dispatchGenericMotionEvent(@NonNull MotionEvent ev) {
         if (mWindow.superDispatchGenericMotionEvent(ev)) {
             return true;
         }
         return onGenericMotionEvent(ev);
     }
 
-    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(@NonNull AccessibilityEvent event) {
         event.setClassName(getClass().getName());
         event.setPackageName(mContext.getPackageName());
 
@@ -840,6 +848,7 @@
     /**
      * @see Activity#onCreatePanelView(int)
      */
+    @Override
     public View onCreatePanelView(int featureId) {
         return null;
     }
@@ -847,7 +856,8 @@
     /**
      * @see Activity#onCreatePanelMenu(int, Menu)
      */
-    public boolean onCreatePanelMenu(int featureId, Menu menu) {
+    @Override
+    public boolean onCreatePanelMenu(int featureId, @NonNull Menu menu) {
         if (featureId == Window.FEATURE_OPTIONS_PANEL) {
             return onCreateOptionsMenu(menu);
         }
@@ -858,10 +868,10 @@
     /**
      * @see Activity#onPreparePanel(int, View, Menu)
      */
+    @Override
     public boolean onPreparePanel(int featureId, View view, Menu menu) {
         if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
-            boolean goforit = onPrepareOptionsMenu(menu);
-            return goforit && menu.hasVisibleItems();
+            return onPrepareOptionsMenu(menu) && menu.hasVisibleItems();
         }
         return true;
     }
@@ -869,6 +879,7 @@
     /**
      * @see Activity#onMenuOpened(int, Menu)
      */
+    @Override
     public boolean onMenuOpened(int featureId, Menu menu) {
         if (featureId == Window.FEATURE_ACTION_BAR) {
             mActionBar.dispatchMenuVisibilityChanged(true);
@@ -879,6 +890,7 @@
     /**
      * @see Activity#onMenuItemSelected(int, MenuItem)
      */
+    @Override
     public boolean onMenuItemSelected(int featureId, MenuItem item) {
         return false;
     }
@@ -886,6 +898,7 @@
     /**
      * @see Activity#onPanelClosed(int, Menu)
      */
+    @Override
     public void onPanelClosed(int featureId, Menu menu) {
         if (featureId == Window.FEATURE_ACTION_BAR) {
             mActionBar.dispatchMenuVisibilityChanged(false);
@@ -900,7 +913,7 @@
      * @see Activity#onCreateOptionsMenu(Menu)
      * @see #getOwnerActivity()
      */
-    public boolean onCreateOptionsMenu(Menu menu) {
+    public boolean onCreateOptionsMenu(@NonNull Menu menu) {
         return true;
     }
 
@@ -912,21 +925,21 @@
      * @see Activity#onPrepareOptionsMenu(Menu)
      * @see #getOwnerActivity()
      */
-    public boolean onPrepareOptionsMenu(Menu menu) {
+    public boolean onPrepareOptionsMenu(@NonNull Menu menu) {
         return true;
     }
 
     /**
      * @see Activity#onOptionsItemSelected(MenuItem)
      */
-    public boolean onOptionsItemSelected(MenuItem item) {
+    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
         return false;
     }
 
     /**
      * @see Activity#onOptionsMenuClosed(Menu)
      */
-    public void onOptionsMenuClosed(Menu menu) {
+    public void onOptionsMenuClosed(@NonNull Menu menu) {
     }
 
     /**
@@ -959,47 +972,49 @@
     /**
      * @see Activity#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)
      */
+    @Override
     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
     }
 
     /**
      * @see Activity#registerForContextMenu(View)
      */
-    public void registerForContextMenu(View view) {
+    public void registerForContextMenu(@NonNull View view) {
         view.setOnCreateContextMenuListener(this);
     }
     
     /**
      * @see Activity#unregisterForContextMenu(View)
      */
-    public void unregisterForContextMenu(View view) {
+    public void unregisterForContextMenu(@NonNull View view) {
         view.setOnCreateContextMenuListener(null);
     }
     
     /**
      * @see Activity#openContextMenu(View)
      */
-    public void openContextMenu(View view) {
+    public void openContextMenu(@NonNull View view) {
         view.showContextMenu();
     }
 
     /**
      * @see Activity#onContextItemSelected(MenuItem)
      */
-    public boolean onContextItemSelected(MenuItem item) {
+    public boolean onContextItemSelected(@NonNull MenuItem item) {
         return false;
     }
 
     /**
      * @see Activity#onContextMenuClosed(Menu)
      */
-    public void onContextMenuClosed(Menu menu) {
+    public void onContextMenuClosed(@NonNull Menu menu) {
     }
 
     /**
      * This hook is called when the user signals the desire to start a search.
      */
-    public boolean onSearchRequested(SearchEvent searchEvent) {
+    @Override
+    public boolean onSearchRequested(@NonNull SearchEvent searchEvent) {
         mSearchEvent = searchEvent;
         return onSearchRequested();
     }
@@ -1007,6 +1022,7 @@
     /**
      * This hook is called when the user signals the desire to start a search.
      */
+    @Override
     public boolean onSearchRequested() {
         final SearchManager searchManager = (SearchManager) mContext
                 .getSystemService(Context.SEARCH_SERVICE);
@@ -1029,13 +1045,10 @@
      * @return SearchEvent The SearchEvent that triggered the {@link
      *                    #onSearchRequested} callback.
      */
-    public final SearchEvent getSearchEvent() {
+    public final @Nullable SearchEvent getSearchEvent() {
         return mSearchEvent;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
         if (mActionBar != null && mActionModeTypeStarting == ActionMode.TYPE_PRIMARY) {
@@ -1044,9 +1057,6 @@
         return null;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
         try {
@@ -1063,6 +1073,7 @@
      * Note that if you override this method you should always call through
      * to the superclass implementation by calling super.onActionModeStarted(mode).
      */
+    @Override
     @CallSuper
     public void onActionModeStarted(ActionMode mode) {
         mActionMode = mode;
@@ -1074,6 +1085,7 @@
      * Note that if you override this method you should always call through
      * to the superclass implementation by calling super.onActionModeFinished(mode).
      */
+    @Override
     @CallSuper
     public void onActionModeFinished(ActionMode mode) {
         if (mode == mActionMode) {
@@ -1139,7 +1151,7 @@
      * Convenience for calling
      * {@link android.view.Window#setFeatureDrawableUri}.
      */
-    public final void setFeatureDrawableUri(int featureId, Uri uri) {
+    public final void setFeatureDrawableUri(int featureId, @Nullable Uri uri) {
         getWindow().setFeatureDrawableUri(featureId, uri);
     }
 
@@ -1147,7 +1159,7 @@
      * Convenience for calling
      * {@link android.view.Window#setFeatureDrawable(int, Drawable)}.
      */
-    public final void setFeatureDrawable(int featureId, Drawable drawable) {
+    public final void setFeatureDrawable(int featureId, @Nullable Drawable drawable) {
         getWindow().setFeatureDrawable(featureId, drawable);
     }
 
@@ -1159,7 +1171,7 @@
         getWindow().setFeatureDrawableAlpha(featureId, alpha);
     }
 
-    public LayoutInflater getLayoutInflater() {
+    public @NonNull LayoutInflater getLayoutInflater() {
         return getWindow().getLayoutInflater();
     }
 
@@ -1191,6 +1203,7 @@
      * Cancel the dialog.  This is essentially the same as calling {@link #dismiss()}, but it will
      * also call your {@link DialogInterface.OnCancelListener} (if registered).
      */
+    @Override
     public void cancel() {
         if (!mCanceled && mCancelMessage != null) {
             mCanceled = true;
@@ -1211,7 +1224,7 @@
      * 
      * @param listener The {@link DialogInterface.OnCancelListener} to use.
      */
-    public void setOnCancelListener(final OnCancelListener listener) {
+    public void setOnCancelListener(@Nullable OnCancelListener listener) {
         if (mCancelAndDismissTaken != null) {
             throw new IllegalStateException(
                     "OnCancelListener is already taken by "
@@ -1229,7 +1242,7 @@
      * @param msg The msg to send when the dialog is canceled.
      * @see #setOnCancelListener(android.content.DialogInterface.OnCancelListener)
      */
-    public void setCancelMessage(final Message msg) {
+    public void setCancelMessage(@Nullable Message msg) {
         mCancelMessage = msg;
     }
 
@@ -1237,7 +1250,7 @@
      * Set a listener to be invoked when the dialog is dismissed.
      * @param listener The {@link DialogInterface.OnDismissListener} to use.
      */
-    public void setOnDismissListener(final OnDismissListener listener) {
+    public void setOnDismissListener(@Nullable OnDismissListener listener) {
         if (mCancelAndDismissTaken != null) {
             throw new IllegalStateException(
                     "OnDismissListener is already taken by "
@@ -1254,7 +1267,7 @@
      * Sets a listener to be invoked when the dialog is shown.
      * @param listener The {@link DialogInterface.OnShowListener} to use.
      */
-    public void setOnShowListener(OnShowListener listener) {
+    public void setOnShowListener(@Nullable OnShowListener listener) {
         if (listener != null) {
             mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
         } else {
@@ -1266,13 +1279,13 @@
      * Set a message to be sent when the dialog is dismissed.
      * @param msg The msg to send when the dialog is dismissed.
      */
-    public void setDismissMessage(final Message msg) {
+    public void setDismissMessage(@Nullable Message msg) {
         mDismissMessage = msg;
     }
 
     /** @hide */
-    public boolean takeCancelAndDismissListeners(String msg, final OnCancelListener cancel,
-            final OnDismissListener dismiss) {
+    public boolean takeCancelAndDismissListeners(@Nullable String msg,
+            @Nullable OnCancelListener cancel, @Nullable OnDismissListener dismiss) {
         if (mCancelAndDismissTaken != null) {
             mCancelAndDismissTaken = null;
         } else if (mCancelMessage != null || mDismissMessage != null) {
@@ -1306,15 +1319,15 @@
     /**
      * Sets the callback that will be called if a key is dispatched to the dialog.
      */
-    public void setOnKeyListener(final OnKeyListener onKeyListener) {
+    public void setOnKeyListener(@Nullable OnKeyListener onKeyListener) {
         mOnKeyListener = onKeyListener;
     }
 
     private static final class ListenersHandler extends Handler {
-        private WeakReference<DialogInterface> mDialog;
+        private final WeakReference<DialogInterface> mDialog;
 
         public ListenersHandler(Dialog dialog) {
-            mDialog = new WeakReference<DialogInterface>(dialog);
+            mDialog = new WeakReference<>(dialog);
         }
 
         @Override
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index bb3c719..2a04c39 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1033,11 +1033,12 @@
      *                        false if it is not.
      */
     public void setUserVisibleHint(boolean isVisibleToUser) {
-        if (!mUserVisibleHint && isVisibleToUser && mState < STARTED && mFragmentManager != null) {
+        if (!mUserVisibleHint && isVisibleToUser && mState < STARTED
+                && mFragmentManager != null && isAdded()) {
             mFragmentManager.performPendingDeferredStart(this);
         }
         mUserVisibleHint = isVisibleToUser;
-        mDeferStart = !isVisibleToUser;
+        mDeferStart = mState < STARTED && !isVisibleToUser;
     }
 
     /**
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 13e8e75..4fca69a 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -206,7 +206,7 @@
             }
             results.putAll(mPerfMetrics);
         }
-        if (mUiAutomation != null) {
+        if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) {
             mUiAutomation.disconnect();
             mUiAutomation = null;
         }
@@ -1834,7 +1834,7 @@
     }
 
     /**
-     * Gets the {@link UiAutomation} instance.
+     * Gets the {@link UiAutomation} instance with no flags set.
      * <p>
      * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
      * work across application boundaries while the APIs exposed by the instrumentation
@@ -1848,25 +1848,21 @@
      * {@link Instrumentation} APIs. Using both APIs at the same time is not
      * a mistake by itself but a client has to be aware of the APIs limitations.
      * </p>
-     * @return The UI automation instance. If none exists, a new one is created with no flags set.
+     * <p>
+     * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different
+     * flags, the flags on that instance will be changed, and then it will be returned.
+     * </p>
+     * @return The UI automation instance.
      *
      * @see UiAutomation
      */
     public UiAutomation getUiAutomation() {
-        if ((mUiAutomation == null) || (mUiAutomation.isDestroyed())) {
-            return getUiAutomation(0);
-        }
-        return mUiAutomation;
+        return getUiAutomation(0);
     }
 
     /**
      * Gets the {@link UiAutomation} instance with flags set.
      * <p>
-     * <strong>Note:</strong> Only one UiAutomation can be obtained. Calling this method
-     * twice with different flags will fail unless the UiAutomation obtained in the first call
-     * is released with {@link UiAutomation#destroy()}.
-     * </p>
-     * <p>
      * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
      * work across application boundaries while the APIs exposed by the instrumentation
      * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
@@ -1879,6 +1875,10 @@
      * {@link Instrumentation} APIs. Using both APIs at the same time is not
      * a mistake by itself but a client has to be aware of the APIs limitations.
      * </p>
+     * <p>
+     * If a {@link UiAutomation} exists with different flags, the flags on that instance will be
+     * changed, and then it will be returned.
+     * </p>
      *
      * @param flags The flags to be passed to the UiAutomation, for example
      *        {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
@@ -1888,17 +1888,19 @@
      * @see UiAutomation
      */
     public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
+        boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed());
+
         if (mUiAutomationConnection != null) {
-            if ((mUiAutomation == null) || (mUiAutomation.isDestroyed())) {
+            if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) {
+                return mUiAutomation;
+            }
+            if (mustCreateNewAutomation) {
                 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
                         mUiAutomationConnection);
-                mUiAutomation.connect(flags);
             } else {
-                if (mUiAutomation.getFlags() != flags) {
-                    throw new RuntimeException(
-                            "Cannot get a UiAutomation with different flags from the existing one");
-                }
+                mUiAutomation.disconnect();
             }
+            mUiAutomation.connect(flags);
             return mUiAutomation;
         }
         return null;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8423de8..faefc9d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -174,6 +174,9 @@
      *   <li>Notification of an ongoing countdown timer should be stamped with the timer's end time.
      * </ul>
      *
+     * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this time is not shown
+     * anymore by default and must be opted into by using
+     * {@link android.app.Notification.Builder#setShowWhen(boolean)}
      */
     public long when;
 
@@ -206,6 +209,8 @@
      * {@link Notification.Builder} has displayed the number in the expanded notification view.
      *
      * If the number is 0 or negative, it is never shown.
+     *
+     * @deprecated this number is not shown anymore
      */
     public int number;
 
@@ -899,6 +904,34 @@
     public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
 
     /**
+     * {@link #extras} key: the username to be displayed for all messages sent by the user including
+     * direct replies
+     * {@link android.app.Notification.MessagingStyle} notification.
+     */
+    public static final String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
+
+    /**
+     * {@link #extras} key: a boolean describing whether the platform should automatically
+     * generate possible replies to
+     * {@link android.app.Notification.MessagingStyle.Message} objects provided by a
+     * {@link android.app.Notification.MessagingStyle} notification.
+     */
+    public static final String EXTRA_ALLOW_GENERATED_REPLIES = "android.allowGeneratedReplies";
+
+    /**
+     * {@link #extras} key: a {@link String} to be displayed as the title to a thread represented by
+     * a {@link android.app.Notification.MessagingStyle}
+     */
+    public static final String EXTRA_THREAD_TITLE = "android.threadTitle";
+
+    /**
+     * {@link #extras} key: an array of {@link android.app.Notification.MessagingStyle.Message}
+     * bundles provided by a
+     * {@link android.app.Notification.MessagingStyle} notification.
+     */
+    public static final String EXTRA_MESSAGES = "android.messages";
+
+    /**
      * {@link #extras} key: the user that built the notification.
      *
      * @hide
@@ -1205,6 +1238,7 @@
 
             // Flags bitwise-ored to mFlags
             private static final int FLAG_AVAILABLE_OFFLINE = 0x1;
+            private static final int FLAG_HINT_LAUNCHES_ACTIVITY = 1 << 1;
 
             // Default value for flags integer
             private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE;
@@ -1367,6 +1401,30 @@
             public CharSequence getCancelLabel() {
                 return mCancelLabel;
             }
+
+            /**
+             * Set a hint that this Action will launch an {@link Activity} directly, telling the
+             * platform that it can generate the appropriate transitions.
+             * @param hintLaunchesActivity {@code true} if the content intent will launch
+             * an activity and transitions should be generated, false otherwise.
+             * @return this object for method chaining
+             */
+            public WearableExtender setHintContentIntentLaunchesActivity(
+                    boolean hintLaunchesActivity) {
+                setFlag(FLAG_HINT_LAUNCHES_ACTIVITY, hintLaunchesActivity);
+                return this;
+            }
+
+            /**
+             * Get a hint that this Action will launch an {@link Activity} directly, telling the
+             * platform that it can generate the appropriate transitions
+             * @return {@code true} if the content intent will launch an activity and transitions
+             * should be generated, false otherwise. The default value is {@code false} if this was
+             * never set.
+             */
+            public boolean getHintContentIntentLaunchesActivity() {
+                return (mFlags & FLAG_HINT_LAUNCHES_ACTIVITY) != 0;
+            }
         }
     }
 
@@ -2133,7 +2191,9 @@
 
             if (toAdopt == null) {
                 mN = new Notification();
-                mN.extras.putBoolean(EXTRA_SHOW_WHEN, true);
+                if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+                    mN.extras.putBoolean(EXTRA_SHOW_WHEN, true);
+                }
                 mN.priority = PRIORITY_DEFAULT;
                 mN.visibility = VISIBILITY_PRIVATE;
             } else {
@@ -2183,8 +2243,10 @@
 
         /**
          * Add a timestamp pertaining to the notification (usually the time the event occurred).
-         * It will be shown in the notification content view by default; use
-         * {@link #setShowWhen(boolean) setShowWhen} to control this.
+         *
+         * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this time is not
+         * shown anymore by default and must be opted into by using
+         * {@link android.app.Notification.Builder#setShowWhen(boolean)}
          *
          * @see Notification#when
          */
@@ -2196,6 +2258,8 @@
         /**
          * Control whether the timestamp set with {@link #setWhen(long) setWhen} is shown
          * in the content view.
+         * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this defaults to
+         * {@code false}. For earlier apps, the default is {@code true}.
          */
         public Builder setShowWhen(boolean show) {
             mN.extras.putBoolean(EXTRA_SHOW_WHEN, show);
@@ -2304,9 +2368,22 @@
         }
 
         /**
-         * Set the third line of text in the platform notification template.
-         * Don't use if you're also using {@link #setProgress(int, int, boolean)}; they occupy the
-         * same location in the standard template.
+         * This provides some additional information that is displayed in the notification. No
+         * guarantees are given where exactly it is displayed.
+         *
+         * <p>This information should only be provided if it provides an essential
+         * benefit to the understanding of the notification. The more text you provide the
+         * less readable it becomes. For example, an email client should only provide the account
+         * name here if more than one email account has been added.</p>
+         *
+         * <p>As of {@link android.os.Build.VERSION_CODES#N} this information is displayed in the
+         * notification header area.
+         *
+         * On Android versions before {@link android.os.Build.VERSION_CODES#N}
+         * this will be shown in the third line of text in the platform notification template.
+         * You should not be using {@link #setProgress(int, int, boolean)} at the
+         * same time on those versions; they occupy the same place.
+         * </p>
          */
         public Builder setSubText(CharSequence text) {
             mN.extras.putCharSequence(EXTRA_SUB_TEXT, safeCharSequence(text));
@@ -2345,6 +2422,8 @@
          * Set the large number at the right-hand side of the notification.  This is
          * equivalent to setContentInfo, although it might show the number in a different
          * font size for readability.
+         *
+         * @deprecated this number is not shown anywhere anymore
          */
         public Builder setNumber(int number) {
             mN.number = number;
@@ -2356,6 +2435,10 @@
          *
          * The platform template will draw this on the last line of the notification, at the far
          * right (to the right of a smallIcon if it has been placed there).
+         *
+         * @deprecated use {@link #setSubText(CharSequence)} instead to set a text in the header.
+         * For legacy apps targeting a version below {@link android.os.Build.VERSION_CODES#N} this
+         * field will still show up, but the subtext will take precedence.
          */
         public Builder setContentInfo(CharSequence info) {
             mN.extras.putCharSequence(EXTRA_INFO_TEXT, safeCharSequence(info));
@@ -3009,10 +3092,8 @@
             contentView.setBoolean(R.id.notification_header, "setExpanded", false);
             contentView.setTextViewText(R.id.app_name_text, null);
             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.sub_text_divider, View.GONE);
-            contentView.setViewVisibility(R.id.content_info_divider, View.GONE);
+            contentView.setViewVisibility(R.id.header_text, View.GONE);
+            contentView.setViewVisibility(R.id.header_text_divider, View.GONE);
             contentView.setViewVisibility(R.id.time_divider, View.GONE);
             contentView.setImageViewIcon(R.id.profile_badge, null);
             contentView.setViewVisibility(R.id.profile_badge, View.GONE);
@@ -3112,39 +3193,12 @@
         private void bindNotificationHeader(RemoteViews contentView) {
             bindSmallIcon(contentView);
             bindHeaderAppName(contentView);
-            bindHeaderSubText(contentView);
-            bindContentInfo(contentView);
+            bindHeaderText(contentView);
             bindHeaderChronometerAndTime(contentView);
             bindExpandButton(contentView);
             bindProfileBadge(contentView);
         }
 
-        private void bindContentInfo(RemoteViews contentView) {
-            boolean visible = false;
-            if (mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) {
-                contentView.setTextViewText(R.id.header_content_info,
-                        processLegacyText(mN.extras.getCharSequence(EXTRA_INFO_TEXT)));
-                contentView.setViewVisibility(R.id.header_content_info, View.VISIBLE);
-                visible = true;
-            } else if (mN.number > 0) {
-                final int tooBig = mContext.getResources().getInteger(
-                        R.integer.status_bar_notification_info_maxnum);
-                if (mN.number > tooBig) {
-                    contentView.setTextViewText(R.id.header_content_info, processLegacyText(
-                            mContext.getResources().getString(
-                                    R.string.status_bar_notification_info_overflow)));
-                } else {
-                    contentView.setTextViewText(R.id.header_content_info,
-                            processLegacyText(String.valueOf(mN.number)));
-                }
-                contentView.setViewVisibility(R.id.header_content_info, View.VISIBLE);
-                visible = true;
-            }
-            if (visible) {
-                contentView.setViewVisibility(R.id.content_info_divider, View.VISIBLE);
-            }
-        }
-
         private void bindExpandButton(RemoteViews contentView) {
             contentView.setDrawableParameters(R.id.expand_button, false, -1, resolveContrastColor(),
                     PorterDuff.Mode.SRC_ATOP, -1);
@@ -3169,17 +3223,22 @@
             }
         }
 
-        private void bindHeaderSubText(RemoteViews contentView) {
-            CharSequence subText = mN.extras.getCharSequence(EXTRA_SUB_TEXT);
-            if (subText == null && mStyle != null && mStyle.mSummaryTextSet
+        private void bindHeaderText(RemoteViews contentView) {
+            CharSequence headerText = mN.extras.getCharSequence(EXTRA_SUB_TEXT);
+            if (headerText == null && mStyle != null && mStyle.mSummaryTextSet
                     && mStyle.hasSummaryInHeader()) {
-                subText = mStyle.mSummaryText;
+                headerText = mStyle.mSummaryText;
             }
-            if (subText != null) {
+            if (headerText == null
+                    && mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
+                    && mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) {
+                headerText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
+            }
+            if (headerText != null) {
                 // TODO: Remove the span entirely to only have the string with propper formating.
-                contentView.setTextViewText(R.id.header_sub_text, processLegacyText(subText));
-                contentView.setViewVisibility(R.id.header_sub_text, View.VISIBLE);
-                contentView.setViewVisibility(R.id.sub_text_divider, View.VISIBLE);
+                contentView.setTextViewText(R.id.header_text, processLegacyText(headerText));
+                contentView.setViewVisibility(R.id.header_text, View.VISIBLE);
+                contentView.setViewVisibility(R.id.header_text_divider, View.VISIBLE);
             }
         }
 
@@ -3529,7 +3588,8 @@
         private static Class<? extends Style> getNotificationStyleClass(String templateClass) {
             Class<? extends Style>[] classes = new Class[] {
                     BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class,
-                    DecoratedCustomViewStyle.class, DecoratedMediaCustomViewStyle.class };
+                    DecoratedCustomViewStyle.class, DecoratedMediaCustomViewStyle.class,
+                    MessagingStyle.class };
             for (Class<? extends Style> innerClass : classes) {
                 if (templateClass.equals(innerClass.getName())) {
                     return innerClass;
@@ -4126,6 +4186,350 @@
     }
 
     /**
+     * Helper class for generating large-format notifications that include multiple back-and-forth
+     * messages of varying types between any number of people.
+     *
+     * <br>
+     * If the platform does not provide large-format notifications, this method has no effect. The
+     * user will always see the normal notification view.
+     * <br>
+     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like
+     * so:
+     * <pre class="prettyprint">
+     *
+     * Notification noti = new Notification.Builder()
+     *     .setContentTitle(&quot;2 new messages wtih &quot; + sender.toString())
+     *     .setContentText(subject)
+     *     .setSmallIcon(R.drawable.new_message)
+     *     .setLargeIcon(aBitmap)
+     *     .setStyle(new Notification.MessagingStyle(resources.getString(R.string.reply_name))
+     *         .addMessage(messages[0].getText(), messages[0].getTime(), messages[0].getSender())
+     *         .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getSender()))
+     *     .build();
+     * </pre>
+     */
+    public static class MessagingStyle extends Style {
+
+        /**
+         * The maximum number of messages that will be retained in the Notification itself (the
+         * number displayed is up to the platform).
+         */
+        public static final int MAXIMUM_RETAINED_MESSAGES = 25;
+
+        CharSequence mUserDisplayName;
+        CharSequence mConversationTitle;
+        boolean mAllowGeneratedReplies = true;
+        ArrayList<Message> mMessages = new ArrayList<>();
+
+        MessagingStyle() {
+        }
+
+        /**
+         * @param userDisplayName the name to be displayed for any replies sent by the user before the
+         * posting app reposts the notification with those messages after they've been actually
+         * sent and in previous messages sent by the user added in
+         * {@link #addMessage(Notification.MessagingStyle.Message)}
+         */
+        public MessagingStyle(CharSequence userDisplayName) {
+            mUserDisplayName = userDisplayName;
+        }
+
+        /**
+         * Returns the name to be displayed for any replies sent by the user
+         */
+        public CharSequence getUserDisplayName() {
+            return mUserDisplayName;
+        }
+
+        /**
+         * Set whether the platform should automatically generate possible replies from messages.
+         * @param allowGeneratedReplies {@code true} to allow generated replies, {@code false}
+         * otherwise
+         * @return this object for method chaining
+         * The default value is {@code true}
+         */
+        public MessagingStyle setAllowGeneratedReplies(boolean allowGeneratedReplies) {
+            mAllowGeneratedReplies = allowGeneratedReplies;
+            return this;
+        }
+
+        /**
+         * Return whether the platform should automatically generate possible replies from messages.
+         */
+        public boolean getAllowGeneratedReplies() {
+            return mAllowGeneratedReplies;
+        }
+
+        /**
+         * Sets the title to be displayed on this conversation. This should only be used for
+         * group messaging and left unset for one-on-one conversations.
+         * @param conversationTitle
+         * @return this object for method chaining.
+         */
+        public MessagingStyle setConversationTitle(CharSequence conversationTitle) {
+            mConversationTitle = conversationTitle;
+            return this;
+        }
+
+        /**
+         * Return the title to be displayed on this conversation. Can be <code>null</code> and
+         * should be for one-on-one conversations
+         */
+        public CharSequence getConversationTitle() {
+            return mConversationTitle;
+        }
+
+        /**
+         * Adds a message for display by this notification. Convenience call for a simple
+         * {@link Message} in {@link #addMessage(Notification.MessagingStyle.Message)}.
+         * @param text A {@link CharSequence} to be displayed as the message content
+         * @param timestamp Time at which the message arrived
+         * @param sender A {@link CharSequence} to be used for displaying the name of the
+         * sender. Should be <code>null</code> for messages by the current user, in which case
+         * the platform will insert {@link #getUserDisplayName()}.
+         * Should be unique amongst all individuals in the conversation, and should be
+         * consistent during re-posts of the notification.
+         *
+         * @see Message#Message(CharSequence, long, CharSequence)
+         *
+         * @return this object for method chaining
+         */
+        public MessagingStyle addMessage(CharSequence text, long timestamp, CharSequence sender) {
+            mMessages.add(new Message(text, timestamp, sender));
+            if (mMessages.size() > MAXIMUM_RETAINED_MESSAGES) {
+                mMessages.remove(0);
+            }
+            return this;
+        }
+
+        /**
+         * Adds a {@link Message} for display in this notification.
+         * @param message The {@link Message} to be displayed
+         * @return this object for method chaining
+         */
+        public MessagingStyle addMessage(Message message) {
+            mMessages.add(message);
+            if (mMessages.size() > MAXIMUM_RETAINED_MESSAGES) {
+                mMessages.remove(0);
+            }
+            return this;
+        }
+
+        /**
+         * Gets the list of {@code Message} objects that represent the notification
+         */
+        public List<Message> getMessages() {
+            return mMessages;
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public void addExtras(Bundle extras) {
+            super.addExtras(extras);
+            if (mUserDisplayName != null) {
+                extras.putCharSequence(EXTRA_SELF_DISPLAY_NAME, mUserDisplayName);
+            }
+            if (mConversationTitle != null) {
+                extras.putCharSequence(EXTRA_THREAD_TITLE, mConversationTitle);
+            }
+            extras.putBoolean(EXTRA_ALLOW_GENERATED_REPLIES, mAllowGeneratedReplies);
+            if (!mMessages.isEmpty()) {
+                extras.putParcelableArrayList(EXTRA_MESSAGES, mMessages);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        protected void restoreFromExtras(Bundle extras) {
+            super.restoreFromExtras(extras);
+
+            mMessages.clear();
+            mUserDisplayName = extras.getString(EXTRA_SELF_DISPLAY_NAME);
+            mConversationTitle = extras.getString(EXTRA_THREAD_TITLE);
+            mAllowGeneratedReplies = extras.getBoolean(EXTRA_ALLOW_GENERATED_REPLIES,
+                    mAllowGeneratedReplies);
+            List<Message> messages = extras.getParcelableArrayList(EXTRA_MESSAGES);
+            if (messages != null) {
+                mMessages.addAll(messages);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public RemoteViews makeBigContentView() {
+            // TODO handset to write implementation
+            RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
+
+            return contentView;
+        }
+
+        public static final class Message implements Parcelable {
+
+            private final CharSequence mText;
+            private final long mTimestamp;
+            private final CharSequence mSender;
+
+            private String mDataMimeType;
+            private Uri mDataUri;
+
+            /**
+             * Constructor
+             * @param text A {@link CharSequence} to be displayed as the message content
+             * @param timestamp Time at which the message arrived
+             * @param sender A {@link CharSequence} to be used for displaying the name of the
+             * sender. Should be <code>null</code> for messages by the current user, in which case
+             * the platform will insert {@link MessagingStyle#getUserDisplayName()}.
+             * Should be unique amongst all individuals in the conversation, and should be
+             * consistent during re-posts of the notification.
+             */
+            public Message(CharSequence text, long timestamp, CharSequence sender){
+                mText = text;
+                mTimestamp = timestamp;
+                mSender = sender;
+            }
+
+            /**
+             * Sets a binary blob of data and an associated MIME type for a message. In the case
+             * where the platform doesn't support the MIME type, the original text provided in the
+             * constructor will be used.
+             * @param dataMimeType The MIME type of the content. See
+             * <a href="{@docRoot}notifications/messaging.html"> for the list of supported MIME
+             * types on Android and Android Wear.
+             * @param dataUri The uri containing the content whose type is given by the MIME type.
+             * <p class="note">
+             * <ol>
+             *   <li>Notification Listeners including the System UI need permission to access the
+             *       data the Uri points to. The recommended ways to do this are:</li>
+             *   <li>Store the data in your own ContentProvider, making sure that other apps have
+             *       the correct permission to access your provider. The preferred mechanism for
+             *       providing access is to use per-URI permissions which are temporary and only
+             *       grant access to the receiving application. An easy way to create a
+             *       ContentProvider like this is to use the FileProvider helper class.</li>
+             *   <li>Use the system MediaStore. The MediaStore is primarily aimed at video, audio
+             *       and image MIME types, however beginning with Android 3.0 (API level 11) it can
+             *       also store non-media types (see MediaStore.Files for more info). Files can be
+             *       inserted into the MediaStore using scanFile() after which a content:// style
+             *       Uri suitable for sharing is passed to the provided onScanCompleted() callback.
+             *       Note that once added to the system MediaStore the content is accessible to any
+             *       app on the device.</li>
+             * </ol>
+             * @return this object for method chaining
+             */
+            public Message setData(String dataMimeType, Uri dataUri) {
+                mDataMimeType = dataMimeType;
+                mDataUri = dataUri;
+                return this;
+            }
+
+            private Message(Parcel in) {
+                if (in.readInt() != 0) {
+                    mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+                } else {
+                    mText = null;
+                }
+                mTimestamp = in.readLong();
+                if (in.readInt() != 0) {
+                    mSender = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+                } else {
+                    mSender = null;
+                }
+                if (in.readInt() != 0) {
+                    mDataMimeType = in.readString();
+                }
+                if (in.readInt() != 0) {
+                    mDataUri = in.readParcelable(Uri.class.getClassLoader());
+                }
+            }
+
+            /**
+             * Get the text to be used for this message, or the fallback text if a type and content
+             * Uri have been set
+             */
+            public CharSequence getText() {
+                return mText;
+            }
+
+            /**
+             * Get the time at which this message arrived
+             */
+            public long getTimestamp() {
+                return mTimestamp;
+            }
+
+            /**
+             * Get the text used to display the contact's name in the messaging experience
+             */
+            public CharSequence getSender() {
+                return mSender;
+            }
+
+            /**
+             * Get the MIME type of the data pointed to by the Uri
+             */
+            public String getDataMimeType() {
+                return mDataMimeType;
+            }
+
+            /**
+             * Get the the Uri pointing to the content of the message. Can be null, in which case
+             * {@see #getText()} is used.
+             */
+            public Uri getDataUri() {
+                return mDataUri;
+            }
+
+            @Override
+            public int describeContents() {
+                return 0;
+            }
+
+            @Override
+            public void writeToParcel(Parcel out, int flags) {
+                if (mText != null) {
+                    out.writeInt(1);
+                    TextUtils.writeToParcel(mText, out, flags);
+                } else {
+                    out.writeInt(0);
+                }
+                out.writeLong(mTimestamp);
+                if (mSender != null) {
+                    out.writeInt(1);
+                    TextUtils.writeToParcel(mSender, out, flags);
+                } else {
+                    out.writeInt(0);
+                }
+                if (mDataMimeType != null) {
+                    out.writeInt(1);
+                    out.writeString(mDataMimeType);
+                } else {
+                    out.writeInt(0);
+                }
+                if (mDataUri != null) {
+                    out.writeInt(1);
+                    out.writeParcelable(mDataUri, flags);
+                } else {
+                    out.writeInt(0);
+                }
+            }
+
+            public static final Parcelable.Creator<Message> CREATOR =
+                    new Parcelable.Creator<Message>() {
+                        public Message createFromParcel(Parcel in) {
+                            return new Message(in);
+                        }
+                        public Message[] newArray(int size) {
+                            return new Message[size];
+                        }
+                    };
+        }
+    }
+
+    /**
      * Helper class for generating large-format notifications that include a list of (up to 5) strings.
      *
      * Here's how you'd set the <code>InboxStyle</code> on a notification:
@@ -4863,6 +5267,7 @@
         private static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2;
         private static final int FLAG_START_SCROLL_BOTTOM = 1 << 3;
         private static final int FLAG_HINT_AVOID_BACKGROUND_CLIPPING = 1 << 4;
+        private static final int FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY = 1 << 6;
 
         // Default value for flags integer
         private static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE;
@@ -5429,6 +5834,29 @@
             return mHintScreenTimeout;
         }
 
+        /**
+         * Set a hint that this notification's content intent will launch an {@link Activity}
+         * directly, telling the platform that it can generate the appropriate transitions.
+         * @param hintContentIntentLaunchesActivity {@code true} if the content intent will launch
+         * an activity and transitions should be generated, false otherwise.
+         * @return this object for method chaining
+         */
+        public WearableExtender setHintContentIntentLaunchesActivity(
+                boolean hintContentIntentLaunchesActivity) {
+            setFlag(FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY, hintContentIntentLaunchesActivity);
+            return this;
+        }
+
+        /**
+         * Get a hint that this notification's content intent will launch an {@link Activity}
+         * directly, telling the platform that it can generate the appropriate transitions
+         * @return {@code true} if the content intent will launch an activity and transitions should
+         * be generated, false otherwise. The default value is {@code false} if this was never set.
+         */
+        public boolean getHintContentIntentLaunchesActivity() {
+            return (mFlags & FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY) != 0;
+        }
+
         private void setFlag(int mask, boolean value) {
             if (value) {
                 mFlags |= mask;
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 0d4729d..47bff644 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -153,25 +153,31 @@
 
     /**
      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
-     *     Normal interruption filter.
+     *     Normal interruption filter - no notifications are suppressed.
      */
     public static final int INTERRUPTION_FILTER_ALL = 1;
 
     /**
      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
-     *     Priority interruption filter.
+     *     Priority interruption filter - all notifications are suppressed except those that match
+     *     the priority criteria. Some audio streams are muted. See
+     *     {@link Policy#priorityCallSenders}, {@link Policy#priorityCategories},
+     *     {@link Policy#priorityMessageSenders} to define or query this criteria. Users can
+     *     additionally specify packages that can bypass this interruption filter.
      */
     public static final int INTERRUPTION_FILTER_PRIORITY = 2;
 
     /**
      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
-     *     No interruptions filter.
+     *     No interruptions filter - all notifications are suppressed and all audio streams (except
+     *     those used for phone calls) and vibrations are muted.
      */
     public static final int INTERRUPTION_FILTER_NONE = 3;
 
     /**
      * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
-     *     Alarms only interruption filter.
+     *     Alarms only interruption filter - all notifications except those of category
+     *     {@link Notification#CATEGORY_ALARM} are suppressed. Some audio streams are muted.
      */
     public static final int INTERRUPTION_FILTER_ALARMS = 4;
 
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 3f22385..4c4f128 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -440,6 +440,11 @@
                 compatInfo);
         classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
 
+        if (DEBUG) {
+            Slog.d(TAG, "createBaseActivityResources activity=" + activityToken
+                    + " with key=" + key);
+        }
+
         synchronized (this) {
             final ActivityResources activityResources = getOrCreateActivityResourcesStructLocked(
                     activityToken);
@@ -651,6 +656,16 @@
                 activityResources.overrideConfig.setToDefaults();
             }
 
+            if (DEBUG) {
+                Throwable here = new Throwable();
+                here.fillInStackTrace();
+                Slog.d(TAG, "updating resources override for activity=" + activityToken
+                        + " from oldConfig=" + Configuration.resourceQualifierString(oldConfig)
+                        + " to newConfig="
+                        + Configuration.resourceQualifierString(activityResources.overrideConfig),
+                        here);
+            }
+
             final boolean activityHasOverrideConfig =
                     !activityResources.overrideConfig.equals(Configuration.EMPTY);
 
@@ -692,9 +707,15 @@
                         oldKey.mOverlayDirs, oldKey.mLibDirs, oldKey.mDisplayId,
                         rebasedOverrideConfig, oldKey.mCompatInfo);
 
+                if (DEBUG) {
+                    Slog.d(TAG, "rebasing ref=" + resources + " from oldKey=" + oldKey
+                            + " to newKey=" + newKey);
+                }
+
                 ResourcesImpl resourcesImpl = findResourcesImplForKeyLocked(newKey);
                 if (resourcesImpl == null) {
                     resourcesImpl = createResourcesImpl(newKey);
+                    mResourceImpls.put(newKey, new WeakReference<>(resourcesImpl));
                 }
 
                 if (resourcesImpl != resources.getImpl()) {
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 276f774..2c1ee8e 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -36,6 +36,7 @@
 import android.view.WindowContentFrameStats;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.IAccessibilityManager;
+
 import libcore.io.IoUtils;
 
 import java.io.FileOutputStream;
@@ -77,6 +78,7 @@
 
     private int mOwningUid;
 
+    @Override
     public void connect(IAccessibilityServiceClient client, int flags) {
         if (client == null) {
             throw new IllegalArgumentException("Client cannot be null!");
@@ -326,11 +328,12 @@
             int flags) {
         IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
                 ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
-        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
+        final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
         info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
         info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
         info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
-                | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
+                | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS
+                | AccessibilityServiceInfo.FLAG_FORCE_DIRECT_BOOT_AWARE;
         info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
                 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
                 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 656c7ff..96757bb 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2185,9 +2185,6 @@
      * Force a new device unlock password (the password needed to access the entire device, not for
      * individual accounts) on the user. This takes effect immediately.
      * <p>
-     * Calling this from a managed profile that shares the password with the owner profile will
-     * throw a security exception.
-     * <p>
      * <em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for
      * device admins that are not device owner and not profile owner.
      * The password can now only be changed if there is currently no password set.  Device owner
@@ -2201,10 +2198,10 @@
      * case the currently active quality will be increased to match.
      * <p>
      * Calling with a null or empty password will clear any existing PIN, pattern or password if the
-     * current password constraints allow it. <em>Note: This will not
-     * work in {@link android.os.Build.VERSION_CODES#N} and later for device admins that are not
-     * device owner and not profile owner.  Once set, the password cannot be changed to null or
-     * empty, except by device owner or profile owner.</em>
+     * current password constraints allow it. <em>Note: This will not work in
+     * {@link android.os.Build.VERSION_CODES#N} and later for managed profiles, or for device admins
+     * that are not device owner or profile owner.  Once set, the password cannot be changed to null
+     * or empty except by these admins.</em>
      * <p>
      * The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call this method; if it has
@@ -2291,6 +2288,23 @@
     }
 
     /**
+     * Returns maximum time to lock that applied by all profiles in this user. We do this because we
+     * do not have a separate timeout to lock for work challenge only.
+     *
+     * @hide
+     */
+    public long getMaximumTimeToLockForUserAndProfiles(int userHandle) {
+        if (mService != null) {
+            try {
+                return mService.getMaximumTimeToLockForUserAndProfiles(userHandle);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return 0;
+    }
+
+    /**
      * Make the device lock immediately, as if the lock screen timeout has expired at the point of
      * this call.
      * <p>
@@ -2980,17 +2994,21 @@
      * @return {@code true} if the package is set as always-on VPN controller; {@code false}
      *         otherwise.
      * @throws SecurityException if {@code admin} is not a device or a profile owner.
+     * @throws NameNotFoundException if {@code vpnPackage} is not installed.
+     * @throws UnsupportedOperationException if {@code vpnPackage} exists but does not support being
+     *         set as always-on, or if always-on VPN is not available.
      */
-    public boolean setAlwaysOnVpnPackage(@NonNull ComponentName admin,
-            @Nullable String vpnPackage) {
+    public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage)
+            throws NameNotFoundException, UnsupportedOperationException {
         if (mService != null) {
             try {
-                return mService.setAlwaysOnVpnPackage(admin, vpnPackage);
+                if (!mService.setAlwaysOnVpnPackage(admin, vpnPackage)) {
+                    throw new NameNotFoundException(vpnPackage);
+                }
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
         }
-        return false;
     }
 
     /**
@@ -4159,6 +4177,10 @@
      * The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call this method;
      * if not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set the configuration for
+     * the parent profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param target Component name of the agent to be enabled.
@@ -4179,7 +4201,7 @@
             @NonNull ComponentName target, PersistableBundle configuration) {
         if (mService != null) {
             try {
-                mService.setTrustAgentConfiguration(admin, target, configuration);
+                mService.setTrustAgentConfiguration(admin, target, configuration, mParentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -4190,6 +4212,10 @@
      * Gets configuration for the given trust agent based on aggregating all calls to
      * {@link #setTrustAgentConfiguration(ComponentName, ComponentName, PersistableBundle)} for
      * all device admins.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to retrieve the configuration set
+     * on the parent profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with. If null,
      * this function returns a list of configurations for all admins that declare
@@ -4210,7 +4236,8 @@
             @NonNull ComponentName agent, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getTrustAgentConfiguration(admin, agent, userHandle);
+                return mService.getTrustAgentConfiguration(admin, agent, userHandle,
+                        mParentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -5654,10 +5681,9 @@
     }
 
     /**
-     * @hide
      * Return if this user is a managed profile of another user. An admin can become the profile
      * owner of a managed profile with {@link #ACTION_PROVISION_MANAGED_PROFILE} and of a managed
-     * user with {@link #ACTION_PROVISION_MANAGED_USER}.
+     * user with {@link #createAndManageUser}
      * @param admin Which profile owner this request is associated with.
      * @return if this user is a managed profile of another user.
      */
@@ -5853,8 +5879,43 @@
     /**
      * Called by the profile owner of a managed profile to obtain a {@link DevicePolicyManager}
      * whose calls act on the parent profile.
-     * <p>
-     * Note only some methods will work on the parent Manager.
+     *
+     * <p>The following methods are supported for the parent instance, all other methods will
+     * throw a SecurityException when called on the parent instance:
+     * <ul>
+     * <li>{@link #getPasswordQuality}</li>
+     * <li>{@link #setPasswordQuality}</li>
+     * <li>{@link #getPasswordMinimumLength}</li>
+     * <li>{@link #setPasswordMinimumLength}</li>
+     * <li>{@link #getPasswordMinimumUpperCase}</li>
+     * <li>{@link #setPasswordMinimumUpperCase}</li>
+     * <li>{@link #getPasswordMinimumLowerCase}</li>
+     * <li>{@link #setPasswordMinimumLowerCase}</li>
+     * <li>{@link #getPasswordMinimumLetters}</li>
+     * <li>{@link #setPasswordMinimumLetters}</li>
+     * <li>{@link #getPasswordMinimumNumeric}</li>
+     * <li>{@link #setPasswordMinimumNumeric}</li>
+     * <li>{@link #getPasswordMinimumSymbols}</li>
+     * <li>{@link #setPasswordMinimumSymbols}</li>
+     * <li>{@link #getPasswordMinimumNonLetter}</li>
+     * <li>{@link #setPasswordMinimumNonLetter}</li>
+     * <li>{@link #getPasswordHistoryLength}</li>
+     * <li>{@link #setPasswordHistoryLength}</li>
+     * <li>{@link #getPasswordExpirationTimeout}</li>
+     * <li>{@link #setPasswordExpirationTimeout}</li>
+     * <li>{@link #getPasswordExpiration}</li>
+     * <li>{@link #isActivePasswordSufficient}</li>
+     * <li>{@link #getCurrentFailedPasswordAttempts}</li>
+     * <li>{@link #getMaximumFailedPasswordsForWipe}</li>
+     * <li>{@link #setMaximumFailedPasswordsForWipe}</li>
+     * <li>{@link #getMaximumTimeToLock}</li>
+     * <li>{@link #setMaximumTimeToLock}</li>
+     * <li>{@link #lockNow}</li>
+     * <li>{@link #getKeyguardDisabledFeatures}</li>
+     * <li>{@link #setKeyguardDisabledFeatures}</li>
+     * <li>{@link #getTrustAgentConfiguration}</li>
+     * <li>{@link #setTrustAgentConfiguration}</li>
+     * </ul>
      *
      * @return a new instance of {@link DevicePolicyManager} that acts on the parent profile.
      * @throws SecurityException if {@code admin} is not a profile owner.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 6ee56aa..6df1038 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -80,6 +80,7 @@
 
     void setMaximumTimeToLock(in ComponentName who, long timeMs, boolean parent);
     long getMaximumTimeToLock(in ComponentName who, int userHandle, boolean parent);
+    long getMaximumTimeToLockForUserAndProfiles(int userHandle);
 
     void lockNow(boolean parent);
 
@@ -228,9 +229,9 @@
     boolean getBluetoothContactSharingDisabledForUser(int userId);
 
     void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent,
-            in PersistableBundle args);
+            in PersistableBundle args, boolean parent);
     List<PersistableBundle> getTrustAgentConfiguration(in ComponentName admin,
-            in ComponentName agent, int userId);
+            in ComponentName agent, int userId, boolean parent);
 
     boolean addCrossProfileWidgetProvider(in ComponentName admin, String packageName);
     boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName);
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 801c951..8e515e2 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -427,23 +427,31 @@
     }
 
     /**
-     * Tells the application agent that the backup data size exceeded current transport quota.
-     * Later calls to {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)}
-     * and {@link #onFullBackup(FullBackupDataOutput)} could use this information
-     * to reduce backup size under the limit.
-     * However, the quota can change, so do not assume that the value passed in here is absolute,
-     * similarly all subsequent backups should not be restricted to this size.
-     * This callback will be invoked before data has been put onto the wire in a preflight check,
-     * so it is relatively inexpensive to hit your quota.
-     * Apps that hit quota repeatedly without dealing with it can be subject to having their backup
-     * schedule reduced.
-     * The {@code quotaBytes} is a loose guideline b/c of metadata added by the backupmanager
-     * so apps should be more aggressive in trimming their backup set.
+     * Notification that the application's current backup operation causes it to exceed
+     * the maximum size permitted by the transport.  The ongoing backup operation is
+     * halted and rolled back: any data that had been stored by a previous backup operation
+     * is still intact.  Typically the quota-exceeded state will be detected before any data
+     * is actually transmitted over the network.
      *
-     * @param backupDataBytes Expected or already processed amount of data.
-     *                        Could be less than total backup size if backup process was interrupted
-     *                        before finish of processing all backup data.
-     * @param quotaBytes Current amount of backup data that is allowed for the app.
+     * <p>The {@code quotaBytes} value is the total data size currently permitted for this
+     * application.  If desired, the application can use this as a hint for determining
+     * how much data to store.  For example, a messaging application might choose to
+     * store only the newest messages, dropping enough older content to stay under
+     * the quota.
+     *
+     * <p class="note">Note that the maximum quota for the application can change over
+     * time.  In particular, in the future the quota may grow.  Applications that adapt
+     * to the quota when deciding what data to store should be aware of this and implement
+     * their data storage mechanisms in a way that can take advantage of additional
+     * quota.
+     *
+     * @param backupDataBytes The amount of data measured while initializing the backup
+     *    operation, if the total exceeds the app's alloted quota.  If initial measurement
+     *    suggested that the data would fit but then too much data was actually submitted
+     *    as part of the operation, then this value is the amount of data that had been
+     *    streamed into the transport at the time the quota was reached.
+     * @param quotaBytes The maximum data size that the transport currently permits
+     *    this application to store as a backup.
      */
     public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
     }
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 1af4953..2d9f4a7 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -17,8 +17,7 @@
 package android.appwidget;
 
 import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.List;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -35,7 +34,9 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.util.DisplayMetrics;
+import android.util.SparseArray;
 import android.util.TypedValue;
 import android.widget.RemoteViews;
 import android.widget.RemoteViews.OnClickHandler;
@@ -62,7 +63,7 @@
     private final Handler mHandler;
     private final int mHostId;
     private final Callbacks mCallbacks;
-    private final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<>();
+    private final SparseArray<AppWidgetHostView> mViews = new SparseArray<>();
     private OnClickHandler mOnClickHandler;
 
     static class Callbacks extends IAppWidgetHost.Stub {
@@ -164,7 +165,6 @@
         bindService();
     }
 
-
     private static void bindService() {
         synchronized (sServiceLock) {
             if (sService == null) {
@@ -179,17 +179,25 @@
      * becomes visible, i.e. from onStart() in your Activity.
      */
     public void startListening() {
-        int[] updatedIds;
-        ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
+        final int[] idsToUpdate;
+        synchronized (mViews) {
+            int N = mViews.size();
+            idsToUpdate = new int[N];
+            for (int i = 0; i < N; i++) {
+                idsToUpdate[i] = mViews.keyAt(i);
+            }
+        }
+        List<RemoteViews> updatedViews;
+        int[] updatedIds = new int[idsToUpdate.length];
         try {
-            updatedIds = sService.startListening(mCallbacks, mContextOpPackageName, mHostId,
-                    updatedViews);
+            updatedViews = sService.startListening(
+                    mCallbacks, mContextOpPackageName, mHostId, idsToUpdate, updatedIds).getList();
         }
         catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
         }
 
-        final int N = updatedIds.length;
+        int N = updatedViews.size();
         for (int i = 0; i < N; i++) {
             updateAppWidgetView(updatedIds[i], updatedViews.get(i));
         }
@@ -206,10 +214,6 @@
         catch (RemoteException e) {
             throw new RuntimeException("system server dead?", e);
         }
-
-        // This is here because keyguard needs it since it'll be switching users after this call.
-        // If it turns out other apps need to call this often, we should re-think how this works.
-        clearViews();
     }
 
     /**
@@ -418,7 +422,9 @@
      * Clear the list of Views that have been created by this AppWidgetHost.
      */
     protected void clearViews() {
-        mViews.clear();
+        synchronized (mViews) {
+            mViews.clear();
+        }
     }
 }
 
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index d762a17..2a7eff8 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -36,6 +36,7 @@
 import android.os.ParcelUuid;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Pair;
 
@@ -1015,6 +1016,8 @@
         try {
             if (mService != null) {
                 return mService.factoryReset();
+            } else {
+                SystemProperties.set("persist.bluetooth.factoryreset", "true");
             }
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index 7d698b3..01f82e6 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -284,6 +284,8 @@
         out.writeInt(mInstance);
         out.writeInt(mProperties);
         out.writeInt(mPermissions);
+        out.writeInt(mKeySize);
+        out.writeInt(mWriteType);
         out.writeTypedList(mDescriptors);
     }
 
@@ -303,6 +305,8 @@
         mInstance = in.readInt();
         mProperties = in.readInt();
         mPermissions = in.readInt();
+        mKeySize = in.readInt();
+        mWriteType = in.readInt();
 
         mDescriptors = new ArrayList<BluetoothGattDescriptor>();
 
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index e355a1c..35437a1 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -144,7 +144,7 @@
     }
 
     /**
-     * 
+     *
      * Get a list of devices that match any of the given connection
      * states.
      *
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index cd67b3e..4db4567 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.accounts.Account;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -60,6 +61,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
@@ -289,6 +292,31 @@
     /** @hide */
     public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
 
+    /** @hide */
+    @IntDef(flag = true,
+            value = {
+                NOTIFY_SYNC_TO_NETWORK,
+                NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface NotifyFlags {}
+
+    /**
+     * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: attempt to sync the change
+     * to the network.
+     */
+    public static final int NOTIFY_SYNC_TO_NETWORK = 1<<0;
+
+    /**
+     * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: if set, this notification
+     * will be skipped if it is being delivered to the root URI of a ContentObserver that is
+     * using "notify for descendants."  The purpose of this is to allow the provide to send
+     * a general notification of "something under X" changed that observers of that specific
+     * URI can receive, while also sending a specific URI under X.  It would use this flag
+     * when sending the former, so that observers of "X and descendants" only see the latter.
+     */
+    public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 1<<1;
+
     // Always log queries which take 500ms+; shorter queries are
     // sampled accordingly.
     private static final boolean ENABLE_CONTENT_SAMPLE = false;
@@ -1676,7 +1704,7 @@
      * The observer that originated the change will only receive the notification if it
      * has requested to receive self-change notifications by implementing
      * {@link ContentObserver#deliverSelfNotifications()} to return true.
-     * @param syncToNetwork If true, attempt to sync the change to the network.
+     * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
      */
     public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
@@ -1690,6 +1718,32 @@
     }
 
     /**
+     * Notify registered observers that a row was updated.
+     * To register, call {@link #registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver) registerContentObserver()}.
+     * By default, CursorAdapter objects will get this notification.
+     * If syncToNetwork is true, this will attempt to schedule a local sync using the sync
+     * adapter that's registered for the authority of the provided uri. No account will be
+     * passed to the sync adapter, so all matching accounts will be synchronized.
+     *
+     * @param uri The uri of the content that was changed.
+     * @param observer The observer that originated the change, may be <code>null</null>.
+     * The observer that originated the change will only receive the notification if it
+     * has requested to receive self-change notifications by implementing
+     * {@link ContentObserver#deliverSelfNotifications()} to return true.
+     * @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
+     * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
+     */
+    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
+            @NotifyFlags int flags) {
+        Preconditions.checkNotNull(uri, "uri");
+        notifyChange(
+                ContentProvider.getUriWithoutUserId(uri),
+                observer,
+                flags,
+                ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
+    }
+
+    /**
      * Notify registered observers within the designated user(s) that a row was updated.
      *
      * @hide
@@ -1699,7 +1753,24 @@
         try {
             getContentService().notifyChange(
                     uri, observer == null ? null : observer.getContentObserver(),
-                    observer != null && observer.deliverSelfNotifications(), syncToNetwork,
+                    observer != null && observer.deliverSelfNotifications(),
+                    syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
+                    userHandle);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Notify registered observers within the designated user(s) that a row was updated.
+     *
+     * @hide
+     */
+    public void notifyChange(Uri uri, ContentObserver observer, @NotifyFlags int flags,
+            @UserIdInt int userHandle) {
+        try {
+            getContentService().notifyChange(
+                    uri, observer == null ? null : observer.getContentObserver(),
+                    observer != null && observer.deliverSelfNotifications(), flags,
                     userHandle);
         } catch (RemoteException e) {
         }
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index d47e780..3446e03 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -52,7 +52,7 @@
      *     USER_CURRENT are properly interpreted.
      */
     void notifyChange(in Uri uri, IContentObserver observer,
-            boolean observerWantsSelfNotifications, boolean syncToNetwork,
+            boolean observerWantsSelfNotifications, int flags,
             int userHandle);
 
     void requestSync(in Account account, String authority, in Bundle extras);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 10259be..30f2c94 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3056,15 +3056,29 @@
     public static final String ACTION_MANAGED_PROFILE_UNLOCKED =
             "android.intent.action.MANAGED_PROFILE_UNLOCKED";
 
+    /** @hide */
+    public static final String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED =
+            "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+
     /**
-     * Broadcast sent to the primary user when an associated managed profile's availability has
-     * changed. This includes when the user toggles the profile's quiet mode. Carries an extra
+     * Broadcast sent to the primary user when an associated managed profile has become available.
+     * Currently this includes when the user disables quiet mode for the profile. Carries an extra
      * {@link #EXTRA_USER} that specifies the UserHandle of the profile. When quiet mode is changed,
      * this broadcast will carry a boolean extra {@link #EXTRA_QUIET_MODE} indicating the new state
      * of quiet mode. This is only sent to registered receivers, not manifest receivers.
      */
-    public static final String ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED =
-            "android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED";
+    public static final String ACTION_MANAGED_PROFILE_AVAILABLE =
+            "android.intent.action.MANAGED_PROFILE_AVAILABLE";
+
+    /**
+     * Broadcast sent to the primary user when an associated managed profile has become unavailable.
+     * Currently this includes when the user enables quiet mode for the profile. Carries an extra
+     * {@link #EXTRA_USER} that specifies the UserHandle of the profile. When quiet mode is changed,
+     * this broadcast will carry a boolean extra {@link #EXTRA_QUIET_MODE} indicating the new state
+     * of quiet mode. This is only sent to registered receivers, not manifest receivers.
+     */
+    public static final String ACTION_MANAGED_PROFILE_UNAVAILABLE =
+            "android.intent.action.MANAGED_PROFILE_UNAVAILABLE";
 
     /**
      * Sent when the user taps on the clock widget in the system's "quick settings" area.
@@ -4165,6 +4179,9 @@
 
     /**
      * Optional boolean extra indicating whether quiet mode has been switched on or off.
+     * When a profile goes into quiet mode, all apps in the profile are killed and the
+     * profile user is stopped. Widgets originating from the profile are masked, and app
+     * launcher icons are grayed out.
      */
     public static final String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
 
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 3a17e23..22ab43b 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -449,11 +449,12 @@
     }
 
     /**
-     * Modify priority of this filter.  The default priority is 0. Positive
-     * values will be before the default, lower values will be after it.
-     * Applications must use a value that is larger than
-     * {@link #SYSTEM_LOW_PRIORITY} and smaller than
-     * {@link #SYSTEM_HIGH_PRIORITY} .
+     * Modify priority of this filter.  This only affects receiver filters.
+     * The priority of activity filters are set in XML and cannot be changed
+     * programatically. The default priority is 0. Positive values will be
+     * before the default, lower values will be after it. Applications should
+     * use a value that is larger than {@link #SYSTEM_LOW_PRIORITY} and
+     * smaller than {@link #SYSTEM_HIGH_PRIORITY} .
      *
      * @param priority The new priority value.
      *
@@ -883,6 +884,15 @@
             return true;
         }
 
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof AuthorityEntry) {
+                final AuthorityEntry other = (AuthorityEntry)obj;
+                return match(other);
+            }
+            return false;
+        }
+
         /**
          * Determine whether this AuthorityEntry matches the given data Uri.
          * <em>Note that this comparison is case-sensitive, unlike formal
@@ -917,7 +927,7 @@
             }
             return MATCH_CATEGORY_HOST;
         }
-    };
+    }
 
     /**
      * Add a new Intent data "scheme specific part" to match against.  The filter must
diff --git a/core/java/android/content/pm/FeatureInfo.java b/core/java/android/content/pm/FeatureInfo.java
index 7671f72..9ee6fa2 100644
--- a/core/java/android/content/pm/FeatureInfo.java
+++ b/core/java/android/content/pm/FeatureInfo.java
@@ -48,6 +48,9 @@
      * <p>
      * If this object represents a feature requested by an app, this is the
      * minimum version of the feature required by the app.
+     * <p>
+     * When a feature version is undefined by a device, it's assumed to be
+     * version 0.
      */
     public int version;
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e89cbd7..39bc783 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -130,6 +130,7 @@
             MATCH_DISABLED_COMPONENTS,
             MATCH_DISABLED_UNTIL_USED_COMPONENTS,
             MATCH_SYSTEM_ONLY,
+            MATCH_FACTORY_ONLY,
             MATCH_DEBUG_TRIAGED_MISSING,
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -415,6 +416,13 @@
     public static final int MATCH_SYSTEM_ONLY = 0x00100000;
 
     /**
+     * Internal {@link PackageInfo} flag: include only components on the system image.
+     * This will not return information on any unbundled update to system components.
+     * @hide
+     */
+    public static final int MATCH_FACTORY_ONLY = 0x00200000;
+
+    /**
      * Internal flag used to indicate that a system component has done their
      * homework and verified that they correctly handle packages and components
      * that come and go over time. In particular:
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ea251f6..aa1e372 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -385,6 +385,7 @@
         public final int installLocation;
         public final VerifierInfo[] verifiers;
         public final Signature[] signatures;
+        public final Certificate[][] certificates;
         public final boolean coreApp;
         public final boolean multiArch;
         public final boolean use32bitAbi;
@@ -392,8 +393,8 @@
 
         public ApkLite(String codePath, String packageName, String splitName, int versionCode,
                 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
-                Signature[] signatures, boolean coreApp, boolean multiArch, boolean use32bitAbi,
-                boolean extractNativeLibs) {
+                Signature[] signatures, Certificate[][] certificates, boolean coreApp,
+                boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs) {
             this.codePath = codePath;
             this.packageName = packageName;
             this.splitName = splitName;
@@ -402,6 +403,7 @@
             this.installLocation = installLocation;
             this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
             this.signatures = signatures;
+            this.certificates = certificates;
             this.coreApp = coreApp;
             this.multiArch = multiArch;
             this.use32bitAbi = use32bitAbi;
@@ -1074,6 +1076,43 @@
     }
 
     /**
+     * Populates the correct packages fields with the given certificates.
+     * <p>
+     * This is useful when we've already processed the certificates [such as during package
+     * installation through an installer session]. We don't re-process the archive and
+     * simply populate the correct fields.
+     */
+    public static void populateCertificates(Package pkg, Certificate[][] certificates)
+            throws PackageParserException {
+        pkg.mCertificates = null;
+        pkg.mSignatures = null;
+        pkg.mSigningKeys = null;
+
+        pkg.mCertificates = certificates;
+        try {
+            pkg.mSignatures = convertToSignatures(certificates);
+        } catch (CertificateEncodingException e) {
+            // certificates weren't encoded properly; something went wrong
+            throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
+                    "Failed to collect certificates from " + pkg.baseCodePath, e);
+        }
+        pkg.mSigningKeys = new ArraySet<>(certificates.length);
+        for (int i = 0; i < certificates.length; i++) {
+            Certificate[] signerCerts = certificates[i];
+            Certificate signerCert = signerCerts[0];
+            pkg.mSigningKeys.add(signerCert.getPublicKey());
+        }
+        // add signatures to child packages
+        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+        for (int i = 0; i < childCount; i++) {
+            Package childPkg = pkg.childPackages.get(i);
+            childPkg.mCertificates = pkg.mCertificates;
+            childPkg.mSignatures = pkg.mSignatures;
+            childPkg.mSigningKeys = pkg.mSigningKeys;
+        }
+    }
+
+    /**
      * 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.
@@ -1096,13 +1135,19 @@
         pkg.mSignatures = null;
         pkg.mSigningKeys = null;
 
-        collectCertificates(pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags);
+        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
+        try {
+            collectCertificates(
+                    pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags);
 
-        if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
-            for (int i = 0; i < pkg.splitCodePaths.length; i++) {
-                collectCertificates(pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i],
-                        parseFlags);
+            if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
+                for (int i = 0; i < pkg.splitCodePaths.length; i++) {
+                    collectCertificates(
+                            pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i], parseFlags);
+                }
             }
+        } finally {
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
     }
 
@@ -1118,6 +1163,7 @@
             Certificate[][] allSignersCerts = null;
             Signature[] signatures = null;
             try {
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2");
                 allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath);
                 signatures = convertToSignatures(allSignersCerts);
                 // APK verified using APK Signature Scheme v2.
@@ -1130,6 +1176,8 @@
                         "Failed to collect certificates from " + apkPath
                                 + " using APK Signature Scheme v2",
                         e);
+            } finally {
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             }
 
             if (verified) {
@@ -1186,7 +1234,7 @@
             }
 
             // APK's integrity needs to be verified using JAR signature scheme.
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "buildVerifyList");
+            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1");
             final List<ZipEntry> toVerify = new ArrayList<>();
             toVerify.add(manifestEntry);
 
@@ -1208,7 +1256,6 @@
                     toVerify.add(entry);
                 }
             }
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             if (!codeFound && requireCode) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
@@ -1218,7 +1265,6 @@
             // Verify that entries are signed consistently with the first entry
             // we encountered. Note that for splits, certificates may have
             // already been populated during an earlier parse of a base APK.
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyEntries");
             for (ZipEntry entry : toVerify) {
                 final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
                 if (ArrayUtils.isEmpty(entryCerts)) {
@@ -1297,17 +1343,25 @@
             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
 
             final Signature[] signatures;
+            final Certificate[][] certificates;
             if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
                 // TODO: factor signature related items out of Package object
                 final Package tempPkg = new Package(null);
-                collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/);
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
+                try {
+                    collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/);
+                } finally {
+                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+                }
                 signatures = tempPkg.mSignatures;
+                certificates = tempPkg.mCertificates;
             } else {
                 signatures = null;
+                certificates = null;
             }
 
             final AttributeSet attrs = parser;
-            return parseApkLite(apkPath, res, parser, attrs, flags, signatures);
+            return parseApkLite(apkPath, res, parser, attrs, flags, signatures, certificates);
 
         } catch (XmlPullParserException | IOException | RuntimeException e) {
             throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
@@ -1393,8 +1447,8 @@
     }
 
     private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser,
-            AttributeSet attrs, int flags, Signature[] signatures) throws IOException,
-            XmlPullParserException, PackageParserException {
+            AttributeSet attrs, int flags, Signature[] signatures, Certificate[][] certificates)
+                    throws IOException, XmlPullParserException, PackageParserException {
         final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
 
         int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
@@ -1454,8 +1508,8 @@
         }
 
         return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
-                revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
-                use32bitAbi, extractNativeLibs);
+                revisionCode, installLocation, verifiers, signatures, certificates, coreApp,
+                multiArch, use32bitAbi, extractNativeLibs);
     }
 
     /**
@@ -5531,7 +5585,7 @@
         return pi;
     }
 
-    public final static class Instrumentation extends Component {
+    public final static class Instrumentation extends Component<IntentInfo> {
         public final InstrumentationInfo info;
 
         public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 984a960..65e0b92 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -113,6 +113,13 @@
     public static final int PROTECTION_FLAG_PREINSTALLED = 0x400;
 
     /**
+     * Additional flag for {@link #protectionLevel}, corresponding
+     * to the <code>setup</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     */
+    public static final int PROTECTION_FLAG_SETUP = 0x800;
+
+    /**
      * Mask for {@link #protectionLevel}: the basic protection type.
      */
     public static final int PROTECTION_MASK_BASE = 0xf;
@@ -226,6 +233,9 @@
         if ((level&PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0) {
             protLevel += "|preinstalled";
         }
+        if ((level&PermissionInfo.PROTECTION_FLAG_SETUP) != 0) {
+            protLevel += "|setup";
+        }
         return protLevel;
     }
 
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 387fda7..93fe73b 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -714,12 +714,11 @@
      * the resource ID passed here is an alias to another Drawable resource.
      * This means that if the density configuration of the alias resource
      * is different than the actual resource, the density of the returned
-     * Drawable would be incorrect, resulting in bad scaling.  To work
-     * around this, you can instead retrieve the Drawable through
-     * {@link TypedArray#getDrawable TypedArray.getDrawable}.  Use
-     * {@link android.content.Context#obtainStyledAttributes(int[])
-     * Context.obtainStyledAttributes} with
-     * an array containing the resource ID of interest to create the TypedArray.</p>
+     * Drawable would be incorrect, resulting in bad scaling. To work
+     * around this, you can instead manually resolve the aliased reference
+     * by using {@link #getValue(int, TypedValue, boolean)} and passing
+     * {@code true} for {@code resolveRefs}. The resulting
+     * {@link TypedValue#resourceId} value may be passed to this method.</p>
      *
      * <p class="note"><strong>Note:</strong> To obtain a themed drawable, use
      * {@link android.content.Context#getDrawable(int) Context.getDrawable(int)}
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index a762f59..34a9523 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -26,6 +26,7 @@
 import android.os.CancellationSignal;
 import android.os.OperationCanceledException;
 import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
 import android.os.Trace;
 import android.util.Log;
 import android.util.LruCache;
@@ -1311,7 +1312,8 @@
                         operation.mBindArgs.clear();
                     }
                 }
-                operation.mStartTime = System.currentTimeMillis();
+                operation.mStartWallTime = System.currentTimeMillis();
+                operation.mStartTime = SystemClock.uptimeMillis();
                 operation.mKind = kind;
                 operation.mSql = sql;
                 if (bindArgs != null) {
@@ -1376,7 +1378,7 @@
                     Trace.asyncTraceEnd(Trace.TRACE_TAG_DATABASE, operation.getTraceMethodName(),
                             operation.mCookie);
                 }
-                operation.mEndTime = System.currentTimeMillis();
+                operation.mEndTime = SystemClock.uptimeMillis();
                 operation.mFinished = true;
                 return SQLiteDebug.DEBUG_LOG_SLOW_QUERIES && SQLiteDebug.shouldLogSlowQuery(
                                 operation.mEndTime - operation.mStartTime);
@@ -1454,8 +1456,9 @@
         // marker for us, potentially losing metadata in the process).
         private static final int MAX_TRACE_METHOD_NAME_LEN = 256;
 
-        public long mStartTime;
-        public long mEndTime;
+        public long mStartWallTime; // in System.currentTimeMillis()
+        public long mStartTime; // in SystemClock.uptimeMillis();
+        public long mEndTime; // in SystemClock.uptimeMillis();
         public String mKind;
         public String mSql;
         public ArrayList<Object> mBindArgs;
@@ -1468,7 +1471,7 @@
             if (mFinished) {
                 msg.append(" took ").append(mEndTime - mStartTime).append("ms");
             } else {
-                msg.append(" started ").append(System.currentTimeMillis() - mStartTime)
+                msg.append(" started ").append(System.currentTimeMillis() - mStartWallTime)
                         .append("ms ago");
             }
             msg.append(" - ").append(getStatus());
@@ -1519,7 +1522,7 @@
             //       relatively expensive to create during preloading. This method is only used
             //       when dumping a connection, which is a rare (mainly error) case. So:
             //       DO NOT CACHE.
-            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(mStartTime));
+            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(mStartWallTime));
         }
     }
 }
diff --git a/core/java/android/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index 2dce425..b2288fc 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -136,12 +136,14 @@
         }
         String vmFlags = "CheckJNI="
             + (vmRuntime.isCheckJniEnabled() ? "true" : "false");
+        boolean isNativeDebuggable = vmRuntime.isNativeDebuggable();
 
         ByteBuffer out = ByteBuffer.allocate(28
                             + vmIdent.length() * 2
                             + appName.length() * 2
                             + instructionSetDescription.length() * 2
-                            + vmFlags.length() * 2);
+                            + vmFlags.length() * 2
+                            + 1);
         out.order(ChunkHandler.CHUNK_ORDER);
         out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
         out.putInt(android.os.Process.myPid());
@@ -154,6 +156,7 @@
         putString(out, instructionSetDescription);
         out.putInt(vmFlags.length());
         putString(out, vmFlags);
+        out.put((byte)(isNativeDebuggable ? 1 : 0));
 
         Chunk reply = new Chunk(CHUNK_HELO, out);
 
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 63ee8d2..cc82eb6 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -186,7 +186,7 @@
      * @see #TYPE_LINEAR_ACCELERATION
      */
     public static final String STRING_TYPE_LINEAR_ACCELERATION =
-        "android.sensor.linear_acceleration";
+            "android.sensor.linear_acceleration";
 
     /**
      * A constant describing a rotation vector sensor type.
@@ -229,7 +229,7 @@
      * @see #TYPE_AMBIENT_TEMPERATURE
      */
     public static final String STRING_TYPE_AMBIENT_TEMPERATURE =
-        "android.sensor.ambient_temperature";
+            "android.sensor.ambient_temperature";
 
     /**
      * A constant describing an uncalibrated magnetic field sensor type.
@@ -254,7 +254,7 @@
      * @see #TYPE_MAGNETIC_FIELD_UNCALIBRATED
      */
     public static final String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED =
-        "android.sensor.magnetic_field_uncalibrated";
+            "android.sensor.magnetic_field_uncalibrated";
 
     /**
      * A constant describing an uncalibrated rotation vector sensor type.
@@ -280,7 +280,7 @@
      * @see #TYPE_GAME_ROTATION_VECTOR
      */
     public static final String STRING_TYPE_GAME_ROTATION_VECTOR =
-        "android.sensor.game_rotation_vector";
+            "android.sensor.game_rotation_vector";
 
     /**
      * A constant describing an uncalibrated gyroscope sensor type.
@@ -302,7 +302,7 @@
      * @see #TYPE_GYROSCOPE_UNCALIBRATED
      */
     public static final String STRING_TYPE_GYROSCOPE_UNCALIBRATED =
-        "android.sensor.gyroscope_uncalibrated";
+            "android.sensor.gyroscope_uncalibrated";
 
     /**
      * A constant describing a significant motion trigger sensor.
@@ -324,7 +324,7 @@
      * @see #TYPE_SIGNIFICANT_MOTION
      */
     public static final String STRING_TYPE_SIGNIFICANT_MOTION =
-        "android.sensor.significant_motion";
+            "android.sensor.significant_motion";
 
     /**
      * A constant describing a step detector sensor.
@@ -391,7 +391,7 @@
      * @see #TYPE_GEOMAGNETIC_ROTATION_VECTOR
      */
     public static final String STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR =
-        "android.sensor.geomagnetic_rotation_vector";
+            "android.sensor.geomagnetic_rotation_vector";
 
     /**
      * A constant describing a heart rate monitor.
@@ -431,7 +431,7 @@
      * A constant string describing a wake up tilt detector sensor type.
      *
      * @hide
-     * @see #TYPE_WAKE_UP_TILT_DETECTOR
+     * @see #TYPE_TILT_DETECTOR
      */
     public static final String SENSOR_STRING_TYPE_TILT_DETECTOR =
             "android.sensor.tilt_detector";
@@ -495,7 +495,7 @@
      */
     public static final String STRING_TYPE_GLANCE_GESTURE = "android.sensor.glance_gesture";
 
-     /**
+    /**
      * A constant describing a pick up sensor.
      *
      * A sensor of this type triggers when the device is picked up regardless of wherever it was
@@ -514,7 +514,7 @@
      */
     public static final String STRING_TYPE_PICK_UP_GESTURE = "android.sensor.pick_up_gesture";
 
-     /**
+    /**
      * A constant describing a wrist tilt gesture sensor.
      *
      * A sensor of this type triggers when the device face is tilted towards the user.
@@ -553,7 +553,7 @@
      */
     public static final String STRING_TYPE_DEVICE_ORIENTATION = "android.sensor.device_orientation";
 
-     /**
+    /**
      * A constant describing a pose sensor with 6 degrees of freedom.
      *
      * Similar to {@link #TYPE_ROTATION_VECTOR}, with additional delta
@@ -578,7 +578,7 @@
      */
     public static final String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
 
-     /**
+    /**
      * A constant describing a stationary detect sensor.
      *
      * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
@@ -593,7 +593,7 @@
      */
     public static final String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
 
-     /**
+    /**
      * A constant describing a motion detect sensor.
      *
      * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
@@ -608,7 +608,7 @@
      */
     public static final String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
 
-     /**
+    /**
      * A constant describing a motion detect sensor.
      *
      * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
@@ -706,6 +706,14 @@
     private static final int DATA_INJECTION_MASK = 0x10;
     private static final int DATA_INJECTION_SHIFT = 4;
 
+    // MASK for dynamic sensor (sensor that added during runtime), bit 6.
+    private static final int DYNAMIC_SENSOR_MASK = 0x20;
+    private static final int DYNAMIC_SENSOR_SHIFT = 5;
+
+    // MASK for indication bit of sensor additional information support (bit 7).
+    private static final int ADDITIONAL_INFO_MASK = 0x40;
+    private static final int ADDITIONAL_INFO_SHIFT = 6;
+
     // TODO(): The following arrays are fragile and error-prone. This needs to be refactored.
 
     // Note: This needs to be updated, whenever a new sensor is added.
@@ -887,13 +895,37 @@
     }
 
     /**
-     * @return The type of this sensor as a string.
+     * @return The UUID of the sensor. If the sensor does not support UUID, the returned value will
+     * be an all zero UUID; if the sensor's combination of type and name is guaranteed to be unique
+     * in system, the return value will be an all "F" UUID.
+     *
+     * @hide
      */
+    @SystemApi
     public UUID getUuid() {
         return mUuid;
     }
 
     /**
+     * @return The unique id of sensor. Return value of 0 means this sensor does not support UUID;
+     * return value of -1 means this sensor can be uniquely identified in system by combination of
+     * its type and name.
+     */
+    public int getId() {
+        if (mUuid == ALL_0_UUID) {
+            return 0;
+        } else if (mUuid == ALL_F_UUID) {
+            return -1;
+        } else {
+            int id = Math.abs(mUuid.hashCode()) + 1;
+            if (id <= 0) { // catch corner case when hash is Integer.MIN_VALUE and Integer.MAX_VALUE
+                id = 1;
+            }
+            return id;
+        }
+    }
+
+    /**
      * @hide
      * @return The permission required to access this sensor. If empty, no permission is required.
      */
@@ -961,6 +993,26 @@
     }
 
     /**
+     * Returns true if the sensor is a dynamic sensor.
+     *
+     * @return <code>true</code> if the sensor is a dynamic sensor (sensor added at runtime).
+     * @see SensorManager.DynamicSensorCallback
+     */
+    public boolean isDynamicSensor() {
+        return (mFlags & DYNAMIC_SENSOR_MASK) != 0;
+    }
+
+    /**
+     * Returns true if the sensor supports sensor additional information API
+     *
+     * @return <code>true</code> if the sensor supports sensor additional information API
+     * @see SensorAdditionalInfo
+     */
+    public boolean isAdditionalInfoSupported() {
+        return (mFlags & ADDITIONAL_INFO_MASK) != 0;
+    }
+
+    /**
      * Returns true if the sensor supports data injection when the
      * HAL is set to data injection mode.
      *
@@ -986,6 +1038,10 @@
                 + ", power=" + mPower + ", minDelay=" + mMinDelay + "}";
     }
 
+    //special UUID hash constant
+    private final static UUID ALL_0_UUID = new UUID(0,0);
+    private final static UUID ALL_F_UUID = new UUID(~0L, ~0L);
+
     /**
      * Sets the Type associated with the sensor.
      * NOTE: to be used only by native bindings in SensorManager.
diff --git a/core/java/android/hardware/SensorAdditionalInfo.java b/core/java/android/hardware/SensorAdditionalInfo.java
index 8e5b8a3..572a287 100644
--- a/core/java/android/hardware/SensorAdditionalInfo.java
+++ b/core/java/android/hardware/SensorAdditionalInfo.java
@@ -27,7 +27,7 @@
  * android.hardware.SensorEventCallback#onSensorAdditionalInfo onSensorAdditionalInfo}.
  *
  * @see SensorManager
- * @see SensorEventListener3
+ * @see SensorEventCallback
  * @see Sensor
  *
  */
@@ -106,7 +106,7 @@
      * such as accelerometer, gyro, etc.
      *
      * Payload:
-     *     floatValues[0..11]: First 3 rows of a homogenous matrix in row major order that captures
+     *     floatValues[0..11]: First 3 rows of a homogeneous matrix in row major order that captures
      *     any linear transformation, including rotation, scaling, shear, shift.
      */
     public static final int TYPE_VEC3_CALIBRATION = 0x10002;
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 35c96f7..0d96b8e 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -18,7 +18,7 @@
 
 /**
  * This class represents a {@link android.hardware.Sensor Sensor} event and
- * holds informations such as the sensor's type, the time-stamp, accuracy and of
+ * holds information such as the sensor's type, the time-stamp, accuracy and of
  * course the sensor's {@link SensorEvent#values data}.
  *
  * <p>
@@ -163,7 +163,7 @@
      * </ul>
      * <p>
      * Typically the output of the gyroscope is integrated over time to
-     * calculate a rotation describing the change of angles over the timestep,
+     * calculate a rotation describing the change of angles over the time step,
      * for example:
      * </p>
      *
@@ -173,7 +173,7 @@
      *     private float timestamp;
      *
      *     public void onSensorChanged(SensorEvent event) {
-     *          // This timestep's delta rotation to be multiplied by the current rotation
+     *          // This time step's delta rotation to be multiplied by the current rotation
      *          // after computing it from the gyro sample data.
      *          if (timestamp != 0) {
      *              final float dT = (event.timestamp - timestamp) * NS2S;
@@ -192,8 +192,8 @@
      *                  axisZ /= omegaMagnitude;
      *              }
      *
-     *              // Integrate around this axis with the angular speed by the timestep
-     *              // in order to get a delta rotation from this sample over the timestep
+     *              // Integrate around this axis with the angular speed by the time step
+     *              // in order to get a delta rotation from this sample over the time step
      *              // We will convert this axis-angle representation of the delta rotation
      *              // into a quaternion before turning it into the rotation matrix.
      *              float thetaOverTwo = omegaMagnitude * dT / 2.0f;
@@ -433,9 +433,9 @@
      * Each field is a component of the estimated hard iron calibration.
      * The values are in micro-Tesla (uT).
      * </p>
-     * <p> Hard iron - These distortions arise due to the magnetized iron, steel or permanenet
+     * <p> Hard iron - These distortions arise due to the magnetized iron, steel or permanent
      * magnets on the device.
-     * Soft iron - These distortions arise due to the interaction with the earth's magentic
+     * Soft iron - These distortions arise due to the interaction with the earth's magnetic
      * field.
      * </p>
      * <h4> {@link android.hardware.Sensor#TYPE_GAME_ROTATION_VECTOR}:</h4>
@@ -508,14 +508,14 @@
      *
      *
      * <ul>
-     *  <li> values[0]: x*sin(&#952/2) </li>
-     *  <li> values[1]: y*sin(&#952/2) </li>
-     *  <li> values[2]: z*sin(&#952/2) </li>
-     *  <li> values[3]: cos(&#952/2)   </li>
+     * <li> values[0]: x*sin(&#952/2) </li>
+     * <li> values[1]: y*sin(&#952/2) </li>
+     * <li> values[2]: z*sin(&#952/2) </li>
+     * <li> values[3]: cos(&#952/2)   </li>
      *
      *
      * <li> values[4]: Translation along x axis from an arbitrary origin. </li>
-     * li> values[5]: Translation along y axis from an arbitrary origin. </li>
+     * <li> values[5]: Translation along y axis from an arbitrary origin. </li>
      * <li> values[6]: Translation along z axis from an arbitrary origin. </li>
      *
      * <li> values[7]:  Delta quaternion rotation x*sin(&#952/2) </li>
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 5684aa5..a20307a 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -884,7 +884,7 @@
      * Used for receiving notifications from the SensorManager when dynamic sensors are connected or
      * disconnected.
      */
-    public static abstract class DynamicSensorConnectionCallback {
+    public static abstract class DynamicSensorCallback {
         /**
          * Called when there is a dynamic sensor being connected to the system.
          *
@@ -902,62 +902,73 @@
 
 
     /**
-     * Add a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
-     * DynamicSensorConnectionCallback} to receive dynamic sensor connection callbacks. Repeat
+     * Add a {@link android.hardware.SensorManager.DynamicSensorCallback
+     * DynamicSensorCallback} to receive dynamic sensor connection callbacks. Repeat
      * registration with the already registered callback object will have no additional effect.
      *
      * @param callback An object that implements the
-     *        {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
-     *        DynamicSensorConnectionCallback}
+     *        {@link android.hardware.SensorManager.DynamicSensorCallback
+     *        DynamicSensorCallback}
      *        interface for receiving callbacks.
-     * @see #addDynamicSensorCallback(DynamicSensorConnectionCallback, Handler)
+     * @see #addDynamicSensorCallback(DynamicSensorCallback, Handler)
      *
      * @throws IllegalArgumentException when callback is null.
      */
-    public void registerDynamicSensorCallback(DynamicSensorConnectionCallback callback) {
+    public void registerDynamicSensorCallback(DynamicSensorCallback callback) {
         registerDynamicSensorCallback(callback, null);
     }
 
     /**
-     * Add a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
-     * DynamicSensorConnectionCallback} to receive dynamic sensor connection callbacks. Repeat
+     * Add a {@link android.hardware.SensorManager.DynamicSensorCallback
+     * DynamicSensorCallback} to receive dynamic sensor connection callbacks. Repeat
      * registration with the already registered callback object will have no additional effect.
      *
      * @param callback An object that implements the
-     *        {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
-     *        DynamicSensorConnectionCallback} interface for receiving callbacks.
+     *        {@link android.hardware.SensorManager.DynamicSensorCallback
+     *        DynamicSensorCallback} interface for receiving callbacks.
      * @param handler The {@link android.os.Handler Handler} the {@link
-     *        android.hardware.SensorManager.DynamicSensorConnectionCallback
+     *        android.hardware.SensorManager.DynamicSensorCallback
      *        sensor connection events} will be delivered to.
      *
      * @throws IllegalArgumentException when callback is null.
      */
     public void registerDynamicSensorCallback(
-            DynamicSensorConnectionCallback callback, Handler handler) {
+            DynamicSensorCallback callback, Handler handler) {
         registerDynamicSensorCallbackImpl(callback, handler);
     }
 
     /**
-     * Remove a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
-     * DynamicSensorConnectionCallback} to stop sending dynamic sensor connection events to that
+     * Remove a {@link android.hardware.SensorManager.DynamicSensorCallback
+     * DynamicSensorCallback} to stop sending dynamic sensor connection events to that
      * callback.
      *
      * @param callback An object that implements the
-     *        {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
-     *        DynamicSensorConnectionCallback}
+     *        {@link android.hardware.SensorManager.DynamicSensorCallback
+     *        DynamicSensorCallback}
      *        interface for receiving callbacks.
      */
-    public void unregisterDynamicSensorCallback(DynamicSensorConnectionCallback callback) {
+    public void unregisterDynamicSensorCallback(DynamicSensorCallback callback) {
         unregisterDynamicSensorCallbackImpl(callback);
     }
 
+    /**
+     * Tell if dynamic sensor discovery feature is supported by system.
+     *
+     * @return <code>true</code> if dynamic sensor discovery is supported, <code>false</code>
+     * otherwise.
+     */
+    public boolean isDynamicSensorDiscoverySupported() {
+        List<Sensor> sensors = getSensorList(Sensor.TYPE_DYNAMIC_SENSOR_META);
+        return sensors.size() > 0;
+    }
+
     /** @hide */
     protected abstract void registerDynamicSensorCallbackImpl(
-            DynamicSensorConnectionCallback callback, Handler handler);
+            DynamicSensorCallback callback, Handler handler);
 
     /** @hide */
     protected abstract void unregisterDynamicSensorCallbackImpl(
-            DynamicSensorConnectionCallback callback);
+            DynamicSensorCallback callback);
 
     /**
      * <p>
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 7d903bd..259ca03 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -1,4 +1,4 @@
-    /*
+/*
  * Copyright (C) 2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -76,7 +76,7 @@
             new HashMap<TriggerEventListener, TriggerEventQueue>();
 
     // Dynamic Sensor callbacks
-    private HashMap<DynamicSensorConnectionCallback, Handler>
+    private HashMap<DynamicSensorCallback, Handler>
             mDynamicSensorCallbacks = new HashMap<>();
     private BroadcastReceiver mDynamicSensorBroadcastReceiver;
 
@@ -120,7 +120,7 @@
     @Override
     protected List<Sensor> getFullDynamicSensorList() {
         // only set up broadcast receiver if the application tries to find dynamic sensors or
-        // explicitly register a DynamicSensorConnectionCallback
+        // explicitly register a DynamicSensorCallback
         setupDynamicSensorBroadcastReceiver();
         updateDynamicSensorList();
         return mFullDynamicSensorsList;
@@ -354,9 +354,9 @@
 
                     Handler mainHandler = new Handler(mContext.getMainLooper());
 
-                    for (Map.Entry<DynamicSensorConnectionCallback, Handler> entry :
+                    for (Map.Entry<DynamicSensorCallback, Handler> entry :
                             mDynamicSensorCallbacks.entrySet()) {
-                        final DynamicSensorConnectionCallback callback = entry.getKey();
+                        final DynamicSensorCallback callback = entry.getKey();
                         Handler handler =
                                 entry.getValue() == null ? mainHandler : entry.getValue();
 
@@ -413,7 +413,7 @@
 
     /** @hide */
     protected void registerDynamicSensorCallbackImpl(
-            DynamicSensorConnectionCallback callback, Handler handler) {
+            DynamicSensorCallback callback, Handler handler) {
         if (DEBUG_DYNAMIC_SENSOR) {
             Log.i(TAG, "DYNS Register dynamic sensor callback");
         }
@@ -432,7 +432,7 @@
 
     /** @hide */
     protected void unregisterDynamicSensorCallbackImpl(
-            DynamicSensorConnectionCallback callback) {
+            DynamicSensorCallback callback) {
         if (DEBUG_DYNAMIC_SENSOR) {
             Log.i(TAG, "Removing dynamic sensor listerner");
         }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 4add962..d06e08b 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2025,11 +2025,20 @@
      * produced in response to a capture request submitted
      * while in HDR mode.</p>
      * <p>Since substantial post-processing is generally needed to
-     * produce an HDR image, only YUV and JPEG outputs are
-     * supported for LIMITED/FULL device HDR captures, and only
-     * JPEG outputs are supported for LEGACY HDR
-     * captures. Using a RAW output for HDR capture is not
+     * produce an HDR image, only YUV, PRIVATE, and JPEG
+     * outputs are supported for LIMITED/FULL device HDR
+     * captures, and only JPEG outputs are supported for LEGACY
+     * HDR captures. Using a RAW output for HDR capture is not
      * supported.</p>
+     * <p>Some devices may also support always-on HDR, which
+     * applies HDR processing at full frame rate.  For these
+     * devices, intents other than STILL_CAPTURE will also
+     * produce an HDR output with no frame rate impact compared
+     * to normal operation, though the quality may be lower
+     * than for STILL_CAPTURE intents.</p>
+     * <p>If SCENE_MODE_HDR is used with unsupported output types
+     * or capture intents, the images captured will be as if
+     * the SCENE_MODE was not enabled at all.</p>
      *
      * @see CaptureRequest#CONTROL_CAPTURE_INTENT
      * @see CaptureRequest#CONTROL_SCENE_MODE
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 5748726..4f41e1c 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -3373,7 +3373,7 @@
 
     /**
      * <p>Maximum raw value output by sensor for this frame.</p>
-     * <p>Since the android.sensor.blackLevel may change for different
+     * <p>Since the {@link CameraCharacteristics#SENSOR_BLACK_LEVEL_PATTERN android.sensor.blackLevelPattern} may change for different
      * capture settings (e.g., {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}), the white
      * level will change accordingly. This key is similar to
      * {@link CameraCharacteristics#SENSOR_INFO_WHITE_LEVEL android.sensor.info.whiteLevel}, but specifies the camera device
@@ -3385,6 +3385,7 @@
      * &gt;= 0</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
+     * @see CameraCharacteristics#SENSOR_BLACK_LEVEL_PATTERN
      * @see CameraCharacteristics#SENSOR_INFO_WHITE_LEVEL
      * @see CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS
      * @see CaptureRequest#SENSOR_SENSITIVITY
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index d84a6fc..d2e820e 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -974,6 +974,7 @@
 
             if (mRemoteDevice != null) {
                 mRemoteDevice.disconnect();
+                mRemoteDevice.unlinkToDeath(this, /*flags*/0);
             }
 
             // Only want to fire the onClosed callback once;
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
index ddc3fd1..ef5f6d7 100644
--- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -31,6 +31,7 @@
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.utils.SubmitInfo;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.view.Surface;
 
@@ -53,6 +54,12 @@
         mRemoteDevice = remoteDevice;
     }
 
+    public void unlinkToDeath(IBinder.DeathRecipient recipient, int flags) {
+        if (mRemoteDevice.asBinder() != null) {
+            mRemoteDevice.asBinder().unlinkToDeath(recipient, flags);
+        }
+    }
+
     public void disconnect()  {
         try {
             mRemoteDevice.disconnect();
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
index 2c2ad1c..b0b94e3 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
@@ -70,7 +70,7 @@
      * CameraDeviceStateListener callbacks to be called after state transitions.
      */
     public interface CameraDeviceStateListener {
-        void onError(int errorCode, RequestHolder holder);
+        void onError(int errorCode, Object errorArg, RequestHolder holder);
         void onConfiguring();
         void onIdle();
         void onBusy();
@@ -162,11 +162,12 @@
      * @param captureError Report a recoverable error for a single buffer or result using a valid
      *                     error code for {@code ICameraDeviceCallbacks}, or
      *                     {@link #NO_CAPTURE_ERROR}.
+     * @param captureErrorArg An argument for some error captureError codes.
      * @return {@code false} if an error has occurred.
      */
     public synchronized boolean setCaptureResult(final RequestHolder request,
-                                             final CameraMetadataNative result,
-                                             final int captureError) {
+            final CameraMetadataNative result,
+            final int captureError, final Object captureErrorArg) {
         if (mCurrentState != STATE_CAPTURING) {
             Log.e(TAG, "Cannot receive result while in state: " + mCurrentState);
             mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
@@ -179,7 +180,7 @@
                 mCurrentHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        mCurrentListener.onError(captureError, request);
+                        mCurrentListener.onError(captureError, captureErrorArg, request);
                     }
                 });
             } else {
@@ -194,6 +195,11 @@
         return mCurrentError == NO_CAPTURE_ERROR;
     }
 
+    public synchronized boolean setCaptureResult(final RequestHolder request,
+            final CameraMetadataNative result) {
+        return setCaptureResult(request, result, NO_CAPTURE_ERROR, /*errorArg*/null);
+    }
+
     /**
      * Set the listener for state transition callbacks.
      *
@@ -239,7 +245,7 @@
                     mCurrentHandler.post(new Runnable() {
                         @Override
                         public void run() {
-                            mCurrentListener.onError(mCurrentError, mCurrentRequest);
+                            mCurrentListener.onError(mCurrentError, /*errorArg*/null, mCurrentRequest);
                         }
                     });
                 }
@@ -299,7 +305,7 @@
                         mCurrentHandler.post(new Runnable() {
                             @Override
                             public void run() {
-                                mCurrentListener.onError(error, mCurrentRequest);
+                                mCurrentListener.onError(error, /*errorArg*/null, mCurrentRequest);
                             }
                         });
                     } else {
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index d01c275..f99928a 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -480,19 +480,15 @@
             throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
-        ArrayList<Surface> surfaces = null;
+        SparseArray<Surface> surfaces = null;
         synchronized(mConfigureLock) {
             if (!mConfiguring) {
                 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) {
-                surfaces = new ArrayList<>();
-                for (int i = 0; i < numSurfaces; ++i) {
-                    surfaces.add(mSurfaces.valueAt(i));
-                }
+            if (mSurfaces != null) {
+                surfaces = mSurfaces.clone();
             }
             mConfiguring = false;
         }
diff --git a/core/java/android/hardware/camera2/legacy/CaptureCollector.java b/core/java/android/hardware/camera2/legacy/CaptureCollector.java
index eb48a01..113927c 100644
--- a/core/java/android/hardware/camera2/legacy/CaptureCollector.java
+++ b/core/java/android/hardware/camera2/legacy/CaptureCollector.java
@@ -19,7 +19,7 @@
 import android.util.Log;
 import android.util.MutableLong;
 import android.util.Pair;
-
+import android.view.Surface;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.TreeSet;
@@ -95,22 +95,28 @@
                     } else {
                         // Send buffer dropped errors for each pending buffer if the request has
                         // started.
-                        if (mFailedPreview) {
-                            Log.w(TAG, "Preview buffers dropped for request: " +
-                                    mRequest.getRequestId());
-                            for (int i = 0; i < mRequest.numPreviewTargets(); i++) {
-                                CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
-                                    /*result*/null,
-                                        CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER);
-                            }
-                        }
-                        if (mFailedJpeg) {
-                            Log.w(TAG, "Jpeg buffers dropped for request: " +
-                                    mRequest.getRequestId());
-                            for (int i = 0; i < mRequest.numJpegTargets(); i++) {
-                                CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
-                                    /*result*/null,
-                                        CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER);
+                        for (Surface targetSurface : mRequest.getRequest().getTargets() ) {
+                            try {
+                                if (mRequest.jpegType(targetSurface)) {
+                                    if (mFailedJpeg) {
+                                        CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
+                                                /*result*/null,
+                                                CameraDeviceImpl.CameraDeviceCallbacks.
+                                                        ERROR_CAMERA_BUFFER,
+                                                targetSurface);
+                                    }
+                                } else {
+                                    // preview buffer
+                                    if (mFailedPreview) {
+                                        CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
+                                                /*result*/null,
+                                                CameraDeviceImpl.CameraDeviceCallbacks.
+                                                        ERROR_CAMERA_BUFFER,
+                                                targetSurface);
+                                    }
+                                }
+                            } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+                                Log.e(TAG, "Unexpected exception when querying Surface: " + e);
                             }
                         }
                     }
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 661edd7..6c95869 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -36,6 +36,7 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.Size;
+import android.util.SparseArray;
 import android.view.Surface;
 
 import java.util.ArrayList;
@@ -64,7 +65,7 @@
     private final CameraCharacteristics mStaticCharacteristics;
     private final ICameraDeviceCallbacks mDeviceCallbacks;
     private final CameraDeviceState mDeviceState = new CameraDeviceState();
-    private List<Surface> mConfiguredSurfaces;
+    private SparseArray<Surface> mConfiguredSurfaces;
     private boolean mClosed = false;
 
     private final ConditionVariable mIdle = new ConditionVariable(/*open*/true);
@@ -89,13 +90,29 @@
     public static final int NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW = 1;
 
     private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
+        return getExtrasFromRequest(holder,
+                /*errorCode*/CameraDeviceState.NO_CAPTURE_ERROR, /*errorArg*/null);
+    }
+
+    private CaptureResultExtras getExtrasFromRequest(RequestHolder holder,
+            int errorCode, Object errorArg) {
+        int errorStreamId = -1;
+        if (errorCode == CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER) {
+            Surface errorTarget = (Surface) errorArg;
+            int indexOfTarget = mConfiguredSurfaces.indexOfValue(errorTarget);
+            if (indexOfTarget < 0) {
+                Log.e(TAG, "Buffer drop error reported for unknown Surface");
+            } else {
+                errorStreamId = mConfiguredSurfaces.keyAt(indexOfTarget);
+            }
+        }
         if (holder == null) {
             return new CaptureResultExtras(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, /*errorStreamId*/-1);
+                /*partialResultCount*/1, errorStreamId);
     }
 
     /**
@@ -105,9 +122,9 @@
     private final CameraDeviceState.CameraDeviceStateListener mStateListener =
             new CameraDeviceState.CameraDeviceStateListener() {
         @Override
-        public void onError(final int errorCode, final RequestHolder holder) {
+        public void onError(final int errorCode, final Object errorArg, final RequestHolder holder) {
             if (DEBUG) {
-                Log.d(TAG, "onError called, errorCode = " + errorCode);
+                Log.d(TAG, "onError called, errorCode = " + errorCode + ", errorArg = " + errorArg);
             }
             switch (errorCode) {
                 /*
@@ -125,7 +142,7 @@
                 }
             }
 
-            final CaptureResultExtras extras = getExtrasFromRequest(holder);
+            final CaptureResultExtras extras = getExtrasFromRequest(holder, errorCode, errorArg);
             mResultHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -281,14 +298,17 @@
      *
      * <p>Every surface in {@code outputs} must be non-{@code null}.</p>
      *
-     * @param outputs a list of surfaces to set.
+     * @param outputs a list of surfaces to set. LegacyCameraDevice will take ownership of this
+     *          list; it must not be modified by the caller once it's passed in.
      * @return an error code for this binder operation, or {@link NO_ERROR}
      *          on success.
      */
-    public int configureOutputs(List<Surface> outputs) {
+    public int configureOutputs(SparseArray<Surface> outputs) {
         List<Pair<Surface, Size>> sizedSurfaces = new ArrayList<>();
         if (outputs != null) {
-            for (Surface output : outputs) {
+            int count = outputs.size();
+            for (int i = 0; i < count; i++)  {
+                Surface output = outputs.valueAt(i);
                 if (output == null) {
                     Log.e(TAG, "configureOutputs - null outputs are not allowed");
                     return BAD_VALUE;
@@ -353,7 +373,7 @@
         }
 
         if (success) {
-            mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null;
+            mConfiguredSurfaces = outputs;
         } else {
             return LegacyExceptionUtils.INVALID_OPERATION;
         }
@@ -659,6 +679,23 @@
         return nativeGetSurfaceId(surface);
     }
 
+    static List<Long> getSurfaceIds(SparseArray<Surface> surfaces) {
+        if (surfaces == null) {
+            throw new NullPointerException("Null argument surfaces");
+        }
+        List<Long> surfaceIds = new ArrayList<>();
+        int count = surfaces.size();
+        for (int i = 0; i < count; i++) {
+            long id = getSurfaceId(surfaces.valueAt(i));
+            if (id == 0) {
+                throw new IllegalStateException(
+                        "Configured surface had null native GraphicBufferProducer pointer!");
+            }
+            surfaceIds.add(id);
+        }
+        return surfaceIds;
+    }
+
     static List<Long> getSurfaceIds(Collection<Surface> surfaces) {
         if (surfaces == null) {
             throw new NullPointerException("Null argument surfaces");
diff --git a/core/java/android/hardware/camera2/legacy/RequestHolder.java b/core/java/android/hardware/camera2/legacy/RequestHolder.java
index 9b628fb..476c3de 100644
--- a/core/java/android/hardware/camera2/legacy/RequestHolder.java
+++ b/core/java/android/hardware/camera2/legacy/RequestHolder.java
@@ -41,6 +41,8 @@
     private final int mNumPreviewTargets;
     private volatile boolean mFailed = false;
 
+    private final Collection<Long> mJpegSurfaceIds;
+
     /**
      * A builder class for {@link RequestHolder} objects.
      *
@@ -150,13 +152,13 @@
          */
         public RequestHolder build(long frameNumber) {
             return new RequestHolder(mRequestId, mSubsequenceId, mRequest, mRepeating, frameNumber,
-                    mNumJpegTargets, mNumPreviewTargets);
+                    mNumJpegTargets, mNumPreviewTargets, mJpegSurfaceIds);
         }
     }
 
     private RequestHolder(int requestId, int subsequenceId, CaptureRequest request,
                           boolean repeating, long frameNumber, int numJpegTargets,
-                          int numPreviewTargets) {
+                          int numPreviewTargets, Collection<Long> jpegSurfaceIds) {
         mRepeating = repeating;
         mRequest = request;
         mRequestId = requestId;
@@ -164,6 +166,7 @@
         mFrameNumber = frameNumber;
         mNumJpegTargets = numJpegTargets;
         mNumPreviewTargets = numPreviewTargets;
+        mJpegSurfaceIds = jpegSurfaceIds;
     }
 
     /**
@@ -238,6 +241,17 @@
     }
 
     /**
+     * Returns true if the given surface requires jpeg buffers.
+     *
+     * @param s a {@link android.view.Surface} to check.
+     * @return true if the surface requires a jpeg buffer.
+     */
+    public boolean jpegType(Surface s)
+            throws LegacyExceptionUtils.BufferQueueAbandonedException {
+        return LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds);
+    }
+
+    /**
      * Mark this request as failed.
      */
     public void failRequest() {
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index e8ce3ec..a3fdd56 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -908,8 +908,7 @@
                         mFaceDetectMapper.mapResultFaces(result, mLastRequest);
 
                         if (!holder.requestFailed()) {
-                            mDeviceState.setCaptureResult(holder, result,
-                                    CameraDeviceState.NO_CAPTURE_ERROR);
+                            mDeviceState.setCaptureResult(holder, result);
                         }
                     }
                     if (DEBUG) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index b8088f3..4756b372 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -815,7 +815,8 @@
                 if (groupId != reqGroupId) {
                     Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
                 }
-                mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint);
+                mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
+                        deviceId));
             }
         }
 
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index fbac58c..47440de 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,9 +16,7 @@
 
 package android.hardware.input;
 
-import com.android.internal.inputmethod.InputMethodSubtypeHandle;
 import com.android.internal.os.SomeArgs;
-import com.android.internal.util.ArrayUtils;
 
 import android.annotation.IntDef;
 import android.annotation.SdkConstant;
diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java
index 014e73f..10fc8e6 100644
--- a/core/java/android/hardware/input/InputManagerInternal.java
+++ b/core/java/android/hardware/input/InputManagerInternal.java
@@ -52,4 +52,11 @@
      */
     public abstract void onInputMethodSubtypeChanged(int userId,
             @Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype);
+
+    /**
+     * Toggles Caps Lock state for input device with specific id.
+     *
+     * @param deviceId The id of input device.
+     */
+    public abstract void toggleCapsLock(int deviceId);
 }
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index 644e29f..194b9ee 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -37,6 +37,7 @@
     private float mStoppedPowerDrawMw;
     private float mSleepPowerDrawMw;
     private float mPeakPowerDrawMw;
+    private int mMaxPacketLengthBytes;
 
     private int[] mSupportedSensors;
 
@@ -46,6 +47,27 @@
     }
 
     /**
+     * returns the maximum number of bytes that can be sent per message to the hub
+     *
+     * @return int - maximum bytes that can be transmitted in a
+     *         single packet
+     */
+    public int getMaxPacketLengthBytes() {
+        return mMaxPacketLengthBytes;
+    }
+
+    /**
+     * set the context hub unique identifer
+     *
+     * @param bytes - Maximum number of bytes per message
+     *
+     * @hide
+     */
+    public void setMaxPacketLenBytes(int bytes) {
+        mMaxPacketLengthBytes = bytes;
+    }
+
+    /**
      * get the context hub unique identifer
      *
      * @return int - unique system wide identifier
@@ -323,6 +345,24 @@
         mMemoryRegions = Arrays.copyOf(memoryRegions, memoryRegions.length);
     }
 
+    @Override
+    public String toString() {
+      String retVal = "";
+      retVal += "Id : " + mId;
+      retVal += ", Name : " + mName;
+      retVal += "\n\tVendor : " + mVendor;
+      retVal += ", ToolChain : " + mToolchain;
+      retVal += "\n\tPlatformVersion : " + mPlatformVersion;
+      retVal += ", StaticSwVersion : " + mStaticSwVersion;
+      retVal += "\n\tPeakMips : " + mPeakMips;
+      retVal += ", StoppedPowerDraw : " + mStoppedPowerDrawMw + " mW";
+      retVal += ", PeakPowerDraw : " + mPeakPowerDrawMw + " mW";
+      retVal += "\n\tSupported sensors : " + Arrays.toString(mSupportedSensors);
+      retVal += "\n\tMemory Regions : " + Arrays.toString(mMemoryRegions);
+
+      return retVal;
+    }
+
     private ContextHubInfo(Parcel in) {
         mId = in.readInt();
         mName = in.readString();
@@ -374,4 +414,4 @@
             return new ContextHubInfo[size];
         }
     };
-}
+}
\ No newline at end of file
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 4ddf767..89edaa9 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -43,23 +43,6 @@
     private Handler mCallbackHandler;
 
     /**
-     * A special context hub identifier meaning any possible hub on the system.
-     */
-    public static final int ANY_HUB       = -1;
-    /**
-     * A constant denoting a message to load a a Nano App
-     */
-    public static final int MSG_LOAD_NANO_APP   = 1;
-    /**
-     * A constant denoting a message to unload a a Nano App
-     */
-    public static final int MSG_UNLOAD_NANO_APP = 2;
-    /**
-     * A constant denoting a message to send a message
-     */
-    public static final int MSG_DATA_SEND       = 3;
-
-    /**
      * An interface to receive asynchronous communication from the context hub.
      */
     public abstract static class Callback {
@@ -69,7 +52,7 @@
          * Callback function called on message receipt from context hub.
          *
          * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
-         * @param nanoAppHandle Handle (unique identifier) for the app that sent the message.
+         * @param nanoAppHandle Handle (unique identifier) for app instance that sent the message.
          * @param message The context hub message.
          *
          * @see ContextHubMessage
@@ -89,7 +72,7 @@
         try {
             retVal = getBinder().getContextHubHandles();
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch context hub handles : " + e);
+            Log.w(TAG, "Could not fetch context hub handles : " + e);
         }
         return retVal;
     }
@@ -107,7 +90,7 @@
         try {
             retVal = getBinder().getContextHubInfo(hubHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch context hub info :" + e);
+            Log.w(TAG, "Could not fetch context hub info :" + e);
         }
 
         return retVal;
@@ -126,6 +109,7 @@
      */
     public int loadNanoApp(int hubHandle, NanoApp app) {
         int retVal = -1;
+
         if (app == null) {
             return retVal;
         }
@@ -133,7 +117,7 @@
         try {
             retVal = getBinder().loadNanoApp(hubHandle, app);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch load nanoApp :" + e);
+            Log.w(TAG, "Could not load nanoApp :" + e);
         }
 
         return retVal;
@@ -152,7 +136,7 @@
         try {
             retVal = getBinder().unloadNanoApp(nanoAppHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch unload nanoApp :" + e);
+            Log.w(TAG, "Could not fetch unload nanoApp :" + e);
         }
 
         return retVal;
@@ -172,7 +156,7 @@
         try {
             retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch nanoApp info :" + e);
+            Log.w(TAG, "Could not fetch nanoApp info :" + e);
         }
 
         return retVal;
@@ -193,7 +177,7 @@
         try {
             retVal = getBinder().findNanoAppOnHub(hubHandle, filter);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not query nanoApp instance :" + e);
+            Log.w(TAG, "Could not query nanoApp instance :" + e);
         }
         return retVal;
     }
@@ -212,10 +196,14 @@
     public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
         int retVal = -1;
 
+        if (message == null || message.getData() == null) {
+            Log.w(TAG, "null ptr");
+            return retVal;
+        }
         try {
             retVal = getBinder().sendMessage(hubHandle, nanoAppHandle, message);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch send message :" + e.toString());
+            Log.w(TAG, "Could not send message :" + e.toString());
         }
 
         return retVal;
@@ -247,7 +235,7 @@
     public int registerCallback(Callback callback, Handler handler) {
         synchronized(this) {
             if (mCallback != null) {
-                Log.e(TAG, "Max number of callbacks reached!");
+                Log.w(TAG, "Max number of callbacks reached!");
                 return -1;
             }
             mCallback = callback;
@@ -268,7 +256,7 @@
     public int unregisterCallback(Callback callback) {
       synchronized(this) {
           if (callback != mCallback) {
-              Log.e(TAG, "Cannot recognize callback!");
+              Log.w(TAG, "Cannot recognize callback!");
               return -1;
           }
 
@@ -311,11 +299,11 @@
             try {
                 getBinder().registerCallback(mClientCallback);
             } catch (RemoteException e) {
-                Log.e(TAG, "Could not register callback:" + e);
+                Log.w(TAG, "Could not register callback:" + e);
             }
 
         } else {
-            Log.d(TAG, "failed to getService");
+            Log.w(TAG, "failed to getService");
         }
     }
 
diff --git a/core/java/android/hardware/location/ContextHubMessage.java b/core/java/android/hardware/location/ContextHubMessage.java
index 954e97d..bca2ae6 100644
--- a/core/java/android/hardware/location/ContextHubMessage.java
+++ b/core/java/android/hardware/location/ContextHubMessage.java
@@ -16,10 +16,10 @@
 
 package android.hardware.location;
 
-
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Log;
 
 import java.util.Arrays;
 
@@ -32,6 +32,9 @@
     private int mVersion;
     private byte[]mData;
 
+    private static final String TAG = "ContextHubMessage";
+
+
     /**
      * Get the message type
      *
@@ -106,9 +109,11 @@
     private ContextHubMessage(Parcel in) {
         mType = in.readInt();
         mVersion = in.readInt();
-        byte[] byteBuffer = new byte[in.readInt()];
-        in.readByteArray(byteBuffer);
+        int bufferLength = in.readInt();
+        mData = new byte[bufferLength];
+        in.readByteArray(mData);
     }
+
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mType);
         out.writeInt(mVersion);
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index 274babe..2b9b974 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -18,9 +18,12 @@
 
 import android.Manifest;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -28,13 +31,30 @@
  * @hide
  */
 public class ContextHubService extends IContextHubService.Stub {
+    public static final String CONTEXTHUB_SERVICE = "contexthub_service";
 
     private static final String TAG = "ContextHubService";
     private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
     private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
-            + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
+        + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
 
-    public static final String CONTEXTHUB_SERVICE = "contexthub_service";
+
+    public static final int ANY_HUB             = -1;
+    public static final int MSG_LOAD_NANO_APP   = 3;
+    public static final int MSG_UNLOAD_NANO_APP = 4;
+
+    private static final String PRE_LOADED_GENERIC_UNKNOWN = "Preloaded app, unknown";
+    private static final String PRE_LOADED_APP_NAME = PRE_LOADED_GENERIC_UNKNOWN;
+    private static final String PRE_LOADED_APP_PUBLISHER = PRE_LOADED_GENERIC_UNKNOWN;
+    private static final int PRE_LOADED_APP_MEM_REQ = 0;
+
+    private static final int MSG_HEADER_SIZE = 4;
+    private static final int MSG_FIELD_TYPE = 0;
+    private static final int MSG_FIELD_VERSION = 1;
+    private static final int MSG_FIELD_HUB_HANDLE = 2;
+    private static final int MSG_FIELD_APP_INSTANCE = 3;
+
+    private static final int OS_APP_INSTANCE = -1;
 
     private final Context mContext;
 
@@ -42,54 +62,37 @@
     private ContextHubInfo[] mContextHubInfo;
     private IContextHubCallback mCallback;
 
+    private native int nativeSendMessage(int[] header, byte[] data);
+    private native ContextHubInfo[] nativeInitialize();
+
+
     public ContextHubService(Context context) {
         mContext = context;
         mContextHubInfo = nativeInitialize();
+        mNanoAppHash = new HashMap<Integer, NanoAppInstanceInfo>();
 
         for (int i = 0; i < mContextHubInfo.length; i++) {
-            Log.v(TAG, "ContextHub[" + i + "] id: " + mContextHubInfo[i].getId()
+            Log.d(TAG, "ContextHub[" + i + "] id: " + mContextHubInfo[i].getId()
                   + ", name:  " + mContextHubInfo[i].getName());
         }
     }
 
-    private native int nativeSendMessage(int[] header, byte[] data);
-    private native ContextHubInfo[] nativeInitialize();
-
     @Override
-    public int registerCallback(IContextHubCallback callback) throws RemoteException{
+    public int registerCallback(IContextHubCallback callback) throws RemoteException {
         checkPermissions();
-        mCallback = callback;
-        return 0;
-    }
-
-
-    private int onMessageReceipt(int[] header, byte[] data) {
-        if (mCallback != null) {
-            // TODO : Defend against unexpected header sizes
-            //        Add abstraction for magic numbers
-            //        onMessageRecipt should pass the right arguments
-            ContextHubMessage msg = new ContextHubMessage(header[0], header[1], data);
-
-            try {
-                mCallback.onMessageReceipt(0, 0, msg);
-            } catch (Exception e) {
-                Log.e(TAG, "Exception " + e + " when calling remote callback");
-                return -1;
-            }
-        } else {
-            Log.d(TAG, "Message Callback is NULL");
+        synchronized (this) {
+            mCallback = callback;
         }
-
         return 0;
     }
 
     @Override
     public int[] getContextHubHandles() throws RemoteException {
         checkPermissions();
-        int [] returnArray = new int[mContextHubInfo.length];
+        int[] returnArray = new int[mContextHubInfo.length];
 
         for (int i = 0; i < returnArray.length; ++i) {
-            returnArray[i] = i + 1; //valid handles from 1...n
+            returnArray[i] = i;
             Log.d(TAG, String.format("Hub %s is mapped to %d",
                                      mContextHubInfo[i].getName(), returnArray[i]));
         }
@@ -100,7 +103,6 @@
     @Override
     public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
         checkPermissions();
-        contextHubHandle -= 1;
         if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
             return null; // null means fail
         }
@@ -111,21 +113,23 @@
     @Override
     public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
         checkPermissions();
-        contextHubHandle -= 1;
 
         if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
-            return -1; // negative handle are invalid, means failed
+            Log.e(TAG, "Invalid contextHubhandle " + contextHubHandle);
+            return -1;
         }
 
-        // Call Native interface here
-        int[] msgHeader = new int[8];
-        msgHeader[0] = contextHubHandle;
-        msgHeader[1] = app.getAppId();
-        msgHeader[2] = app.getAppVersion();
-        msgHeader[3] = ContextHubManager.MSG_LOAD_NANO_APP;
-        msgHeader[4] = 0; // Loading hints
+        int[] msgHeader = new int[MSG_HEADER_SIZE];
+        msgHeader[MSG_FIELD_HUB_HANDLE] = contextHubHandle;
+        msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
+        msgHeader[MSG_FIELD_VERSION] = 0;
+        msgHeader[MSG_FIELD_TYPE] = MSG_LOAD_NANO_APP;
 
-        return nativeSendMessage(msgHeader, app.getAppBinary());
+        if (nativeSendMessage(msgHeader, app.getAppBinary()) != 0) {
+            return -1;
+        }
+        // Do not add an entry to mNanoAppInstance Hash yet. The HAL may reject the app
+        return 0;
     }
 
     @Override
@@ -137,17 +141,23 @@
         }
 
         // Call Native interface here
-        int[] msgHeader = new int[8];
-        msgHeader[0] = info.getContexthubId();
-        msgHeader[1] = ContextHubManager.MSG_UNLOAD_NANO_APP;
-        msgHeader[2] = info.getHandle();
+        int[] msgHeader = new int[MSG_HEADER_SIZE];
+        msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB;
+        msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
+        msgHeader[MSG_FIELD_VERSION] = 0;
+        msgHeader[MSG_FIELD_TYPE] = MSG_UNLOAD_NANO_APP;
 
-        return nativeSendMessage(msgHeader, null);
+        if (nativeSendMessage(msgHeader, null) != 0) {
+            return -1;
+        }
+
+        // Do not add an entry to mNanoAppInstance Hash yet. The HAL may reject the app
+        return 0;
     }
 
     @Override
     public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
-            throws RemoteException {
+                                                      throws RemoteException {
         checkPermissions();
         // This assumes that all the nanoAppInfo is current. This is reasonable
         // for the use cases for tightly controlled nanoApps.
@@ -163,10 +173,10 @@
         checkPermissions();
         ArrayList<Integer> foundInstances = new ArrayList<Integer>();
 
-        for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
+        for (Integer nanoAppInstance: mNanoAppHash.keySet()) {
             NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance);
 
-            if(filter.testMatch(info)){
+            if (filter.testMatch(info)) {
                 foundInstances.add(nanoAppInstance);
             }
         }
@@ -181,20 +191,93 @@
 
     @Override
     public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg)
-            throws RemoteException {
+                           throws RemoteException {
         checkPermissions();
-        int[] msgHeader = new int[8];
-        msgHeader[0] = ContextHubManager.MSG_DATA_SEND;
-        msgHeader[1] = hubHandle;
-        msgHeader[2] = nanoAppHandle;
-        msgHeader[3] = msg.getMsgType();
-        msgHeader[4] = msg.getVersion();
+
+        int[] msgHeader = new int[MSG_HEADER_SIZE];
+        msgHeader[MSG_FIELD_HUB_HANDLE] = hubHandle;
+        msgHeader[MSG_FIELD_APP_INSTANCE] = nanoAppHandle;
+        msgHeader[MSG_FIELD_VERSION] = msg.getVersion();
+        msgHeader[MSG_FIELD_TYPE] = msg.getMsgType();
 
         return nativeSendMessage(msgHeader, msg.getData());
     }
 
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
+            != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump contexthub_service");
+            return;
+        }
+
+        pw.println("Dumping ContextHub Service");
+
+        pw.println("");
+        // dump ContextHubInfo
+        pw.println("=================== CONTEXT HUBS ====================");
+        for (int i = 0; i < mContextHubInfo.length; i++) {
+            pw.println("Handle " + i + " : " + mContextHubInfo[i].toString());
+        }
+        pw.println("");
+        pw.println("=================== NANOAPPS ====================");
+        // Dump nanoAppHash
+        for (Integer nanoAppInstance: mNanoAppHash.keySet()) {
+            pw.println(nanoAppInstance + " : " + mNanoAppHash.get(nanoAppInstance).toString());
+        }
+
+        // dump eventLog
+    }
+
     private void checkPermissions() {
         mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
     }
-}
 
+    private int onMessageReceipt(int[] header, byte[] data) {
+        if (header == null || data == null || header.length < MSG_HEADER_SIZE) {
+            return  -1;
+        }
+
+        synchronized (this) {
+            if (mCallback != null) {
+                ContextHubMessage msg = new ContextHubMessage(header[MSG_FIELD_TYPE],
+                                                              header[MSG_FIELD_VERSION],
+                                                              data);
+
+                try {
+                    mCallback.onMessageReceipt(header[MSG_FIELD_HUB_HANDLE],
+                                               header[MSG_FIELD_APP_INSTANCE],
+                                               msg);
+                } catch (Exception e) {
+                    Log.w(TAG, "Exception " + e + " when calling remote callback");
+                    return -1;
+                }
+            } else {
+                Log.d(TAG, "Message Callback is NULL");
+            }
+        }
+
+        return 0;
+    }
+
+    private int addAppInstance(int hubHandle, int appInstanceHandle, long appId, int appVersion) {
+        // App Id encodes vendor & version
+        NanoAppInstanceInfo appInfo = new NanoAppInstanceInfo();
+
+        appInfo.setAppId(appId);
+        appInfo.setAppVersion(appVersion);
+        appInfo.setName(PRE_LOADED_APP_NAME);
+        appInfo.setContexthubId(hubHandle);
+        appInfo.setHandle(appInstanceHandle);
+        appInfo.setPublisher(PRE_LOADED_APP_PUBLISHER);
+        appInfo.setNeededExecMemBytes(PRE_LOADED_APP_MEM_REQ);
+        appInfo.setNeededReadMemBytes(PRE_LOADED_APP_MEM_REQ);
+        appInfo.setNeededWriteMemBytes(PRE_LOADED_APP_MEM_REQ);
+
+        mNanoAppHash.put(appInstanceHandle, appInfo);
+        Log.d(TAG, "Added app instance " + appInstanceHandle + " with id " + appId
+              + " version " + appVersion);
+
+        return 0;
+    }
+}
diff --git a/core/java/android/hardware/location/MemoryRegion.java b/core/java/android/hardware/location/MemoryRegion.java
index d100de2..857434e 100644
--- a/core/java/android/hardware/location/MemoryRegion.java
+++ b/core/java/android/hardware/location/MemoryRegion.java
@@ -79,6 +79,33 @@
     }
 
     @Override
+    public String toString() {
+        String mask = "";
+
+        if (isReadable()) {
+            mask += "r";
+        } else {
+            mask += "-";
+        }
+
+        if (isWritable()) {
+            mask += "w";
+        } else {
+            mask += "-";
+        }
+
+        if (isExecutable()) {
+            mask += "x";
+        } else {
+            mask += "-";
+        }
+
+        String retVal = "[ " + mSizeBytesFree + "/ " + mSizeBytes + " ] : " + mask;
+
+        return retVal;
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
index b447b62..c8f3439 100644
--- a/core/java/android/hardware/location/NanoApp.java
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -284,4 +284,14 @@
             return new NanoApp[size];
         }
     };
+
+    @Override
+    public String toString() {
+        String retVal = "Id : " + mAppId;
+        retVal += ", Version : " + mAppVersion;
+        retVal += ", Name : " + mName;
+        retVal += ", Publisher : " + mPublisher;
+
+        return retVal;
+    }
 }
diff --git a/core/java/android/hardware/location/NanoAppFilter.java b/core/java/android/hardware/location/NanoAppFilter.java
index 369f9e4..8db70e9 100644
--- a/core/java/android/hardware/location/NanoAppFilter.java
+++ b/core/java/android/hardware/location/NanoAppFilter.java
@@ -20,6 +20,7 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Log;
 
 /**
  * @hide
@@ -27,6 +28,8 @@
 @SystemApi
 public class NanoAppFilter {
 
+    private static final String TAG = "NanoAppFilter";
+
     // The appId, can be set to APP_ID_ANY
     private long mAppId;
 
@@ -54,6 +57,10 @@
      * If this flag is set, only versions strictly less than the version specified shall match.
      */
     public static final int FLAGS_VERSION_LESS_THAN   = 4;
+    /**
+     * If this flag is set, only versions strictly equal to the
+     * version specified shall match.
+     */
     public static final int FLAGS_VERSION_STRICTLY_EQUAL = 8;
 
     /**
@@ -117,14 +124,9 @@
      * @return true if this is a match, false otherwise
      */
     public boolean testMatch(NanoAppInstanceInfo info) {
-        if ((mContextHubId == HUB_ANY || info.getContexthubId() == mContextHubId) &&
+        return (mContextHubId == HUB_ANY || info.getContexthubId() == mContextHubId) &&
                 (mAppId == APP_ANY || info.getAppId() == mAppId) &&
-               // (mAppIdVendorMask == VENDOR_ANY) TODO : Expose Vendor mask cleanly
-                (versionsMatch(mVersionRestrictionMask, mAppVersion, info.getAppVersion()))) {
-            return true;
-        } else {
-            return false;
-        }
+                (versionsMatch(mVersionRestrictionMask, mAppVersion, info.getAppVersion()));
     }
 
     public static final Parcelable.Creator<NanoAppFilter> CREATOR
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java
index ac62919..e842ec6 100644
--- a/core/java/android/hardware/location/NanoAppInstanceInfo.java
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java
@@ -29,7 +29,7 @@
     private String mPublisher;
     private String mName;
 
-    private int mAppId;
+    private long mAppId;
     private int mAppVersion;
 
     private int mNeededReadMemBytes;
@@ -59,6 +59,8 @@
      * set the publisher name for the app
      *
      * @param publisher - name of the publisher
+     *
+     * @hide
      */
     public void setPublisher(String publisher) {
         mPublisher = publisher;
@@ -77,6 +79,8 @@
      * set the name of the app
      *
      * @param name - name of the app
+     *
+     * @hide
      */
     public void setName(String name) {
         mName = name;
@@ -87,7 +91,7 @@
      *
      * @return int - application identifier
      */
-    public int getAppId() {
+    public long getAppId() {
         return mAppId;
     }
 
@@ -95,8 +99,10 @@
      * Set the application identifier
      *
      * @param appId - application identifier
+     *
+     * @hide
      */
-    public void setAppId(int appId) {
+    public void setAppId(long appId) {
         mAppId = appId;
     }
 
@@ -113,6 +119,8 @@
      * Set the application version
      *
      * @param appVersion - version of the app
+     *
+     * @hide
      */
     public void setAppVersion(int appVersion) {
         mAppVersion = appVersion;
@@ -131,6 +139,8 @@
      * Set the read memory needed by the app
      *
      * @param neededReadMemBytes - readable Memory needed in bytes
+     *
+     * @hide
      */
     public void setNeededReadMemBytes(int neededReadMemBytes) {
         mNeededReadMemBytes = neededReadMemBytes;
@@ -150,6 +160,8 @@
      *
      * @param neededWriteMemBytes - writable memory needed by the
      *                            app
+     *
+     * @hide
      */
     public void setNeededWriteMemBytes(int neededWriteMemBytes) {
         mNeededWriteMemBytes = neededWriteMemBytes;
@@ -169,6 +181,8 @@
      *
      * @param neededExecMemBytes - executable memory needed by the
      *                           app
+     *
+     * @hide
      */
     public void setNeededExecMemBytes(int neededExecMemBytes) {
         mNeededExecMemBytes = neededExecMemBytes;
@@ -187,6 +201,8 @@
      * set the sensors needed by this app
      *
      * @param neededSensors - all the sensors needed by this app
+     *
+     * @hide
      */
     public void setNeededSensors(int[] neededSensors) {
         mNeededSensors = neededSensors;
@@ -206,6 +222,8 @@
      *
      * @param outputEvents - the events that may be generated by
      *                     this app
+     *
+     * @hide
      */
     public void setOutputEvents(int[] outputEvents) {
         mOutputEvents = outputEvents;
@@ -224,6 +242,8 @@
      * set the context hub identifier
      *
      * @param contexthubId - system wide unique identifier
+     *
+     * @hide
      */
     public void setContexthubId(int contexthubId) {
         mContexthubId = contexthubId;
@@ -242,6 +262,8 @@
      * set the handle for an app instance
      *
      * @param handle - handle to this instance
+     *
+     * @hide
      */
     public void setHandle(int handle) {
         mHandle = handle;
@@ -252,7 +274,7 @@
         mPublisher = in.readString();
         mName = in.readString();
 
-        mAppId = in.readInt();
+        mAppId = in.readLong();
         mAppVersion = in.readInt();
         mNeededReadMemBytes = in.readInt();
         mNeededWriteMemBytes = in.readInt();
@@ -274,7 +296,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(mPublisher);
         out.writeString(mName);
-        out.writeInt(mAppId);
+        out.writeLong(mAppId);
         out.writeInt(mAppVersion);
         out.writeInt(mContexthubId);
         out.writeInt(mNeededReadMemBytes);
@@ -286,7 +308,6 @@
 
         out.writeInt(mOutputEvents.length);
         out.writeIntArray(mOutputEvents);
-
     }
 
     public static final Parcelable.Creator<NanoAppInstanceInfo> CREATOR
@@ -299,4 +320,15 @@
             return new NanoAppInstanceInfo[size];
         }
     };
+
+    @Override
+    public String toString() {
+        String retVal = "handle : " + mHandle;
+        retVal += ", Id : 0x" + Long.toHexString(mAppId);
+        retVal += ", Version : " + mAppVersion;
+        retVal += ", Name : " + mName;
+        retVal += ", Publisher : " + mPublisher;
+
+        return retVal;
+    }
 }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 6b79a8a..cc201bc 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -295,9 +295,7 @@
     boolean mLastShowInputRequested;
     int mCandidatesVisibility;
     CompletionInfo[] mCurCompletions;
-    
-    boolean mShowInputForced;
-    
+
     boolean mFullscreenApplied;
     boolean mIsFullscreen;
     View mExtractView;
@@ -422,7 +420,6 @@
             boolean wasVis = isInputViewShown();
             mShowInputFlags = 0;
             mShowInputRequested = false;
-            mShowInputForced = false;
             doHideWindow();
             clearInsetOfPreviousIme();
             if (resultReceiver != null) {
@@ -439,8 +436,7 @@
         public void showSoftInput(int flags, ResultReceiver resultReceiver) {
             if (DEBUG) Log.v(TAG, "showSoftInput()");
             boolean wasVis = isInputViewShown();
-            mShowInputFlags = 0;
-            if (onShowInputRequested(flags, false)) {
+            if (dispatchOnShowInputRequested(flags, false)) {
                 try {
                     showWindow(true);
                 } catch (BadTokenException e) {
@@ -721,7 +717,11 @@
                 mShowImeWithHardKeyboard = Settings.Secure.getInt(mService.getContentResolver(),
                         Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0 ?
                         ShowImeWithHardKeyboardType.TRUE : ShowImeWithHardKeyboardType.FALSE;
-                mService.updateInputViewShown();
+                // In Android M and prior, state change of
+                // Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD has triggered
+                // #onConfigurationChanged().  For compatibility reasons, we reset the internal
+                // state as if configuration was changed.
+                mService.resetStateForNewConfiguration();
             }
         }
 
@@ -817,8 +817,8 @@
         mInitialized = false;
         mWindowCreated = false;
         mShowInputRequested = false;
-        mShowInputForced = false;
-        
+        mShowInputFlags = 0;
+
         mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
         mRootView = mInflater.inflate(
                 com.android.internal.R.layout.input_method, null);
@@ -888,7 +888,10 @@
      */
     @Override public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        
+        resetStateForNewConfiguration();
+    }
+
+    private void resetStateForNewConfiguration() {
         boolean visible = mWindowVisible;
         int showFlags = mShowInputFlags;
         boolean showingInput = mShowInputRequested;
@@ -903,7 +906,7 @@
         if (visible) {
             if (showingInput) {
                 // If we were last showing the soft keyboard, try to do so again.
-                if (onShowInputRequested(showFlags, true)) {
+                if (dispatchOnShowInputRequested(showFlags, true)) {
                     showWindow(true);
                     if (completions != null) {
                         mCurCompletions = completions;
@@ -1540,20 +1543,41 @@
                 return false;
             }
         }
-        if ((flags&InputMethod.SHOW_FORCED) != 0) {
-            mShowInputForced = true;
-        }
         return true;
     }
-    
+
+    /**
+     * A utility method to call {{@link #onShowInputRequested(int, boolean)}} and update internal
+     * states depending on its result.  Since {@link #onShowInputRequested(int, boolean)} is
+     * exposed to IME authors as an overridable public method without {@code @CallSuper}, we have
+     * to have this method to ensure that those internal states are always updated no matter how
+     * {@link #onShowInputRequested(int, boolean)} is overridden by the IME author.
+     * @param flags Provides additional information about the show request,
+     * as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
+     * @param configChange This is true if we are re-showing due to a
+     * configuration change.
+     * @return Returns true to indicate that the window should be shown.
+     * @see #onShowInputRequested(int, boolean)
+     */
+    private boolean dispatchOnShowInputRequested(int flags, boolean configChange) {
+        final boolean result = onShowInputRequested(flags, configChange);
+        if (result) {
+            mShowInputFlags = flags;
+        } else {
+            mShowInputFlags = 0;
+        }
+        return result;
+    }
+
     public void showWindow(boolean showInput) {
         if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput
                 + " mShowInputRequested=" + mShowInputRequested
                 + " mWindowAdded=" + mWindowAdded
                 + " mWindowCreated=" + mWindowCreated
                 + " mWindowVisible=" + mWindowVisible
-                + " mInputStarted=" + mInputStarted);
-        
+                + " mInputStarted=" + mInputStarted
+                + " mShowInputFlags=" + mShowInputFlags);
+
         if (mInShowWindow) {
             Log.w(TAG, "Re-entrance in to showWindow");
             return;
@@ -2573,7 +2597,6 @@
         
         p.println("  mShowInputRequested=" + mShowInputRequested
                 + " mLastShowInputRequested=" + mLastShowInputRequested
-                + " mShowInputForced=" + mShowInputForced
                 + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
         p.println("  mCandidatesVisibility=" + mCandidatesVisibility
                 + " mFullscreenApplied=" + mFullscreenApplied
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index f0673ff..a025337 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -767,6 +767,28 @@
     }
 
     /**
+     * Returns a {@link Network} object corresponding to the currently active
+     * default data network for a specific UID.  In the event that the default data
+     * network disconnects, the returned {@code Network} object will no longer
+     * be usable.  This will return {@code null} when there is no default
+     * network for the UID.
+     * <p>This method requires the caller to hold the permission
+     * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}.
+     *
+     * @return a {@link Network} object for the current default network for the
+     *         given UID or {@code null} if no default network is currently active
+     *
+     * @hide
+     */
+    public Network getActiveNetworkForUid(int uid) {
+        try {
+            return mService.getActiveNetworkForUid(uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Configures an always-on VPN connection through a specific application.
      * This connection is automatically granted and persisted after a reboot.
      *
@@ -3021,7 +3043,6 @@
      *
      * @param networkCallback The {@link NetworkCallback} that the system will call as the
      *                        system default network changes.
-     * @hide
      */
     public void registerDefaultNetworkCallback(NetworkCallback networkCallback) {
         // This works because if the NetworkCapabilities are null,
diff --git a/core/java/android/net/ConnectivityMetricsEvent.aidl b/core/java/android/net/ConnectivityMetricsEvent.aidl
index da17561..a027d7c 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.aidl
+++ b/core/java/android/net/ConnectivityMetricsEvent.aidl
@@ -17,3 +17,4 @@
 package android.net;
 
 parcelable ConnectivityMetricsEvent;
+parcelable ConnectivityMetricsEvent.Reference;
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index 098f1e6..b5d67d3 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -78,4 +78,42 @@
         return String.format("ConnectivityMetricsEvent(%d, %d, %d)", timestamp,
                 componentTag, eventTag);
     }
+
+    /** {@hide} */
+    public static class Reference implements Parcelable {
+
+        public long value;
+
+        public Reference(long ref) {
+            this.value = ref;
+        }
+
+        /** Implement the Parcelable interface */
+        public static final Parcelable.Creator<Reference> CREATOR
+                = new Parcelable.Creator<Reference> (){
+            public Reference createFromParcel(Parcel source) {
+                return new Reference(source.readLong());
+            }
+
+            public Reference[] newArray(int size) {
+                return new Reference[size];
+            }
+        };
+
+        /** Implement the Parcelable interface */
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        /** Implement the Parcelable interface */
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeLong(value);
+        }
+
+        public void readFromParcel(Parcel in) {
+            value = in.readLong();
+        }
+    }
 }
diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java
index 3ef8050..eafb8ac 100644
--- a/core/java/android/net/ConnectivityMetricsLogger.java
+++ b/core/java/android/net/ConnectivityMetricsLogger.java
@@ -15,6 +15,7 @@
  */
 package android.net;
 
+import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -28,14 +29,24 @@
     public static final String CONNECTIVITY_METRICS_LOGGER_SERVICE = "connectivity_metrics_logger";
 
     // Component Tags
-    public static final int COMPONENT_TAG_CONNECTIVITY = 1;
-    public static final int COMPONENT_TAG_BLUETOOTH = 2;
-    public static final int COMPONENT_TAG_WIFI = 3;
-    public static final int COMPONENT_TAG_TELECOM = 4;
-    public static final int COMPONENT_TAG_TELEPHONY = 5;
+    public static final int COMPONENT_TAG_CONNECTIVITY = 0;
+    public static final int COMPONENT_TAG_BLUETOOTH = 1;
+    public static final int COMPONENT_TAG_WIFI = 2;
+    public static final int COMPONENT_TAG_TELECOM = 3;
+    public static final int COMPONENT_TAG_TELEPHONY = 4;
+
+    public static final int NUMBER_OF_COMPONENTS = 5;
+
+    // Event Tag
+    public static final int TAG_SKIPPED_EVENTS = -1;
+
+    public static final String DATA_KEY_EVENTS_COUNT = "count";
 
     private IConnectivityMetricsLogger mService;
 
+    private long mServiceUnblockedTimestampMillis = 0;
+    private int mNumSkippedEvents = 0;
+
     public ConnectivityMetricsLogger() {
         mService = IConnectivityMetricsLogger.Stub.asInterface(ServiceManager.getService(
                 CONNECTIVITY_METRICS_LOGGER_SERVICE));
@@ -46,12 +57,51 @@
             if (DBG) {
                 Log.d(TAG, "logEvent(" + componentTag + "," + eventTag + ") Service not ready");
             }
-        } else {
-            try {
-                mService.logEvent(new ConnectivityMetricsEvent(timestamp, componentTag, eventTag, data));
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error logging event " + e.getMessage());
+            return;
+        }
+
+        if (mServiceUnblockedTimestampMillis > 0) {
+            if (System.currentTimeMillis() < mServiceUnblockedTimestampMillis) {
+                // Service is throttling events.
+                // Don't send new events because they will be dropped.
+                mNumSkippedEvents++;
+                return;
             }
         }
+
+        ConnectivityMetricsEvent skippedEventsEvent = null;
+        if (mNumSkippedEvents > 0) {
+            // Log number of skipped events
+            Bundle b = new Bundle();
+            b.putInt(DATA_KEY_EVENTS_COUNT, mNumSkippedEvents);
+            skippedEventsEvent = new ConnectivityMetricsEvent(mServiceUnblockedTimestampMillis,
+                    componentTag, TAG_SKIPPED_EVENTS, b);
+
+            mServiceUnblockedTimestampMillis = 0;
+        }
+
+        ConnectivityMetricsEvent event = new ConnectivityMetricsEvent(timestamp, componentTag,
+                eventTag, data);
+
+        try {
+            long result;
+            if (skippedEventsEvent == null) {
+                result = mService.logEvent(event);
+            } else {
+                result = mService.logEvents(new ConnectivityMetricsEvent[]
+                        {skippedEventsEvent, event});
+            }
+
+            if (result == 0) {
+                mNumSkippedEvents = 0;
+            } else {
+                mNumSkippedEvents++;
+                if (result > 0) { // events are throttled
+                    mServiceUnblockedTimestampMillis = result;
+                }
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error logging event " + e.getMessage());
+        }
     }
 }
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 97bd5d2..8c5f603 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -40,6 +40,9 @@
 
     public int leaseDuration;
 
+    /** Link MTU option. 0 means unset. */
+    public int mtu;
+
     public DhcpResults() {
         super();
     }
@@ -57,19 +60,7 @@
             serverAddress = source.serverAddress;
             vendorInfo = source.vendorInfo;
             leaseDuration = source.leaseDuration;
-        }
-    }
-
-    /**
-     * Updates the DHCP fields that need to be retained from
-     * original DHCP request if the current renewal shows them
-     * being empty.
-     */
-    public void updateFromDhcpRequest(DhcpResults orig) {
-        if (orig == null) return;
-        if (gateway == null) gateway = orig.gateway;
-        if (dnsServers.size() == 0) {
-            dnsServers.addAll(orig.dnsServers);
+            mtu = source.mtu;
         }
     }
 
@@ -89,6 +80,7 @@
         super.clear();
         vendorInfo = null;
         leaseDuration = 0;
+        mtu = 0;
     }
 
     @Override
@@ -98,6 +90,7 @@
         str.append(" DHCP server ").append(serverAddress);
         str.append(" Vendor info ").append(vendorInfo);
         str.append(" lease ").append(leaseDuration).append(" seconds");
+        if (mtu != 0) str.append(" MTU ").append(mtu);
 
         return str.toString();
     }
@@ -113,7 +106,8 @@
         return super.equals((StaticIpConfiguration) obj) &&
                 Objects.equals(serverAddress, target.serverAddress) &&
                 Objects.equals(vendorInfo, target.vendorInfo) &&
-                leaseDuration == target.leaseDuration;
+                leaseDuration == target.leaseDuration &&
+                mtu == target.mtu;
     }
 
     /** Implement the Parcelable interface */
@@ -134,6 +128,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         super.writeToParcel(dest, flags);
         dest.writeInt(leaseDuration);
+        dest.writeInt(mtu);
         NetworkUtils.parcelInetAddress(dest, serverAddress, flags);
         dest.writeString(vendorInfo);
     }
@@ -141,6 +136,7 @@
     private static void readFromParcel(DhcpResults dhcpResults, Parcel in) {
         StaticIpConfiguration.readFromParcel(dhcpResults, in);
         dhcpResults.leaseDuration = in.readInt();
+        dhcpResults.mtu = in.readInt();
         dhcpResults.serverAddress = (Inet4Address) NetworkUtils.unparcelInetAddress(in);
         dhcpResults.vendorInfo = in.readString();
     }
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java
deleted file mode 100644
index 7acf3f5..0000000
--- a/core/java/android/net/DnsPinger.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.internal.util.Protocol;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketTimeoutException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Performs a simple DNS "ping" by sending a "server status" query packet to the
- * DNS server. As long as the server replies, we consider it a success.
- * <p>
- * We do not use a simple hostname lookup because that could be cached and the
- * API may not differentiate between a time out and a failure lookup (which we
- * really care about).
- * <p>
- *
- * @hide
- */
-public final class DnsPinger extends Handler {
-    private static final boolean DBG = false;
-
-    private static final int RECEIVE_POLL_INTERVAL_MS = 200;
-    private static final int DNS_PORT = 53;
-
-    /** Short socket timeout so we don't block one any 'receive' call */
-    private static final int SOCKET_TIMEOUT_MS = 1;
-
-    /** Used to generate IDs */
-    private static final Random sRandom = new Random();
-    private static final AtomicInteger sCounter = new AtomicInteger();
-
-    private ConnectivityManager mConnectivityManager = null;
-    private final Context mContext;
-    private final int mConnectionType;
-    private final Handler mTarget;
-    private final ArrayList<InetAddress> mDefaultDns;
-    private String TAG;
-
-    //Invalidates old dns requests upon a cancel
-    private AtomicInteger mCurrentToken = new AtomicInteger();
-
-    private static final int BASE = Protocol.BASE_DNS_PINGER;
-
-    /**
-     * Async response packet for dns pings.
-     * arg1 is the ID of the ping, also returned by {@link #pingDnsAsync(InetAddress, int, int)}
-     * arg2 is the delay, or is negative on error.
-     */
-    public static final int DNS_PING_RESULT = BASE;
-    /** An error code for a {@link #DNS_PING_RESULT} packet */
-    public static final int TIMEOUT = -1;
-    /** An error code for a {@link #DNS_PING_RESULT} packet */
-    public static final int SOCKET_EXCEPTION = -2;
-
-    /**
-     * Send a new ping via a socket.  arg1 is ID, arg2 is timeout, obj is InetAddress to ping
-     */
-    private static final int ACTION_PING_DNS = BASE + 1;
-    private static final int ACTION_LISTEN_FOR_RESPONSE = BASE + 2;
-    private static final int ACTION_CANCEL_ALL_PINGS = BASE + 3;
-
-    private List<ActivePing> mActivePings = new ArrayList<ActivePing>();
-    private int mEventCounter;
-
-    private class ActivePing {
-        DatagramSocket socket;
-        int internalId;
-        short packetId;
-        int timeout;
-        Integer result;
-        long start = SystemClock.elapsedRealtime();
-    }
-
-    /* Message argument for ACTION_PING_DNS */
-    private class DnsArg {
-        InetAddress dns;
-        int seq;
-
-        DnsArg(InetAddress d, int s) {
-            dns = d;
-            seq = s;
-        }
-    }
-
-    public DnsPinger(Context context, String TAG, Looper looper,
-            Handler target, int connectionType) {
-        super(looper);
-        this.TAG = TAG;
-        mContext = context;
-        mTarget = target;
-        mConnectionType = connectionType;
-        if (!ConnectivityManager.isNetworkTypeValid(connectionType)) {
-            throw new IllegalArgumentException("Invalid connectionType in constructor: "
-                    + connectionType);
-        }
-        mDefaultDns = new ArrayList<InetAddress>();
-        mDefaultDns.add(getDefaultDns());
-        mEventCounter = 0;
-    }
-
-    @Override
-    public void handleMessage(Message msg) {
-        switch (msg.what) {
-            case ACTION_PING_DNS:
-                DnsArg dnsArg = (DnsArg) msg.obj;
-                if (dnsArg.seq != mCurrentToken.get()) {
-                    break;
-                }
-                try {
-                    ActivePing newActivePing = new ActivePing();
-                    InetAddress dnsAddress = dnsArg.dns;
-                    newActivePing.internalId = msg.arg1;
-                    newActivePing.timeout = msg.arg2;
-                    newActivePing.socket = new DatagramSocket();
-                    // Set some socket properties
-                    newActivePing.socket.setSoTimeout(SOCKET_TIMEOUT_MS);
-
-                    // Try to bind but continue ping if bind fails
-                    try {
-                        newActivePing.socket.setNetworkInterface(NetworkInterface.getByName(
-                                getCurrentLinkProperties().getInterfaceName()));
-                    } catch (Exception e) {
-                        loge("sendDnsPing::Error binding to socket " + e);
-                    }
-
-                    newActivePing.packetId = (short) sRandom.nextInt();
-                    byte[] buf = mDnsQuery.clone();
-                    buf[0] = (byte) (newActivePing.packetId >> 8);
-                    buf[1] = (byte) newActivePing.packetId;
-
-                    // Send the DNS query
-                    DatagramPacket packet = new DatagramPacket(buf,
-                            buf.length, dnsAddress, DNS_PORT);
-                    if (DBG) {
-                        log("Sending a ping " + newActivePing.internalId +
-                                " to " + dnsAddress.getHostAddress()
-                                + " with packetId " + newActivePing.packetId + ".");
-                    }
-
-                    newActivePing.socket.send(packet);
-                    mActivePings.add(newActivePing);
-                    mEventCounter++;
-                    sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0),
-                            RECEIVE_POLL_INTERVAL_MS);
-                } catch (IOException e) {
-                    sendResponse(msg.arg1, -9999, SOCKET_EXCEPTION);
-                }
-                break;
-            case ACTION_LISTEN_FOR_RESPONSE:
-                if (msg.arg1 != mEventCounter) {
-                    break;
-                }
-                for (ActivePing curPing : mActivePings) {
-                    try {
-                        /** Each socket will block for {@link #SOCKET_TIMEOUT_MS} in receive() */
-                        byte[] responseBuf = new byte[2];
-                        DatagramPacket replyPacket = new DatagramPacket(responseBuf, 2);
-                        curPing.socket.receive(replyPacket);
-                        // Check that ID field matches (we're throwing out the rest of the packet)
-                        if (responseBuf[0] == (byte) (curPing.packetId >> 8) &&
-                                responseBuf[1] == (byte) curPing.packetId) {
-                            curPing.result =
-                                    (int) (SystemClock.elapsedRealtime() - curPing.start);
-                        } else {
-                            if (DBG) {
-                                log("response ID didn't match, ignoring packet");
-                            }
-                        }
-                    } catch (SocketTimeoutException e) {
-                        // A timeout here doesn't mean anything - squelsh this exception
-                    } catch (Exception e) {
-                        if (DBG) {
-                            log("DnsPinger.pingDns got socket exception: " + e);
-                        }
-                        curPing.result = SOCKET_EXCEPTION;
-                    }
-                }
-                Iterator<ActivePing> iter = mActivePings.iterator();
-                while (iter.hasNext()) {
-                   ActivePing curPing = iter.next();
-                   if (curPing.result != null) {
-                       sendResponse(curPing.internalId, curPing.packetId, curPing.result);
-                       curPing.socket.close();
-                       iter.remove();
-                   } else if (SystemClock.elapsedRealtime() >
-                                  curPing.start + curPing.timeout) {
-                       sendResponse(curPing.internalId, curPing.packetId, TIMEOUT);
-                       curPing.socket.close();
-                       iter.remove();
-                   }
-                }
-                if (!mActivePings.isEmpty()) {
-                    sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0),
-                            RECEIVE_POLL_INTERVAL_MS);
-                }
-                break;
-            case ACTION_CANCEL_ALL_PINGS:
-                for (ActivePing activePing : mActivePings)
-                    activePing.socket.close();
-                mActivePings.clear();
-                break;
-        }
-    }
-
-    /**
-     * Returns a list of DNS addresses, coming from either the link properties of the
-     * specified connection or the default system DNS if the link properties has no dnses.
-     * @return a non-empty non-null list
-     */
-    public List<InetAddress> getDnsList() {
-        LinkProperties curLinkProps = getCurrentLinkProperties();
-        if (curLinkProps == null) {
-            loge("getCurLinkProperties:: LP for type" + mConnectionType + " is null!");
-            return mDefaultDns;
-        }
-
-        Collection<InetAddress> dnses = curLinkProps.getDnsServers();
-        if (dnses == null || dnses.size() == 0) {
-            loge("getDns::LinkProps has null dns - returning default");
-            return mDefaultDns;
-        }
-
-        return new ArrayList<InetAddress>(dnses);
-    }
-
-    /**
-     * Send a ping.  The response will come via a {@link #DNS_PING_RESULT} to the handler
-     * specified at creation.
-     * @param dns address of dns server to ping
-     * @param timeout timeout for ping
-     * @return an ID field, which will also be included in the {@link #DNS_PING_RESULT} message.
-     */
-    public int pingDnsAsync(InetAddress dns, int timeout, int delay) {
-        int id = sCounter.incrementAndGet();
-        sendMessageDelayed(obtainMessage(ACTION_PING_DNS, id, timeout,
-                new DnsArg(dns, mCurrentToken.get())), delay);
-        return id;
-    }
-
-    public void cancelPings() {
-        mCurrentToken.incrementAndGet();
-        obtainMessage(ACTION_CANCEL_ALL_PINGS).sendToTarget();
-    }
-
-    private void sendResponse(int internalId, int externalId, int responseVal) {
-        if(DBG) {
-            log("Responding to packet " + internalId +
-                    " externalId " + externalId +
-                    " and val " + responseVal);
-        }
-        mTarget.sendMessage(obtainMessage(DNS_PING_RESULT, internalId, responseVal));
-    }
-
-    private LinkProperties getCurrentLinkProperties() {
-        if (mConnectivityManager == null) {
-            mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
-                    Context.CONNECTIVITY_SERVICE);
-        }
-
-        return mConnectivityManager.getLinkProperties(mConnectionType);
-    }
-
-    private InetAddress getDefaultDns() {
-        String dns = Settings.Global.getString(mContext.getContentResolver(),
-                Settings.Global.DEFAULT_DNS_SERVER);
-        if (dns == null || dns.length() == 0) {
-            dns = mContext.getResources().getString(
-                    com.android.internal.R.string.config_default_dns_server);
-        }
-        try {
-            return NetworkUtils.numericToInetAddress(dns);
-        } catch (IllegalArgumentException e) {
-            loge("getDefaultDns::malformed default dns address");
-            return null;
-        }
-    }
-
-    private static final byte[] mDnsQuery = new byte[] {
-        0, 0, // [0-1] is for ID (will set each time)
-        1, 0, // [2-3] are flags.  Set byte[2] = 1 for recursion desired (RD) on.  Currently on.
-        0, 1, // [4-5] bytes are for number of queries (QCOUNT)
-        0, 0, // [6-7] unused count field for dns response packets
-        0, 0, // [8-9] unused count field for dns response packets
-        0, 0, // [10-11] unused count field for dns response packets
-        3, 'w', 'w', 'w',
-        6, 'g', 'o', 'o', 'g', 'l', 'e',
-        3, 'c', 'o', 'm',
-        0,    // null terminator of address (also called empty TLD)
-        0, 1, // QTYPE, set to 1 = A (host address)
-        0, 1  // QCLASS, set to 1 = IN (internet)
-    };
-
-    private void log(String s) {
-        Log.d(TAG, s);
-    }
-
-    private void loge(String s) {
-        Log.e(TAG, s);
-    }
-}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 1a9c9ea..c897c45 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -44,6 +44,7 @@
 interface IConnectivityManager
 {
     Network getActiveNetwork();
+    Network getActiveNetworkForUid(int uid);
     NetworkInfo getActiveNetworkInfo();
     NetworkInfo getActiveNetworkInfoForUid(int uid);
     NetworkInfo getNetworkInfo(int networkType);
diff --git a/core/java/android/net/IConnectivityMetricsLogger.aidl b/core/java/android/net/IConnectivityMetricsLogger.aidl
index 2778671..a83a019 100644
--- a/core/java/android/net/IConnectivityMetricsLogger.aidl
+++ b/core/java/android/net/IConnectivityMetricsLogger.aidl
@@ -16,15 +16,28 @@
 
 package android.net;
 
+import android.app.PendingIntent;
 import android.net.ConnectivityMetricsEvent;
-import android.net.IConnectivityMetricsLoggerSubscriber;
 
 /** {@hide} */
 interface IConnectivityMetricsLogger {
 
-    void logEvent(in ConnectivityMetricsEvent event);
-    void logEvents(in ConnectivityMetricsEvent[] events);
+    /**
+     * @return 0 on success
+     *        <0 if error happened
+     *        >0 timestamp after which new events will be accepted
+     */
+    long logEvent(in ConnectivityMetricsEvent event);
+    long logEvents(in ConnectivityMetricsEvent[] events);
 
-    boolean subscribe(in IConnectivityMetricsLoggerSubscriber subscriber);
-    void unsubscribe(in IConnectivityMetricsLoggerSubscriber subscriber);
+    /**
+     * @param reference of the last event previously returned. The function will return
+     *                  events following it.
+     *                  If 0 then all events will be returned.
+     *                  After the function call it will contain reference of the last event.
+     */
+    ConnectivityMetricsEvent[] getEvents(inout ConnectivityMetricsEvent.Reference reference);
+
+    boolean register(in PendingIntent newEventsIntent);
+    void unregister(in PendingIntent newEventsIntent);
 }
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index e555fa4..29291ca 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -19,11 +19,9 @@
 import android.Manifest;
 import android.Manifest.permission;
 import android.annotation.Nullable;
-import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.UserHandle;
@@ -69,12 +67,32 @@
          */
         public final String mConfigurationActivityClassName;
 
+        /**
+         * Optional class name of the scoring service we can bind to. Null if none is set.
+         */
+        public final String mScoringServiceClassName;
+
         public NetworkScorerAppData(String packageName, int packageUid, CharSequence scorerName,
-                @Nullable String configurationActivityClassName) {
+                @Nullable String configurationActivityClassName,
+                @Nullable String scoringServiceClassName) {
             mScorerName = scorerName;
             mPackageName = packageName;
             mPackageUid = packageUid;
             mConfigurationActivityClassName = configurationActivityClassName;
+            mScoringServiceClassName = scoringServiceClassName;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("NetworkScorerAppData{");
+            sb.append("mPackageName='").append(mPackageName).append('\'');
+            sb.append(", mPackageUid=").append(mPackageUid);
+            sb.append(", mScorerName=").append(mScorerName);
+            sb.append(", mConfigurationActivityClassName='").append(mConfigurationActivityClassName)
+                    .append('\'');
+            sb.append(", mScoringServiceClassName='").append(mScoringServiceClassName).append('\'');
+            sb.append('}');
+            return sb.toString();
         }
     }
 
@@ -128,18 +146,27 @@
             Intent intent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE);
             intent.setPackage(receiverInfo.packageName);
             List<ResolveInfo> configActivities = pm.queryIntentActivities(intent, 0 /* flags */);
-            if (!configActivities.isEmpty()) {
+            if (configActivities != null && !configActivities.isEmpty()) {
                 ActivityInfo activityInfo = configActivities.get(0).activityInfo;
                 if (activityInfo != null) {
                     configurationActivityClassName = activityInfo.name;
                 }
             }
 
+            // Find the scoring service class we can bind to, if any.
+            String scoringServiceClassName = null;
+            Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS);
+            serviceIntent.setPackage(receiverInfo.packageName);
+            ResolveInfo resolveServiceInfo = pm.resolveService(serviceIntent, 0 /* flags */);
+            if (resolveServiceInfo != null && resolveServiceInfo.serviceInfo != null) {
+                scoringServiceClassName = resolveServiceInfo.serviceInfo.name;
+            }
+
             // NOTE: loadLabel will attempt to load the receiver's label and fall back to the
             // app label if none is present.
             scorers.add(new NetworkScorerAppData(receiverInfo.packageName,
                     receiverInfo.applicationInfo.uid, receiverInfo.loadLabel(pm),
-                    configurationActivityClassName));
+                    configurationActivityClassName, scoringServiceClassName));
         }
 
         return scorers;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8e2dd6b..c452837 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -448,19 +448,41 @@
         public abstract Timer getForegroundActivityTimer();
         public abstract Timer getBluetoothScanTimer();
 
-        // Time this uid has any processes in the top state.
+        // Note: the following times are disjoint.  They can be added together to find the
+        // total time a uid has had any processes running at all.
+
+        /**
+         * Time this uid has any processes in the top state (or above such as persistent).
+         */
         public static final int PROCESS_STATE_TOP = 0;
-        // Time this uid has any process with a started out bound foreground service.
+        /**
+         * Time this uid has any process with a started out bound foreground service, but
+         * none in the "top" state.
+         */
         public static final int PROCESS_STATE_FOREGROUND_SERVICE = 1;
-        // Time this uid has any process that is top while the device is sleeping.
+        /**
+         * Time this uid has any process that is top while the device is sleeping, but none
+         * in the "foreground service" or better state.
+         */
         public static final int PROCESS_STATE_TOP_SLEEPING = 2;
-        // Time this uid has any process in an active foreground state.
+        /**
+         * Time this uid has any process in an active foreground state, but none in the
+         * "top sleeping" or better state.
+         */
         public static final int PROCESS_STATE_FOREGROUND = 3;
-        // Time this uid has any process in an active background state.
+        /**
+         * Time this uid has any process in an active background state, but none in the
+         * "foreground" or better state.
+         */
         public static final int PROCESS_STATE_BACKGROUND = 4;
-        // Time this uid has any processes running at all.
+        /**
+         * Time this uid has any processes that are sitting around cached, not in one of the
+         * other active states.
+         */
         public static final int PROCESS_STATE_CACHED = 5;
-        // Total number of process states we track.
+        /**
+         * Total number of process states we track.
+         */
         public static final int NUM_PROCESS_STATE = 6;
 
         static final String[] PROCESS_STATE_NAMES = {
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 878b7a0..3c7c962 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -231,6 +231,18 @@
         mAsynchronous = async;
     }
 
+    /** {@hide} */
+    public String getTraceName(Message message) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getName()).append(": ");
+        if (message.callback != null) {
+            sb.append(message.callback.getClass().getName());
+        } else {
+            sb.append("#").append(message.what);
+        }
+        return sb.toString();
+    }
+
     /**
      * Returns a string representing the name of the specified message.
      * The default implementation will either return the class name of the
@@ -739,8 +751,8 @@
         message.callback.run();
     }
 
-    final MessageQueue mQueue;
     final Looper mLooper;
+    final MessageQueue mQueue;
     final Callback mCallback;
     final boolean mAsynchronous;
     IMessenger mMessenger;
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 24a6cdf..68b0a9f 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -328,11 +328,6 @@
      */
     void setDnsServersForNetwork(int netId, in String[] servers, String domains);
 
-    /**
-     * Flush the DNS cache associated with the specified network.
-     */
-    void flushNetworkDnsCache(int netId);
-
     void setFirewallEnabled(boolean enabled);
     boolean isFirewallEnabled();
     void setFirewallInterfaceRule(String iface, boolean allow);
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 34c880f..b58ff1f 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -72,6 +72,7 @@
     final Thread mThread;
 
     private Printer mLogging;
+    private long mTraceTag;
 
      /** Initialize the current thread as a looper.
       * This gives you a chance to create handlers that then reference
@@ -139,13 +140,23 @@
             }
 
             // This must be in a local variable, in case a UI event sets the logger
-            Printer logging = me.mLogging;
+            final Printer logging = me.mLogging;
             if (logging != null) {
                 logging.println(">>>>> Dispatching to " + msg.target + " " +
                         msg.callback + ": " + msg.what);
             }
 
-            msg.target.dispatchMessage(msg);
+            final long traceTag = me.mTraceTag;
+            if (traceTag != 0) {
+                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
+            }
+            try {
+                msg.target.dispatchMessage(msg);
+            } finally {
+                if (traceTag != 0) {
+                    Trace.traceEnd(traceTag);
+                }
+            }
 
             if (logging != null) {
                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
@@ -208,6 +219,11 @@
         mLogging = printer;
     }
 
+    /** {@hide} */
+    public void setTraceTag(long traceTag) {
+        mTraceTag = traceTag;
+    }
+
     /**
      * Quits the looper.
      * <p>
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a0a16f1..92edc62 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -221,7 +221,7 @@
     /**
      * Wake lock level: Enables Sustained Performance Mode.
      * <p>
-     * This is used by Gaming and VR applications to ensure the device provides
+     * This is used by Gaming and VR applications to ensure the device
      * will provide consistent performance over a large amount of time.
      * </p>
      */
@@ -1031,6 +1031,16 @@
     }
 
     /**
+     * Returns True if the device supports Sustained Performance Mode.
+     * Applications Should check if the device supports this mode, before
+     * using {@link #SUSTAINED_PERFORMANCE_WAKE_LOCK}.
+     */
+    public boolean isSustainedPerformanceModeSupported() {
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_sustainedPerformanceModeSupported);
+    }
+
+    /**
      * Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
      * This broadcast is only sent to registered receivers.
      */
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 720d3f7..ece1228 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -83,6 +83,8 @@
     public static final String PROP_FORCE_ADOPTABLE = "persist.fw.force_adoptable";
     /** {@hide} */
     public static final String PROP_EMULATE_FBE = "persist.sys.emulate_fbe";
+    /** {@hide} */
+    public static final String PROP_SDCARDFS = "persist.sys.sdcardfs";
 
     /** {@hide} */
     public static final String UUID_PRIVATE_INTERNAL = null;
@@ -93,6 +95,10 @@
     public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0;
     /** {@hide} */
     public static final int DEBUG_EMULATE_FBE = 1 << 1;
+    /** {@hide} */
+    public static final int DEBUG_SDCARDFS_FORCE_ON = 1 << 2;
+    /** {@hide} */
+    public static final int DEBUG_SDCARDFS_FORCE_OFF = 1 << 3;
 
     // NOTE: keep in sync with installd
     /** {@hide} */
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index d41bc07..b1cad05 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -1184,10 +1184,9 @@
     
     /**
      * Called when the Preference hierarchy has been attached to the
-     * {@link PreferenceActivity} or {@link PreferenceFragment}. This can
-     * also be called when this Preference has been attached to a group
-     * that was already attached to the {@link PreferenceActivity} or
-     * {@link PreferenceFragment}.
+     * {@link PreferenceActivity}. This can also be called when this
+     * Preference has been attached to a group that was already attached
+     * to the {@link PreferenceActivity}.
      */
     protected void onAttachedToActivity() {
         // At this point, the hierarchy that this preference is in is connected
@@ -1195,16 +1194,6 @@
         registerDependency();
     }
 
-    /**
-     * Called when the Preference hierarchy has been detached from the
-     * {@link PreferenceActivity} or {@link PreferenceFragment}. This can
-     * also be called when this Preference has been removed from a group
-     * that was already attached to the {@link PreferenceActivity} or
-     * {@link PreferenceFragment}.
-     */
-    protected void onDetachedFromActivity() {
-    }
-
     private void registerDependency() {
         
         if (TextUtils.isEmpty(mDependencyKey)) return;
diff --git a/core/java/android/preference/PreferenceGroup.java b/core/java/android/preference/PreferenceGroup.java
index 13c3661..f17506b 100644
--- a/core/java/android/preference/PreferenceGroup.java
+++ b/core/java/android/preference/PreferenceGroup.java
@@ -186,11 +186,7 @@
     private boolean removePreferenceInt(Preference preference) {
         synchronized(this) {
             preference.onPrepareForRemoval();
-            boolean success = mPreferenceList.remove(preference);
-            if (mAttachedToActivity) {
-                preference.onDetachedFromActivity();
-            }
-            return success;
+            return mPreferenceList.remove(preference);
         }
     }
     
@@ -266,7 +262,7 @@
     protected boolean isOnSameScreenAsChildren() {
         return true;
     }
-
+    
     @Override
     protected void onAttachedToActivity() {
         super.onAttachedToActivity();
@@ -283,17 +279,11 @@
     }
 
     @Override
-    protected void onDetachedFromActivity() {
-        super.onDetachedFromActivity();
-
+    protected void onPrepareForRemoval() {
+        super.onPrepareForRemoval();
+        
         // We won't be attached to the activity anymore
         mAttachedToActivity = false;
-
-        // Dispatch to all contained preferences
-        final int preferenceCount = getPreferenceCount();
-        for (int i = 0; i < preferenceCount; i++) {
-            getPreference(i).onDetachedFromActivity();
-        }
     }
 
     @Override
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index 73174e3..1a6b06f 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -519,9 +519,6 @@
      */
     boolean setPreferences(PreferenceScreen preferenceScreen) {
         if (preferenceScreen != mPreferenceScreen) {
-            if (mPreferenceScreen != null) {
-                mPreferenceScreen.onDetachedFromActivity();
-            }
             mPreferenceScreen = preferenceScreen;
             return true;
         }
@@ -830,11 +827,7 @@
      */
     void dispatchActivityDestroy() {
         List<OnActivityDestroyListener> list = null;
-
-        if (mPreferenceScreen != null) {
-            mPreferenceScreen.onDetachedFromActivity();
-            mPreferenceScreen = null;
-        }
+        
         synchronized (this) {
             if (mActivityDestroyListeners != null) {
                 list = new ArrayList<OnActivityDestroyListener>(mActivityDestroyListeners);
diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java
index e9c196d..721c94e 100644
--- a/core/java/android/print/PrintAttributes.java
+++ b/core/java/android/print/PrintAttributes.java
@@ -20,6 +20,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources.NotFoundException;
@@ -31,6 +32,7 @@
 import android.util.Log;
 
 import com.android.internal.R;
+import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -49,7 +51,7 @@
     @IntDef(flag = true, value = {
             COLOR_MODE_MONOCHROME, COLOR_MODE_COLOR
     })
-    public @interface ColorMode {
+    @interface ColorMode {
     }
     /** Color mode: Monochrome color scheme, for example one color is used. */
     public static final int COLOR_MODE_MONOCHROME = 1 << 0;
@@ -64,7 +66,7 @@
     @IntDef(flag = true, value = {
             DUPLEX_MODE_NONE, DUPLEX_MODE_LONG_EDGE, DUPLEX_MODE_SHORT_EDGE
     })
-    public @interface DuplexMode {
+    @interface DuplexMode {
     }
     /** Duplex mode: No duplexing. */
     public static final int DUPLEX_MODE_NONE = 1 << 0;
@@ -76,23 +78,29 @@
     private static final int VALID_DUPLEX_MODES =
             DUPLEX_MODE_NONE | DUPLEX_MODE_LONG_EDGE | DUPLEX_MODE_SHORT_EDGE;
 
-    private MediaSize mMediaSize;
-    private Resolution mResolution;
-    private Margins mMinMargins;
+    private @Nullable MediaSize mMediaSize;
+    private @Nullable Resolution mResolution;
+    private @Nullable Margins mMinMargins;
 
-    private int mColorMode;
-    private int mDuplexMode;
+    private @IntRange(from = 0) int mColorMode;
+    private @IntRange(from = 0) int mDuplexMode;
 
     PrintAttributes() {
         /* hide constructor */
     }
 
     private PrintAttributes(@NonNull Parcel parcel) {
-        mMediaSize = (parcel.readInt() ==  1) ? MediaSize.createFromParcel(parcel) : null;
-        mResolution = (parcel.readInt() ==  1) ? Resolution.createFromParcel(parcel) : null;
-        mMinMargins = (parcel.readInt() ==  1) ? Margins.createFromParcel(parcel) : null;
+        mMediaSize = (parcel.readInt() == 1) ? MediaSize.createFromParcel(parcel) : null;
+        mResolution = (parcel.readInt() == 1) ? Resolution.createFromParcel(parcel) : null;
+        mMinMargins = (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null;
         mColorMode = parcel.readInt();
+        if (mColorMode != 0) {
+            enforceValidColorMode(mColorMode);
+        }
         mDuplexMode = parcel.readInt();
+        if (mDuplexMode != 0) {
+            enforceValidDuplexMode(mDuplexMode);
+        }
     }
 
     /**
@@ -179,7 +187,7 @@
      * @see #COLOR_MODE_COLOR
      * @see #COLOR_MODE_MONOCHROME
      */
-    public @ColorMode int getColorMode() {
+    public @IntRange(from = 0) int getColorMode() {
         return mColorMode;
     }
 
@@ -214,13 +222,13 @@
     /**
      * Gets the duplex mode.
      *
-     * @return The duplex mode.
+     * @return The duplex mode or zero if not set.
      *
      * @see #DUPLEX_MODE_NONE
      * @see #DUPLEX_MODE_LONG_EDGE
      * @see #DUPLEX_MODE_SHORT_EDGE
      */
-    public @DuplexMode int getDuplexMode() {
+    public @IntRange(from = 0) int getDuplexMode() {
         return mDuplexMode;
     }
 
@@ -448,7 +456,7 @@
         private static final String LOG_TAG = "MediaSize";
 
         private static final Map<String, MediaSize> sIdToMediaSizeMap =
-                new ArrayMap<String, MediaSize>();
+                new ArrayMap<>();
 
         /**
          * Unknown media size in portrait mode.
@@ -781,15 +789,15 @@
                 new MediaSize("JPN_YOU4", "android",
                         R.string.mediasize_japanese_you4, 4134, 9252);
 
-        private final String mId;
+        private final @NonNull String mId;
         /**@hide */
-        public final String mLabel;
+        public final @NonNull String mLabel;
         /**@hide */
-        public final String mPackageName;
+        public final @Nullable String mPackageName;
         /**@hide */
-        public final int mLabelResId;
-        private final int mWidthMils;
-        private final int mHeightMils;
+        public final @StringRes int mLabelResId;
+        private final @IntRange(from = 1) int mWidthMils;
+        private final @IntRange(from = 1) int mHeightMils;
 
         /**
          * Creates a new instance.
@@ -808,29 +816,7 @@
          */
         public MediaSize(String id, String packageName, int labelResId,
                 int widthMils, int heightMils) {
-            if (TextUtils.isEmpty(id)) {
-                throw new IllegalArgumentException("id cannot be empty.");
-            }
-            if (TextUtils.isEmpty(packageName)) {
-                throw new IllegalArgumentException("packageName cannot be empty.");
-            }
-            if (labelResId <= 0) {
-                throw new IllegalArgumentException("labelResId must be greater than zero.");
-            }
-            if (widthMils <= 0) {
-                throw new IllegalArgumentException("widthMils "
-                        + "cannot be less than or equal to zero.");
-            }
-            if (heightMils <= 0) {
-                throw new IllegalArgumentException("heightMils "
-                       + "cannot be less than or euqual to zero.");
-            }
-            mPackageName = packageName;
-            mId = id;
-            mLabelResId = labelResId;
-            mWidthMils = widthMils;
-            mHeightMils = heightMils;
-            mLabel = null;
+            this(id, null, packageName, widthMils, heightMils, labelResId);
 
             // Build this mapping only for predefined media sizes.
             sIdToMediaSizeMap.put(mId, this);
@@ -851,26 +837,7 @@
          */
         public MediaSize(@NonNull String id, @NonNull String label,
                 @IntRange(from = 1) int widthMils, @IntRange(from = 1) int heightMils) {
-            if (TextUtils.isEmpty(id)) {
-                throw new IllegalArgumentException("id cannot be empty.");
-            }
-            if (TextUtils.isEmpty(label)) {
-                throw new IllegalArgumentException("label cannot be empty.");
-            }
-            if (widthMils <= 0) {
-                throw new IllegalArgumentException("widthMils "
-                        + "cannot be less than or equal to zero.");
-            }
-            if (heightMils <= 0) {
-                throw new IllegalArgumentException("heightMils "
-                       + "cannot be less than or euqual to zero.");
-            }
-            mId = id;
-            mLabel = label;
-            mWidthMils = widthMils;
-            mHeightMils = heightMils;
-            mLabelResId = 0;
-            mPackageName = null;
+            this(id, label, null, widthMils, heightMils, 0);
         }
 
         /**
@@ -890,15 +857,37 @@
             return definedMediaSizes;
         }
 
-        /** @hide */
-        public MediaSize(String id, String label, String packageName,
-                int widthMils, int heightMils, int labelResId) {
+        /**
+         * Creates a new instance.
+         *
+         * @param id The unique media size id. It is unique amongst other media sizes
+         *        supported by the printer.
+         * @param label The <strong>localized</strong> human readable label.
+         * @param packageName The name of the creating package.
+         * @param widthMils The width in mils (thousands of an inch).
+         * @param heightMils The height in mils (thousands of an inch).
+         * @param labelResId The resource if of a human readable label.
+         *
+         * @throws IllegalArgumentException If the id is empty or the label is unset
+         * or the widthMils is less than or equal to zero or the heightMils is less
+         * than or equal to zero.
+         *
+         * @hide
+         */
+        public MediaSize(String id, String label, String packageName, int widthMils, int heightMils,
+                int labelResId) {
             mPackageName = packageName;
-            mId = id;
+            mId = Preconditions.checkStringNotEmpty(id, "id cannot be empty.");
             mLabelResId = labelResId;
-            mWidthMils = widthMils;
-            mHeightMils = heightMils;
+            mWidthMils = Preconditions.checkArgumentPositive(widthMils, "widthMils cannot be " +
+                    "less than or equal to zero.");
+            mHeightMils = Preconditions.checkArgumentPositive(heightMils, "heightMils cannot be " +
+                    "less than or equal to zero.");
             mLabel = label;
+
+            // The label has to be either a string ot a StringRes
+            Preconditions.checkArgument(!TextUtils.isEmpty(label) !=
+                    (!TextUtils.isEmpty(packageName) && labelResId != 0), "label cannot be empty.");
         }
 
         /**
@@ -926,10 +915,7 @@
                 try {
                     return packageManager.getResourcesForApplication(
                             mPackageName).getString(mLabelResId);
-                } catch (NotFoundException nfe) {
-                    Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
-                            + " from package " + mPackageName);
-                } catch (NameNotFoundException nnfee) {
+                } catch (NotFoundException | NameNotFoundException e) {
                     Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
                             + " from package " + mPackageName);
                 }
@@ -1084,10 +1070,10 @@
      * the one with 300 DPI resolution.
      */
     public static final class Resolution {
-        private final String mId;
-        private final String mLabel;
-        private final int mHorizontalDpi;
-        private final int mVerticalDpi;
+        private final @NonNull String mId;
+        private final @NonNull String mLabel;
+        private final @IntRange(from = 1) int mHorizontalDpi;
+        private final @IntRange(from = 1) int mVerticalDpi;
 
         /**
          * Creates a new instance.
@@ -1244,8 +1230,7 @@
          * @param rightMils The right margin in mils (thousands of an inch).
          * @param bottomMils The bottom margin in mils (thousands of an inch).
          */
-        public Margins(@IntRange(from = 0) int leftMils, @IntRange(from = 0) int topMils,
-                @IntRange(from = 0) int rightMils, @IntRange(from = 0) int bottomMils) {
+        public Margins(int leftMils, int topMils, int rightMils, int bottomMils) {
             mTopMils = topMils;
             mLeftMils = leftMils;
             mRightMils = rightMils;
@@ -1257,7 +1242,7 @@
          *
          * @return The left margin.
          */
-        public @IntRange(from = 0) int getLeftMils() {
+        public int getLeftMils() {
             return mLeftMils;
         }
 
@@ -1266,7 +1251,7 @@
          *
          * @return The top margin.
          */
-        public @IntRange(from = 0) int getTopMils() {
+        public int getTopMils() {
             return mTopMils;
         }
 
@@ -1275,7 +1260,7 @@
          *
          * @return The right margin.
          */
-        public @IntRange(from = 0) int getRightMils() {
+        public int getRightMils() {
             return mRightMils;
         }
 
@@ -1284,7 +1269,7 @@
          *
          * @return The bottom margin.
          */
-        public @IntRange(from = 0) int getBottomMils() {
+        public int getBottomMils() {
             return mBottomMils;
         }
 
diff --git a/core/java/android/print/PrintDocumentInfo.java b/core/java/android/print/PrintDocumentInfo.java
index db3b6f4..bec6f29 100644
--- a/core/java/android/print/PrintDocumentInfo.java
+++ b/core/java/android/print/PrintDocumentInfo.java
@@ -22,6 +22,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
+import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -114,8 +115,8 @@
      */
     public static final int CONTENT_TYPE_PHOTO = 1;
 
-    private String mName;
-    private int mPageCount;
+    private @NonNull String mName;
+    private @IntRange(from = -1) int mPageCount;
     private int mContentType;
     private long mDataSize;
 
@@ -144,10 +145,11 @@
      * @param parcel Data from which to initialize.
      */
     private PrintDocumentInfo(Parcel parcel) {
-        mName = parcel.readString();
+        mName = Preconditions.checkStringNotEmpty(parcel.readString());
         mPageCount = parcel.readInt();
+        Preconditions.checkArgument(mPageCount == PAGE_COUNT_UNKNOWN || mPageCount > 0);
         mContentType = parcel.readInt();
-        mDataSize = parcel.readLong();
+        mDataSize = Preconditions.checkArgumentNonnegative(parcel.readLong());
     }
 
     /**
@@ -180,7 +182,7 @@
      * @see #CONTENT_TYPE_DOCUMENT
      * @see #CONTENT_TYPE_PHOTO
      */
-    public @ContentType int getContentType() {
+    public int getContentType() {
         return mContentType;
     }
 
@@ -262,13 +264,13 @@
         builder.append("PrintDocumentInfo{");
         builder.append("name=").append(mName);
         builder.append(", pageCount=").append(mPageCount);
-        builder.append(", contentType=").append(contentTyepToString(mContentType));
+        builder.append(", contentType=").append(contentTypeToString(mContentType));
         builder.append(", dataSize=").append(mDataSize);
         builder.append("}");
         return builder.toString();
     }
 
-    private String contentTyepToString(int contentType) {
+    private String contentTypeToString(int contentType) {
         switch (contentType) {
             case CONTENT_TYPE_DOCUMENT: {
                 return "CONTENT_TYPE_DOCUMENT";
diff --git a/core/java/android/print/PrinterCapabilitiesInfo.java b/core/java/android/print/PrinterCapabilitiesInfo.java
index d13879b..01c23f6 100644
--- a/core/java/android/print/PrinterCapabilitiesInfo.java
+++ b/core/java/android/print/PrinterCapabilitiesInfo.java
@@ -24,11 +24,13 @@
 import android.print.PrintAttributes.Margins;
 import android.print.PrintAttributes.MediaSize;
 import android.print.PrintAttributes.Resolution;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.function.IntConsumer;
 
 /**
  * This class represents the capabilities of a printer. Instances
@@ -55,9 +57,9 @@
 
     private static final Margins DEFAULT_MARGINS = new Margins(0,  0,  0,  0);
 
-    private Margins mMinMargins = DEFAULT_MARGINS;
-    private List<MediaSize> mMediaSizes;
-    private List<Resolution> mResolutions;
+    private @NonNull Margins mMinMargins = DEFAULT_MARGINS;
+    private @NonNull List<MediaSize> mMediaSizes;
+    private @NonNull List<Resolution> mResolutions;
 
     private int mColorModes;
     private int mDuplexModes;
@@ -205,15 +207,37 @@
         return builder.build();
     }
 
+    /**
+     * Call enforceSingle for each bit in the mask.
+     *
+     * @param mask The mask
+     * @param enforceSingle The function to call
+     */
+    private static void enforceValidMask(int mask, IntConsumer enforceSingle) {
+        int current = mask;
+        while (current > 0) {
+            final int currentMode = (1 << Integer.numberOfTrailingZeros(current));
+            current &= ~currentMode;
+            enforceSingle.accept(currentMode);
+        }
+    }
+
     private PrinterCapabilitiesInfo(Parcel parcel) {
-        mMinMargins = readMargins(parcel);
+        mMinMargins = Preconditions.checkNotNull(readMargins(parcel));
         readMediaSizes(parcel);
         readResolutions(parcel);
 
         mColorModes = parcel.readInt();
+        enforceValidMask(mColorModes,
+                (currentMode) -> PrintAttributes.enforceValidColorMode(currentMode));
+
         mDuplexModes = parcel.readInt();
+        enforceValidMask(mDuplexModes,
+                (currentMode) -> PrintAttributes.enforceValidDuplexMode(currentMode));
 
         readDefaults(parcel);
+        Preconditions.checkArgument(mMediaSizes.size() > mDefaults[PROPERTY_MEDIA_SIZE]);
+        Preconditions.checkArgument(mResolutions.size() > mDefaults[PROPERTY_RESOLUTION]);
     }
 
     @Override
@@ -537,12 +561,8 @@
          */
         public @NonNull Builder setColorModes(@ColorMode int colorModes,
                 @ColorMode int defaultColorMode) {
-            int currentModes = colorModes;
-            while (currentModes > 0) {
-                final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
-                currentModes &= ~currentMode;
-                PrintAttributes.enforceValidColorMode(currentMode);
-            }
+            enforceValidMask(colorModes,
+                    (currentMode) -> PrintAttributes.enforceValidColorMode(currentMode));
             PrintAttributes.enforceValidColorMode(defaultColorMode);
             mPrototype.mColorModes = colorModes;
             mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
@@ -568,12 +588,8 @@
          */
         public @NonNull Builder setDuplexModes(@DuplexMode int duplexModes,
                 @DuplexMode int defaultDuplexMode) {
-            int currentModes = duplexModes;
-            while (currentModes > 0) {
-                final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
-                currentModes &= ~currentMode;
-                PrintAttributes.enforceValidDuplexMode(currentMode);
-            }
+            enforceValidMask(duplexModes,
+                    (currentMode) -> PrintAttributes.enforceValidDuplexMode(currentMode));
             PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
             mPrototype.mDuplexModes = duplexModes;
             mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 69dd9e5a..2a3c3fe 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1569,9 +1569,8 @@
      * @return true if the calling app can draw on top of other apps, false otherwise.
      */
     public static boolean canDrawOverlays(Context context) {
-        int uid = Binder.getCallingUid();
-        return Settings.isCallingPackageAllowedToDrawOverlays(context, uid, Settings
-                .getPackageNameForUid(context, uid), false);
+        return Settings.isCallingPackageAllowedToDrawOverlays(context, Process.myUid(),
+                context.getOpPackageName(), false);
     }
 
     /**
@@ -3885,9 +3884,8 @@
          * @return true if the calling app can write to system settings, false otherwise
          */
         public static boolean canWrite(Context context) {
-            int uid = Binder.getCallingUid();
-            return isCallingPackageAllowedToWriteSettings(context, uid, getPackageNameForUid(
-                    context, uid), false);
+            return isCallingPackageAllowedToWriteSettings(context, Process.myUid(),
+                    context.getOpPackageName(), false);
         }
     }
 
@@ -8308,6 +8306,16 @@
         public static final String BOOT_COUNT = "boot_count";
 
         /**
+         * Whether the safe boot is disallowed.
+         *
+         * <p>This setting should have the identical value as the corresponding user restriction.
+         * The purpose of the setting is to make the restriction available in early boot stages
+         * before the user restrictions are loaded.
+         * @hide
+         */
+        public static final String SAFE_BOOT_DISALLOWED = "safe_boot_disallowed";
+
+        /**
          * 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/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 7af0b05..0557d13 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -35,7 +35,6 @@
 import android.view.ActionMode;
 import android.view.Display;
 import android.view.KeyEvent;
-import android.view.KeyboardShortcutGroup;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index afdd1d4..7325aef 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -69,6 +69,12 @@
  *         &lt;action android:name="android.service.notification.NotificationListenerService" />
  *     &lt;/intent-filter>
  * &lt;/service></pre>
+ *
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing any operations. The {@link #requestRebind(ComponentName)}
+ * method is the <i>only</i> one that is safe to call before {@link #onListenerConnected()}
+ * or after {@link #onListenerDisconnected()}.
+ * </p>
  */
 public abstract class NotificationListenerService extends Service {
     // TAG = "NotificationListenerService[MySubclass]"
@@ -164,6 +170,7 @@
 
     /** @hide */
     protected NotificationListenerWrapper mWrapper = null;
+    private boolean isConnected = false;
 
     @GuardedBy("mLock")
     private RankingMap mRankingMap;
@@ -222,10 +229,10 @@
 
     /**
      * Implement this method to learn when notifications are removed.
-     * <P>
+     * <p>
      * This might occur because the user has dismissed the notification using system UI (or another
      * notification listener) or because the app has withdrawn the notification.
-     * <P>
+     * <p>
      * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
      * result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
      * fields such as {@link android.app.Notification#contentView} and
@@ -243,10 +250,10 @@
 
     /**
      * Implement this method to learn when notifications are removed.
-     * <P>
+     * <p>
      * This might occur because the user has dismissed the notification using system UI (or another
      * notification listener) or because the app has withdrawn the notification.
-     * <P>
+     * <p>
      * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
      * result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
      * fields such as {@link android.app.Notification#contentView} and
@@ -275,6 +282,15 @@
     }
 
     /**
+     * Implement this method to learn about when the listener is disconnected from the
+     * notification manager.You will not receive any events after this call, and may only
+     * call {@link #requestRebind(ComponentName)} at this time.
+     */
+    public void onListenerDisconnected() {
+        // optional
+    }
+
+    /**
      * Implement this method to be notified when the notification ranking changes.
      *
      * @param rankingMap The current ranking map that can be used to retrieve ranking information
@@ -322,12 +338,15 @@
      * It should be called after the user dismisses a single notification using your UI;
      * upon being informed, the notification manager will actually remove the notification
      * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback.
-     * <P>
+     * <p>
      * <b>Note:</b> If your listener allows the user to fire a notification's
      * {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call
      * this method at that time <i>if</i> the Notification in question has the
      * {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @param pkg Package of the notifying app.
      * @param tag Tag of the notification as specified by the notifying app in
      *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
@@ -357,12 +376,16 @@
      * It should be called after the user dismisses a single notification using your UI;
      * upon being informed, the notification manager will actually remove the notification
      * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback.
-     * <P>
+     * <p>
      * <b>Note:</b> If your listener allows the user to fire a notification's
      * {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call
      * this method at that time <i>if</i> the Notification in question has the
      * {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set.
      * <p>
+     *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @param key Notification to dismiss from {@link StatusBarNotification#getKey()}.
      */
     public final void cancelNotification(String key) {
@@ -384,6 +407,9 @@
      * upon being informed, the notification manager will actually remove all active notifications
      * and you will get multiple {@link #onNotificationRemoved(StatusBarNotification)} callbacks.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * {@see #cancelNotification(String, String, int)}
      */
     public final void cancelAllNotifications() {
@@ -396,6 +422,9 @@
      * Use this if your listener has a user interface that allows the user to dismiss
      * multiple notifications at once.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @param keys Notifications to dismiss, or {@code null} to dismiss all.
      *
      * {@see #cancelNotification(String, String, int)}
@@ -414,6 +443,10 @@
      * user. This should only be called when there is sufficient confidence that the user is
      * looking at the notifications, such as when the notifications appear on the screen due to
      * an explicit user interaction.
+     *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @param keys Notifications to mark as seen.
      */
     public final void setNotificationsShown(String[] keys) {
@@ -436,6 +469,9 @@
      * <p>
      * Set to {@link #TRIM_FULL} initially.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @hide
      *
      * @param trim trim of the notifications to be passed via {@link #onNotificationPosted}.
@@ -455,6 +491,9 @@
      * Request the list of outstanding notifications (that is, those that are visible to the
      * current user). Useful when you don't know what's already been posted.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @return An array of active notifications, sorted in natural order.
      */
     public StatusBarNotification[] getActiveNotifications() {
@@ -480,6 +519,9 @@
      * notifications but didn't want to retain the bits, and now need to go back and extract
      * more data out of those notifications.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @param keys the keys of the notifications to request
      * @return An array of notifications corresponding to the requested keys, in the
      * same order as the key list.
@@ -545,6 +587,9 @@
      * shared across all listeners or a feature the notification host does not support or refuses
      * to grant.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @return Zero or more of the HINT_ constants.
      */
     public final int getCurrentListenerHints() {
@@ -572,6 +617,9 @@
      * <p>
      * Listen for updates using {@link #onInterruptionFilterChanged(int)}.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
      * unavailable.
      */
@@ -594,6 +642,9 @@
      * <p>
      * Listen for updates using {@link #onListenerHintsChanged(int)}.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @param hints One or more of the HINT_ constants.
      */
     public final void requestListenerHints(int hints) {
@@ -614,6 +665,9 @@
      * <p>
      * Listen for updates using {@link #onInterruptionFilterChanged(int)}.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @param interruptionFilter One of the INTERRUPTION_FILTER_ constants.
      */
     public final void requestInterruptionFilter(int interruptionFilter) {
@@ -640,6 +694,9 @@
      * such events, for example to retrieve the RankingMap right after
      * initialization.
      *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation.
+     *
      * @return A {@link RankingMap} object providing access to ranking information
      */
     public RankingMap getCurrentRanking() {
@@ -648,6 +705,12 @@
         }
     }
 
+    /**
+     * This is not the lifecycle event you are looking for.
+     *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing any operations.
+     */
     @Override
     public IBinder onBind(Intent intent) {
         if (mWrapper == null) {
@@ -665,6 +728,12 @@
         return true;
     }
 
+    @Override
+    public void onDestroy() {
+        onListenerDisconnected();
+        super.onDestroy();
+    }
+
     /**
      * Directly register this service with the Notification Manager.
      *
@@ -693,7 +762,7 @@
     /**
      * Directly unregister this service from the Notification Manager.
      *
-     * <P>This method will fail for listeners that were not registered
+     * <p>This method will fail for listeners that were not registered
      * with (@link registerAsService).
      * @hide
      */
@@ -708,11 +777,8 @@
     /**
      * Request that the listener be rebound, after a previous call to (@link requestUnbind).
      *
-     * <P>This method will fail for listeners that have
+     * <p>This method will fail for listeners that have
      * not been granted the permission by the user.
-     *
-     * <P>The service should wait for the {@link #onListenerConnected()} event
-     * before performing any operations.
      */
     public static void requestRebind(ComponentName componentName)
             throws RemoteException {
@@ -724,14 +790,19 @@
     /**
      * Request that the service be unbound.
      *
-     * <P>This will no longer receive updates until
+     * <p>This will no longer receive updates until
      * {@link #requestRebind(ComponentName)} is called.
      * The service will likely be kiled by the system after this call.
+     *
+     * <p>The service should wait for the {@link #onListenerConnected()} event
+     * before performing this operation. I know it's tempting, but you must wait.
      */
     public final void requestUnbind() throws RemoteException {
         if (mWrapper != null) {
             INotificationManager noMan = getNotificationInterface();
             noMan.requestUnbindListener(mWrapper);
+            // Disable future messages.
+            isConnected = false;
         }
     }
 
@@ -842,6 +913,7 @@
             synchronized (mLock) {
                 applyUpdateLocked(update);
             }
+            isConnected = true;
             mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_CONNECTED).sendToTarget();
         }
 
@@ -1303,6 +1375,9 @@
 
         @Override
         public void handleMessage(Message msg) {
+            if (!isConnected) {
+                return;
+            }
             switch (msg.what) {
                 case MSG_ON_NOTIFICATION_POSTED: {
                     SomeArgs args = (SomeArgs) msg.obj;
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
new file mode 100644
index 0000000..62ecab3
--- /dev/null
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -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.service.vr;
+
+import android.service.vr.IVrStateCallbacks;
+
+/** @hide */
+interface IVrManager {
+
+    /**
+     * Add a callback to be notified when VR mode state changes.
+     *
+     * @param cb the callback instance to add.
+     */
+    void registerListener(in IVrStateCallbacks cb);
+
+    /**
+     * Remove the callack from the current set of registered callbacks.
+     *
+     * @param cb the callback to remove.
+     */
+    void unregisterListener(in IVrStateCallbacks cb);
+
+    /**
+     * Return current VR mode state.
+     *
+     * @return {@code true} if VR mode is enabled.
+     */
+    boolean getVrModeState();
+
+}
+
diff --git a/core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl b/core/java/android/service/vr/IVrStateCallbacks.aidl
similarity index 62%
copy from core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl
copy to core/java/android/service/vr/IVrStateCallbacks.aidl
index a2c62cd..c4fdcd0 100644
--- a/core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl
+++ b/core/java/android/service/vr/IVrStateCallbacks.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * Copyright (c) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-package android.net;
+package android.service.vr;
 
-import android.net.ConnectivityMetricsEvent;
+/** @hide */
+oneway interface IVrStateCallbacks {
 
-/** {@hide} */
-oneway interface IConnectivityMetricsLoggerSubscriber {
+    void onVrStateChanged(in boolean enabled);
 
-    void onEvents(in ConnectivityMetricsEvent[] events);
 }
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 328fe99..7f0021d 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -183,8 +183,10 @@
 
         if (includepad) {
             spacing = metrics.bottom - metrics.top;
+            mDesc = metrics.bottom;
         } else {
             spacing = metrics.descent - metrics.ascent;
+            mDesc = metrics.descent;
         }
 
         mBottom = spacing;
@@ -208,8 +210,6 @@
             mTopPadding = metrics.top - metrics.ascent;
             mBottomPadding = metrics.bottom - metrics.descent;
         }
-
-        mDesc = spacing + mBottomPadding + (includepad ? metrics.top : metrics.ascent);
     }
 
     /**
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 6a33579..94ce57a 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -1132,22 +1132,12 @@
 
     @Override
     public int getLineTop(int line) {
-        int top = mLines[mColumns * line + TOP];
-        if (mMaximumVisibleLineCount > 0 && line >= mMaximumVisibleLineCount &&
-                line != mLineCount) {
-            top += getBottomPadding();
-        }
-        return top;
+        return mLines[mColumns * line + TOP];
     }
 
     @Override
     public int getLineDescent(int line) {
-        int descent = mLines[mColumns * line + DESCENT];
-        if (mMaximumVisibleLineCount > 0 && line >= mMaximumVisibleLineCount - 1 && // -1 intended
-                line != mLineCount) {
-            descent += getBottomPadding();
-        }
-        return descent;
+        return mLines[mColumns * line + DESCENT];
     }
 
     @Override
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index 4888877..86318e9 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -101,6 +101,15 @@
         mOverrideConfiguration = new Configuration(overrideConfiguration);
     }
 
+    /**
+     * Used by ActivityThread to apply the overridden configuration to onConfigurationChange
+     * callbacks.
+     * @hide
+     */
+    public Configuration getOverrideConfiguration() {
+        return mOverrideConfiguration;
+    }
+
     @Override
     public AssetManager getAssets() {
         // Ensure we're returning assets with the correct configuration.
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5bcf102..4ba97d5 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -180,7 +180,12 @@
     // caller must call setNewConfiguration() sometime later.
     Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
             IBinder freezeThisOneIfNeeded);
-    void setNewConfiguration(in Configuration config);
+    // Notify window manager of the new configuration. Returns an array of stack ids that's
+    // affected by the update, ActivityManager should resize these stacks.
+    int[] setNewConfiguration(in Configuration config);
+
+    // Retrieves the new bounds after the configuration update evaluated by window manager.
+    Rect getBoundsForNewConfiguration(int stackId);
 
     void startFreezingScreen(int exitAnim, int enterAnim);
     void stopFreezingScreen();
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index e0c6770..636384c 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1870,6 +1870,11 @@
         return keyCode == KeyEvent.KEYCODE_META_LEFT || keyCode == KeyEvent.KEYCODE_META_RIGHT;
     }
 
+    /** @hide */
+    public static final boolean isAltKey(int keyCode) {
+        return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT;
+    }
+
     /** {@inheritDoc} */
     @Override
     public final int getDeviceId() {
diff --git a/core/java/android/view/KeyboardShortcutInfo.java b/core/java/android/view/KeyboardShortcutInfo.java
index c2bd347..eee925d 100644
--- a/core/java/android/view/KeyboardShortcutInfo.java
+++ b/core/java/android/view/KeyboardShortcutInfo.java
@@ -51,7 +51,7 @@
         mLabel = label;
         mIcon = icon;
         mBaseCharacter = MIN_VALUE;
-        checkArgument(keycode > KeyEvent.KEYCODE_UNKNOWN && keycode <= KeyEvent.getMaxKeyCode());
+        checkArgument(keycode >= KeyEvent.KEYCODE_UNKNOWN && keycode <= KeyEvent.getMaxKeyCode());
         mKeycode = keycode;
         mModifiers = modifiers;
     }
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index cff9d8e..37da869 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -22,7 +22,6 @@
 import android.util.AttributeSet;
 import android.widget.ImageView;
 import android.widget.RemoteViews;
-import android.widget.TextView;
 
 import java.util.ArrayList;
 
@@ -37,7 +36,7 @@
     private final int mChildMinWidth;
     private final int mContentEndMargin;
     private View mAppName;
-    private View mSubTextView;
+    private View mHeaderText;
     private OnClickListener mExpandClickListener;
     private HeaderTouchListener mTouchListener = new HeaderTouchListener();
     private ImageView mExpandButton;
@@ -73,11 +72,10 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mAppName = findViewById(com.android.internal.R.id.app_name_text);
-        mSubTextView = findViewById(com.android.internal.R.id.header_sub_text);
+        mHeaderText = findViewById(com.android.internal.R.id.header_text);
         mExpandButton = (ImageView) findViewById(com.android.internal.R.id.expand_button);
         mIcon = findViewById(com.android.internal.R.id.icon);
         mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
-        mInfo = findViewById(com.android.internal.R.id.header_content_info);
     }
 
     @Override
@@ -105,15 +103,7 @@
         }
         if (totalWidth > givenWidth) {
             int overFlow = totalWidth - givenWidth;
-            // We are overflowing, lets shrink the info first
-            final int infoWidth = mInfo.getMeasuredWidth();
-            if (mInfo.getVisibility() != GONE && infoWidth > mChildMinWidth) {
-                int newSize = infoWidth - Math.min(infoWidth - mChildMinWidth, overFlow);
-                int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
-                mInfo.measure(childWidthSpec, wrapContentHeightSpec);
-                overFlow -= infoWidth - newSize;
-            }
-            // still overflowing, lets shrink the app name now
+            // We are overflowing, lets shrink the app name first
             final int appWidth = mAppName.getMeasuredWidth();
             if (overFlow > 0 && mAppName.getVisibility() != GONE && appWidth > mChildMinWidth) {
                 int newSize = appWidth - Math.min(appWidth - mChildMinWidth, overFlow);
@@ -121,13 +111,13 @@
                 mAppName.measure(childWidthSpec, wrapContentHeightSpec);
                 overFlow -= appWidth - newSize;
             }
-            // still overflowing, finaly we shrink the subtext
-            if (overFlow > 0 && mSubTextView.getVisibility() != GONE) {
+            // still overflowing, finaly we shrink the header text
+            if (overFlow > 0 && mHeaderText.getVisibility() != GONE) {
                 // we're still too big
-                final int subTextWidth = mSubTextView.getMeasuredWidth();
-                int newSize = Math.max(0, subTextWidth - overFlow);
+                final int textWidth = mHeaderText.getMeasuredWidth();
+                int newSize = Math.max(0, textWidth - overFlow);
                 int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
-                mSubTextView.measure(childWidthSpec, wrapContentHeightSpec);
+                mHeaderText.measure(childWidthSpec, wrapContentHeightSpec);
             }
         }
         setMeasuredDimension(givenWidth, givenHeight);
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 4ffb3d3..ab4cbcf 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -307,18 +307,22 @@
      *
      * Deep copies the data into native to simplify reference ownership.
      */
-    public boolean setOutline(Outline outline) {
+    public boolean setOutline(@Nullable Outline outline) {
         if (outline == null) {
             return nSetOutlineNone(mNativeRenderNode);
-        } else if (outline.isEmpty()) {
-            return nSetOutlineEmpty(mNativeRenderNode);
-        } else if (outline.mRect != null) {
-            return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
-                    outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha);
-        } else if (outline.mPath != null) {
-            return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath,
-                    outline.mAlpha);
         }
+
+        switch(outline.mMode) {
+            case Outline.MODE_EMPTY:
+                return nSetOutlineEmpty(mNativeRenderNode);
+            case Outline.MODE_ROUND_RECT:
+                return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
+                        outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha);
+            case Outline.MODE_CONVEX_PATH:
+                return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath,
+                        outline.mAlpha);
+        }
+
         throw new IllegalArgumentException("Unrecognized outline?");
     }
 
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 37e4000..7cd161c 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -145,13 +145,6 @@
     private int mSpanSlop;
     private int mMinSpan;
 
-    // Bounds for recently seen values
-    private float mTouchUpper;
-    private float mTouchLower;
-    private float mTouchHistoryLastAccepted;
-    private int mTouchHistoryDirection;
-    private long mTouchHistoryLastAcceptedTime;
-    private int mTouchMinMajor;
     private final Handler mHandler;
 
     private float mAnchoredScaleStartX;
@@ -207,8 +200,6 @@
         mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
 
         final Resources res = context.getResources();
-        mTouchMinMajor = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.config_minScalingTouchMajor);
         mMinSpan = res.getDimensionPixelSize(com.android.internal.R.dimen.config_minScalingSpan);
         mHandler = handler;
         // Quick scale is enabled by default after JB_MR2
@@ -223,77 +214,6 @@
     }
 
     /**
-     * The touchMajor/touchMinor elements of a MotionEvent can flutter/jitter on
-     * some hardware/driver combos. Smooth it out to get kinder, gentler behavior.
-     * @param ev MotionEvent to add to the ongoing history
-     */
-    private void addTouchHistory(MotionEvent ev) {
-        final long currentTime = SystemClock.uptimeMillis();
-        final int count = ev.getPointerCount();
-        boolean accept = currentTime - mTouchHistoryLastAcceptedTime >= TOUCH_STABILIZE_TIME;
-        float total = 0;
-        int sampleCount = 0;
-        for (int i = 0; i < count; i++) {
-            final boolean hasLastAccepted = !Float.isNaN(mTouchHistoryLastAccepted);
-            final int historySize = ev.getHistorySize();
-            final int pointerSampleCount = historySize + 1;
-            for (int h = 0; h < pointerSampleCount; h++) {
-                float major;
-                if (h < historySize) {
-                    major = ev.getHistoricalTouchMajor(i, h);
-                } else {
-                    major = ev.getTouchMajor(i);
-                }
-                if (major < mTouchMinMajor) major = mTouchMinMajor;
-                total += major;
-
-                if (Float.isNaN(mTouchUpper) || major > mTouchUpper) {
-                    mTouchUpper = major;
-                }
-                if (Float.isNaN(mTouchLower) || major < mTouchLower) {
-                    mTouchLower = major;
-                }
-
-                if (hasLastAccepted) {
-                    final int directionSig = (int) Math.signum(major - mTouchHistoryLastAccepted);
-                    if (directionSig != mTouchHistoryDirection ||
-                            (directionSig == 0 && mTouchHistoryDirection == 0)) {
-                        mTouchHistoryDirection = directionSig;
-                        final long time = h < historySize ? ev.getHistoricalEventTime(h)
-                                : ev.getEventTime();
-                        mTouchHistoryLastAcceptedTime = time;
-                        accept = false;
-                    }
-                }
-            }
-            sampleCount += pointerSampleCount;
-        }
-
-        final float avg = total / sampleCount;
-
-        if (accept) {
-            float newAccepted = (mTouchUpper + mTouchLower + avg) / 3;
-            mTouchUpper = (mTouchUpper + newAccepted) / 2;
-            mTouchLower = (mTouchLower + newAccepted) / 2;
-            mTouchHistoryLastAccepted = newAccepted;
-            mTouchHistoryDirection = 0;
-            mTouchHistoryLastAcceptedTime = ev.getEventTime();
-        }
-    }
-
-    /**
-     * Clear all touch history tracking. Useful in ACTION_CANCEL or ACTION_UP.
-     * @see #addTouchHistory(MotionEvent)
-     */
-    private void clearTouchHistory() {
-        mTouchUpper = Float.NaN;
-        mTouchLower = Float.NaN;
-        mTouchHistoryLastAccepted = Float.NaN;
-        mTouchHistoryDirection = 0;
-        mTouchHistoryLastAcceptedTime = 0;
-    }
-
-    /**
      * Accepts MotionEvents and dispatches events to a {@link OnScaleGestureListener}
      * when appropriate.
      *
@@ -344,7 +264,6 @@
             }
 
             if (streamComplete) {
-                clearTouchHistory();
                 return true;
             }
         }
@@ -391,17 +310,14 @@
             focusY = sumY / div;
         }
 
-        addTouchHistory(event);
-
         // Determine average deviation from focal point
         float devSumX = 0, devSumY = 0;
         for (int i = 0; i < count; i++) {
             if (skipIndex == i) continue;
 
             // Convert the resulting diameter into a radius.
-            final float touchSize = mTouchHistoryLastAccepted / 2;
-            devSumX += Math.abs(event.getX(i) - focusX) + touchSize;
-            devSumY += Math.abs(event.getY(i) - focusY) + touchSize;
+            devSumX += Math.abs(event.getX(i) - focusX);
+            devSumY += Math.abs(event.getY(i) - focusY);
         }
         final float devX = devSumX / div;
         final float devY = devSumY / div;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2e6dad0..b0aa5c3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2434,6 +2434,7 @@
      *           11111111                PFLAG3_POINTER_ICON_MASK
      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
+     *        1                          PFLAG3_TEMPORARY_DETACH
      * |-------|-------|-------|-------|
      */
 
@@ -2667,6 +2668,14 @@
      */
     private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
 
+    /**
+     * Flag indicating that the view is temporarily detached from the parent view.
+     *
+     * @see #onStartTemporaryDetach()
+     * @see #onFinishTemporaryDetach()
+     */
+    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
+
     /* End of masks for mPrivateFlags3 */
 
     /**
@@ -3890,6 +3899,7 @@
      * cleanup.
      */
     final RenderNode mRenderNode;
+    private Runnable mRenderNodeDetachedCallback;
 
     /**
      * Set to true when the view is sending hover accessibility events because it
@@ -9735,9 +9745,20 @@
     }
 
     /**
-     * @hide
+     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
+     * and {@link #onFinishTemporaryDetach()}.
      */
+    public final boolean isTemporarilyDetached() {
+        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
+    }
+
+    /**
+     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
+     * a container View.
+     */
+    @CallSuper
     public void dispatchStartTemporaryDetach() {
+        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
         onStartTemporaryDetach();
     }
 
@@ -9753,10 +9774,13 @@
     }
 
     /**
-     * @hide
+     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
+     * a container View.
      */
+    @CallSuper
     public void dispatchFinishTemporaryDetach() {
         onFinishTemporaryDetach();
+        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
     }
 
     /**
@@ -15187,6 +15211,7 @@
     protected void onDetachedFromWindowInternal() {
         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
+        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
 
         removeUnsetPressCallback();
         removeLongPressCallback();
@@ -16013,6 +16038,20 @@
      * @hide
      */
     public void onRenderNodeDetached(RenderNode renderNode) {
+        if (renderNode == mRenderNode && mRenderNodeDetachedCallback != null) {
+            mRenderNodeDetachedCallback.run();
+        }
+    }
+
+    /**
+     * Set callback for functor detach. Exposed to WebView through WebViewDelegate.
+     * Should not be used otherwise.
+     * @hide
+     */
+    public final Runnable setRenderNodeDetachedCallback(@Nullable Runnable callback) {
+        Runnable oldCallback = mRenderNodeDetachedCallback;
+        mRenderNodeDetachedCallback = callback;
+        return oldCallback;
     }
 
     /**
@@ -16915,7 +16954,7 @@
             }
         } else if (cache != null) {
             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
-            if (layerType == LAYER_TYPE_NONE) {
+            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
                 // no layer paint, use temporary paint to draw bitmap
                 Paint cachePaint = parent.mCachePaint;
                 if (cachePaint == null) {
@@ -16927,13 +16966,12 @@
                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
             } else {
                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
-                int layerPaintAlpha = mLayerPaint != null ? mLayerPaint.getAlpha() : 255;
-                if (mLayerPaint == null && alpha < 1) {
-                    mLayerPaint = new Paint();
+                int layerPaintAlpha = mLayerPaint.getAlpha();
+                if (alpha < 1) {
                     mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
                 }
                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
-                if (mLayerPaint != null) {
+                if (alpha < 1) {
                     mLayerPaint.setAlpha(layerPaintAlpha);
                 }
             }
@@ -18079,13 +18117,7 @@
          * to clear the previous drawable. setVisible first while we still have the callback set.
          */
         if (mBackground != null) {
-            // It's possible for this method to be invoked from the View constructor before
-            // subclass constructors have run. Drawables can and should trigger invalidations
-            // and other activity with their callback on visibility changes, which shouldn't
-            // happen before subclass constructors finish. However, we won't have set the
-            // drawable as visible until the view becomes attached. This guard below keeps
-            // multiple calls to this method from constructors from causing issues.
-            if (mBackground.isVisible()) {
+            if (isAttachedToWindow()) {
                 mBackground.setVisible(false, false);
             }
             mBackground.setCallback(null);
@@ -18320,13 +18352,7 @@
         }
 
         if (mForegroundInfo.mDrawable != null) {
-            // It's possible for this method to be invoked from the View constructor before
-            // subclass constructors have run. Drawables can and should trigger invalidations
-            // and other activity with their callback on visibility changes, which shouldn't
-            // happen before subclass constructors finish. However, we won't have set the
-            // drawable as visible until the view becomes attached. This guard below keeps
-            // multiple calls to this method from constructors from causing issues.
-            if (mForegroundInfo.mDrawable.isVisible()) {
+            if (isAttachedToWindow()) {
                 mForegroundInfo.mDrawable.setVisible(false, false);
             }
             mForegroundInfo.mDrawable.setCallback(null);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 420c4f2..5b2877f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3415,6 +3415,13 @@
                         updateConfiguration(config, false);
                     }
 
+                    final boolean framesChanged = !mWinFrame.equals(args.arg1)
+                            || !mPendingOverscanInsets.equals(args.arg5)
+                            || !mPendingContentInsets.equals(args.arg2)
+                            || !mPendingStableInsets.equals(args.arg6)
+                            || !mPendingVisibleInsets.equals(args.arg3)
+                            || !mPendingOutsets.equals(args.arg7);
+
                     mWinFrame.set((Rect) args.arg1);
                     mPendingOverscanInsets.set((Rect) args.arg5);
                     mPendingContentInsets.set((Rect) args.arg2);
@@ -3431,7 +3438,7 @@
                         mReportNextDraw = true;
                     }
 
-                    if (mView != null) {
+                    if (mView != null && framesChanged) {
                         forceLayout(mView);
                     }
 
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index b721074..737e4607 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -44,6 +44,8 @@
     public boolean focused;
     public final Rect boundsInScreen = new Rect();
     public List<IBinder> childTokens;
+    public CharSequence title;
+    public int accessibilityIdOfAnchor = View.NO_ID;
 
     private WindowInfo() {
         /* do nothing - hide constructor */
@@ -65,6 +67,8 @@
         window.parentToken = other.parentToken;
         window.focused = other.focused;
         window.boundsInScreen.set(other.boundsInScreen);
+        window.title = other.title;
+        window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor;
 
         if (other.childTokens != null && !other.childTokens.isEmpty()) {
             if (window.childTokens == null) {
@@ -95,6 +99,8 @@
         parcel.writeStrongBinder(parentToken);
         parcel.writeInt(focused ? 1 : 0);
         boundsInScreen.writeToParcel(parcel, flags);
+        parcel.writeCharSequence(title);
+        parcel.writeInt(accessibilityIdOfAnchor);
 
         if (childTokens != null && !childTokens.isEmpty()) {
             parcel.writeInt(1);
@@ -108,13 +114,15 @@
     public String toString() {
         StringBuilder builder = new StringBuilder();
         builder.append("WindowInfo[");
-        builder.append("type=").append(type);
+        builder.append("title=").append(title);
+        builder.append(", type=").append(type);
         builder.append(", layer=").append(layer);
         builder.append(", token=").append(token);
         builder.append(", bounds=").append(boundsInScreen);
         builder.append(", parent=").append(parentToken);
         builder.append(", focused=").append(focused);
         builder.append(", children=").append(childTokens);
+        builder.append(", accessibility anchor=").append(accessibilityIdOfAnchor);
         builder.append(']');
         return builder.toString();
     }
@@ -126,6 +134,8 @@
         parentToken = parcel.readStrongBinder();
         focused = (parcel.readInt() == 1);
         boundsInScreen.readFromParcel(parcel);
+        title = parcel.readCharSequence();
+        accessibilityIdOfAnchor = parcel.readInt();
 
         final boolean hasChildren = (parcel.readInt() == 1);
         if (hasChildren) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 03dcf99..c372c30 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1693,6 +1693,14 @@
          */
         public long userActivityTimeout = -1;
 
+        /**
+         * For windows with an anchor (e.g. PopupWindow), keeps track of the View that anchors the
+         * window.
+         *
+         * @hide
+         */
+        public int accessibilityIdOfAnchor = -1;
+
         public LayoutParams() {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = TYPE_APPLICATION;
@@ -1799,6 +1807,7 @@
             out.writeInt(surfaceInsets.bottom);
             out.writeInt(hasManualSurfaceInsets ? 1 : 0);
             out.writeInt(needsMenuKey);
+            out.writeInt(accessibilityIdOfAnchor);
         }
 
         public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1849,6 +1858,7 @@
             surfaceInsets.bottom = in.readInt();
             hasManualSurfaceInsets = in.readInt() != 0;
             needsMenuKey = in.readInt();
+            accessibilityIdOfAnchor = in.readInt();
         }
 
         @SuppressWarnings({"PointlessBitwiseExpression"})
@@ -1888,6 +1898,8 @@
         /** {@hide} */
         public static final int PREFERRED_DISPLAY_MODE_ID = 1 << 23;
         /** {@hide} */
+        public static final int ACCESSIBILITY_ANCHOR_CHANGED = 1 << 24;
+        /** {@hide} */
         public static final int EVERYTHING_CHANGED = 0xffffffff;
 
         // internal buffer to backup/restore parameters under compatibility mode.
@@ -2048,6 +2060,11 @@
                 changes |= NEEDS_MENU_KEY_CHANGED;
             }
 
+            if (accessibilityIdOfAnchor != o.accessibilityIdOfAnchor) {
+                accessibilityIdOfAnchor = o.accessibilityIdOfAnchor;
+                changes |= ACCESSIBILITY_ANCHOR_CHANGED;
+            }
+
             return changes;
         }
 
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 23b0df2..96f179b 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1397,4 +1397,9 @@
      *         is allowed, so for example, if DOCKED_RIGHT is not allowed, DOCKED_LEFT is allowed.
      */
     public boolean isDockSideAllowed(int dockSide);
+
+    /**
+     * Called when the configuration has changed, and it's safe to load new values from resources.
+     */
+    public void onConfigurationChanged();
 }
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 2cde03d..f8a13a3 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -240,10 +240,12 @@
  *   <li>{@link #getMovementGranularity()} - Sets the granularity at which a view's text
  *       was traversed.</li>
  *   <li>{@link #getText()} -  The text of the source's sub-tree.</li>
- *   <li>{@link #getFromIndex()} - The start of the next/previous text at the specified granularity
- *           - inclusive.</li>
- *   <li>{@link #getToIndex()} - The end of the next/previous text at the specified granularity
- *           - exclusive.</li>
+ *   <li>{@link #getFromIndex()} - The start the text that was skipped over in this movement.
+ *       This is the starting point when moving forward through the text, but not when moving
+ *       back.</li>
+ *   <li>{@link #getToIndex()} - The end of the text that was skipped over in this movement.
+ *       This is the ending point when moving forward through the text, but not when moving
+ *       back.</li>
  *   <li>{@link #isPassword()} - Whether the source is password.</li>
  *   <li>{@link #isEnabled()} - Whether the source is enabled.</li>
  *   <li>{@link #getContentDescription()} - The content description of the source.</li>
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 1482111..02d2a8b 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -328,36 +328,6 @@
     // Action arguments
 
     /**
-     * Argument for specifying index of {@link android.text.style.ClickableSpan} the click action is
-     * related to.
-     * <p>
-     * <strong>Type:</strong> int<br>
-     * <strong>Actions:</strong>
-     * {@link AccessibilityAction#ACTION_CLICK}
-     * </p>
-     *
-     * @see AccessibilityAction#ACTION_CLICK
-     */
-    public static final String ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT =
-            "android.view.accessibility.action.ARGUMENT_CLICK_SPAN_INDEX_INT";
-
-    /**
-     * Argument for specifying index of character in the text which contains
-     * {@link android.text.style.ClickableSpan} the click action is
-     * related to. If there is more than one {@link android.text.style.ClickableSpan} assigned for
-     * the range the character is in only the first span would be clicked.
-     * <p>
-     * <strong>Type:</strong> int<br>
-     * <strong>Actions:</strong>
-     * {@link AccessibilityAction#ACTION_CLICK}
-     * </p>
-     *
-     * @see AccessibilityAction#ACTION_CLICK
-     */
-    public static final String ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT =
-            "android.view.accessibility.action.ARGUMENT_CLICK_CHARACTER_INDEX_INT";
-
-    /**
      * Argument for which movement granularity to be used when traversing the node text.
      * <p>
      * <strong>Type:</strong> int<br>
@@ -3391,33 +3361,6 @@
 
         /**
          * Action that clicks on the node info.
-         *
-         * <p>
-         * If a specific {@link android.text.style.ClickableSpan} within node's text content is
-         * supposed to be clicked, then one of {@link #ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT} or
-         * {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT} arguments should be specified.
-         * If both arguments are set {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT} would
-         * be ignored.<br>
-         *
-         * {@link #ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT} specifies index of corresponding
-         * {@link android.text.style.ClickableSpan} in {@link android.text.SpannableString}.<br>
-         *
-         * {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT} specifies index of character
-         * that could contain one or more spans.
-         * </p>
-         *
-         * <p>
-         * <strong>Optional arguments:</strong>
-         * {@link #ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT},
-         * {@link #ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT}<br>
-         * <strong>Example:</strong> Perform click on 3rd {@link android.text.style.ClickableSpan}
-         * inside {@link android.text.SpannableString} in node's text.
-         * <code><pre><p>
-         *   Bundle arguments = new Bundle();
-         *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT, 3);
-         *   info.performAction(AccessibilityAction.ACTION_CLICK.getId(), arguments);
-         * </code></pre></p>
-         * </p>
          */
         public static final AccessibilityAction ACTION_CLICK =
                 new AccessibilityAction(
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index ad78b68..d0d4507 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -89,6 +89,8 @@
     private int mParentId = UNDEFINED;
     private final Rect mBoundsInScreen = new Rect();
     private LongArray mChildIds;
+    private CharSequence mTitle;
+    private int mAnchorId = UNDEFINED;
 
     private int mConnectionId = UNDEFINED;
 
@@ -97,6 +99,26 @@
     }
 
     /**
+     * Gets the title of the window.
+     *
+     * @return The title.
+     */
+    public CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Sets the title of the window.
+     *
+     * @param title The title.
+     *
+     * @hide
+     */
+    public void setTitle(CharSequence title) {
+        mTitle = title;
+    }
+
+    /**
      * Gets the type of the window.
      *
      * @return The type.
@@ -159,9 +181,35 @@
     }
 
     /**
-     * Gets the parent window if such.
+     * Sets the anchor node's ID.
      *
-     * @return The parent window.
+     * @param anchorId The anchor's accessibility id in its window.
+     *
+     * @hide
+     */
+    public void setAnchorId(int anchorId) {
+        mAnchorId = anchorId;
+    }
+
+    /**
+     * Gets the node that anchors this window to another.
+     *
+     * @return The anchor node, or {@code null} if none exists.
+     */
+    public AccessibilityNodeInfo getAnchor() {
+        if ((mConnectionId == UNDEFINED) || (mAnchorId == UNDEFINED) || (mParentId == UNDEFINED)) {
+            return null;
+        }
+
+        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
+                mParentId, mAnchorId, true, 0);
+    }
+
+    /**
+     * Gets the parent window.
+     *
+     * @return The parent window, or {@code null} if none exists.
      */
     public AccessibilityWindowInfo getParent() {
         if (mConnectionId == UNDEFINED || mParentId == UNDEFINED) {
@@ -370,6 +418,8 @@
         infoClone.mId = info.mId;
         infoClone.mParentId = info.mParentId;
         infoClone.mBoundsInScreen.set(info.mBoundsInScreen);
+        infoClone.mTitle = info.mTitle;
+        infoClone.mAnchorId = info.mAnchorId;
 
         if (info.mChildIds != null && info.mChildIds.size() > 0) {
             if (infoClone.mChildIds == null) {
@@ -410,6 +460,8 @@
         parcel.writeInt(mId);
         parcel.writeInt(mParentId);
         mBoundsInScreen.writeToParcel(parcel, flags);
+        parcel.writeCharSequence(mTitle);
+        parcel.writeInt(mAnchorId);
 
         final LongArray childIds = mChildIds;
         if (childIds == null) {
@@ -432,6 +484,8 @@
         mId = parcel.readInt();
         mParentId = parcel.readInt();
         mBoundsInScreen.readFromParcel(parcel);
+        mTitle = parcel.readCharSequence();
+        mAnchorId = parcel.readInt();
 
         final int childCount = parcel.readInt();
         if (childCount > 0) {
@@ -471,6 +525,7 @@
     public String toString() {
         StringBuilder builder = new StringBuilder();
         builder.append("AccessibilityWindowInfo[");
+        builder.append("title=").append(mTitle);
         builder.append("id=").append(mId);
         builder.append(", type=").append(typeToString(mType));
         builder.append(", layer=").append(mLayer);
@@ -494,6 +549,7 @@
             builder.append(']');
         } else {
             builder.append(", hasParent=").append(mParentId != UNDEFINED);
+            builder.append(", isAnchored=").append(mAnchorId != UNDEFINED);
             builder.append(", hasChildren=").append(mChildIds != null
                     && mChildIds.size() > 0);
         }
@@ -515,6 +571,8 @@
             mChildIds.clear();
         }
         mConnectionId = UNDEFINED;
+        mAnchorId = UNDEFINED;
+        mTitle = null;
     }
 
     /**
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 1536c29..d89c172 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -93,8 +93,12 @@
      */
     public static final int ZORDER_BOTTOM = -1;
 
-    private static final boolean USE_CLOSEGUARD
-            = SystemProperties.getBoolean("log.closeguard.Animation", false);
+    // Use a preload holder to isolate static initialization into inner class, which allows
+    // Animation and its subclasses to be compile-time initialized.
+    private static class NoImagePreloadHolder {
+        public static final boolean USE_CLOSEGUARD
+                = SystemProperties.getBoolean("log.closeguard.Animation", false);
+    }
 
     /**
      * Set by {@link #getTransformation(long, Transformation)} when the animation ends.
@@ -859,7 +863,7 @@
             if (!mStarted) {
                 fireAnimationStart();
                 mStarted = true;
-                if (USE_CLOSEGUARD) {
+                if (NoImagePreloadHolder.USE_CLOSEGUARD) {
                     guard.open("cancel or detach or getTransformation");
                 }
             }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 6879901..1ce80434 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1307,6 +1307,12 @@
     void focusInLocked(View view) {
         if (DEBUG) Log.v(TAG, "focusIn: " + dumpViewInfo(view));
 
+        if (view != null && view.isTemporarilyDetached()) {
+            // This is a request from a view that is temporarily detached from a window.
+            if (DEBUG) Log.v(TAG, "Temporarily detached view, ignoring");
+            return;
+        }
+
         if (mCurRootView != view.getRootView()) {
             // This is a request from a window that isn't in the window with
             // IME focus, so ignore it.
@@ -1332,6 +1338,7 @@
                 // whenever we go into touch mode, so it ends up hiding
                 // at times when we don't really want it to.  For now it
                 // seems better to just turn it all off.
+                // TODO: Check view.isTemporarilyDetached() when re-enable the following code.
                 if (false && view.hasWindowFocus()) {
                     mNextServedView = null;
                     scheduleCheckFocusLocked(view);
@@ -1348,7 +1355,7 @@
         synchronized (mH) {
             if (DEBUG) Log.v(TAG, "onViewDetachedFromWindow: view=" + dumpViewInfo(view)
                     + " mServedView=" + dumpViewInfo(mServedView));
-            if (mServedView == view && view.hasWindowFocus()) {
+            if (mServedView == view) {
                 mNextServedView = null;
                 scheduleCheckFocusLocked(view);
             }
@@ -2315,6 +2322,7 @@
         sb.append(",focus=" + view.hasFocus());
         sb.append(",windowFocus=" + view.hasWindowFocus());
         sb.append(",window=" + view.getWindowToken());
+        sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
         return sb.toString();
     }
 }
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 8104f7d..b6516c8 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -16,6 +16,8 @@
 
 package android.webkit;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.app.Application;
@@ -109,6 +111,24 @@
     }
 
     /**
+     * Set the Runnable callback the DrawGlFunction functor is detached and free to be destroyed.
+     * This will replace the previous callback, if any.
+     *
+     * @param view The view to set the callback. Should be the view where onDraw inserted
+     *        DrawGLFunctor.
+     * @param callback The new callback to set on the view.
+     * @throws IllegalArgumentException if view is null.
+     * @return The previous callback on this view.
+     */
+    public Runnable setDrawGlFunctionDetachedCallback(
+        @NonNull View view, @Nullable Runnable callback) {
+        if (view == null) {
+            throw new IllegalArgumentException("View cannot be null");
+        }
+        return view.setRenderNodeDetachedCallback(callback);
+    }
+
+    /**
      * Detaches the draw GL functor.
      *
      * @param nativeDrawGLFunctor the pointer to the native functor that implements
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index d884f19..0ac5731 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -21,7 +21,6 @@
 import android.app.AppGlobals;
 import android.app.Application;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -561,20 +560,12 @@
         return result;
     }
 
-    /**
-     * Returns whether the entire package from an ACTION_PACKAGE_CHANGED intent was changed (rather
-     * than just one of its components).
-     * @hide
-     */
-    public static boolean entirePackageChanged(Intent intent) {
-        String[] componentList =
-            intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
-        return Arrays.asList(componentList).contains(
-                intent.getDataString().substring("package:".length()));
-    }
+    private static String WEBVIEW_UPDATE_SERVICE_NAME = "webviewupdate";
 
-    private static IWebViewUpdateService getUpdateService() {
-        return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
+    /** @hide */
+    public static IWebViewUpdateService getUpdateService() {
+        return IWebViewUpdateService.Stub.asInterface(
+                ServiceManager.getService(WEBVIEW_UPDATE_SERVICE_NAME));
     }
 
     private static native boolean nativeReserveAddressSpace(long addressSpaceToReserve);
diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java
index d106dba..5d091c9 100644
--- a/core/java/android/webkit/WebViewProviderInfo.java
+++ b/core/java/android/webkit/WebViewProviderInfo.java
@@ -16,12 +16,16 @@
 
 package android.webkit;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import java.util.Arrays;
 
-/** @hide */
+/**
+ * @hide
+ */
+@SystemApi
 public final class WebViewProviderInfo implements Parcelable {
 
     public WebViewProviderInfo(String packageName, String description,
diff --git a/core/java/android/webkit/WebViewUpdateService.java b/core/java/android/webkit/WebViewUpdateService.java
new file mode 100644
index 0000000..4e83d88
--- /dev/null
+++ b/core/java/android/webkit/WebViewUpdateService.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.webkit;
+
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+
+/**
+ * @hide
+ */
+@SystemApi
+public final class WebViewUpdateService {
+
+    private WebViewUpdateService () {}
+
+    /**
+     * Fetch all packages that could potentially implement WebView.
+     */
+    public static WebViewProviderInfo[] getAllWebViewPackages() {
+        try {
+            return getUpdateService().getAllWebViewPackages();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Fetch all packages that could potentially implement WebView and are currently valid.
+     */
+    public static WebViewProviderInfo[] getValidWebViewPackages() {
+        try {
+            return getUpdateService().getValidWebViewPackages();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Used by DevelopmentSetting to get the name of the WebView provider currently in use.
+     */
+    public static String getCurrentWebViewPackageName() {
+        try {
+            return getUpdateService().getCurrentWebViewPackageName();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static IWebViewUpdateService getUpdateService() {
+        return WebViewFactory.getUpdateService();
+    }
+}
diff --git a/core/java/android/widget/AccessibilityIterators.java b/core/java/android/widget/AccessibilityIterators.java
index a3d58a4..442ffa1 100644
--- a/core/java/android/widget/AccessibilityIterators.java
+++ b/core/java/android/widget/AccessibilityIterators.java
@@ -134,8 +134,8 @@
 
         @Override
         public int[] following(int offset) {
-            final int textLegth = mText.length();
-            if (textLegth <= 0) {
+            final int textLength = mText.length();
+            if (textLength <= 0) {
                 return null;
             }
             if (offset >= mText.length()) {
@@ -163,8 +163,8 @@
 
         @Override
         public int[] preceding(int offset) {
-            final int textLegth = mText.length();
-            if (textLegth <= 0) {
+            final int textLength = mText.length();
+            if (textLength <= 0) {
                 return null;
             }
             if (offset <= 0) {
@@ -181,8 +181,13 @@
             final int pageHeight = mTempRect.height() - mView.getTotalPaddingTop()
                     - mView.getTotalPaddingBottom();
             final int previousPageEndY = currentLineTop - pageHeight;
-            final int currentPageStartLine = (previousPageEndY > 0) ?
-                     mLayout.getLineForVertical(previousPageEndY) + 1 : 0;
+            int currentPageStartLine = (previousPageEndY > 0) ?
+                     mLayout.getLineForVertical(previousPageEndY) : 0;
+            // If we're at the end of text, we're at the end of the current line rather than the
+            // start of the next line, so we should move up one fewer lines than we would otherwise.
+            if (end == mText.length() && (currentPageStartLine < currentLine)) {
+                currentPageStartLine += 1;
+            }
 
             final int start = getLineEdgeIndex(currentPageStartLine, DIRECTION_START);
 
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 027f6d6..9d228cf 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -20,6 +20,7 @@
 import android.annotation.IdRes;
 import android.annotation.LayoutRes;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.util.Log;
@@ -61,17 +62,13 @@
 
     private final LayoutInflater mInflater;
 
-    /**
-     * Contains the list of objects that represent the data of this ArrayAdapter.
-     * The content of this list is referred to as "the array" in the documentation.
-     */
-    private List<T> mObjects;
+    private final Context mContext;
 
     /**
      * The resource indicating what views to inflate to display the content of this
      * array adapter.
      */
-    private int mResource;
+    private final int mResource;
 
     /**
      * The resource indicating what views to inflate to display the content of this
@@ -80,7 +77,13 @@
     private int mDropDownResource;
 
     /**
-     * If the inflated resource is not a TextView, {@link #mFieldId} is used to find
+     * Contains the list of objects that represent the data of this ArrayAdapter.
+     * The content of this list is referred to as "the array" in the documentation.
+     */
+    private List<T> mObjects;
+
+    /**
+     * If the inflated resource is not a TextView, {@code mFieldId} is used to find
      * a TextView inside the inflated views hierarchy. This field must contain the
      * identifier that matches the one defined in the resource file.
      */
@@ -92,8 +95,6 @@
      */
     private boolean mNotifyOnChange = true;
 
-    private Context mContext;
-
     // A copy of the original mObjects array, initialized from and then used instead as soon as
     // the mFilter ArrayFilter is used. mObjects will then only contain the filtered values.
     private ArrayList<T> mOriginalValues;
@@ -109,8 +110,8 @@
      * @param resource The resource ID for a layout file containing a TextView to use when
      *                 instantiating views.
      */
-    public ArrayAdapter(Context context, @LayoutRes int resource) {
-        this(context, resource, 0, new ArrayList<T>());
+    public ArrayAdapter(@NonNull Context context, @LayoutRes int resource) {
+        this(context, resource, 0, new ArrayList<>());
     }
 
     /**
@@ -121,8 +122,9 @@
      *                 instantiating views.
      * @param textViewResourceId The id of the TextView within the layout resource to be populated
      */
-    public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId) {
-        this(context, resource, textViewResourceId, new ArrayList<T>());
+    public ArrayAdapter(@NonNull Context context, @LayoutRes int resource,
+            @IdRes int textViewResourceId) {
+        this(context, resource, textViewResourceId, new ArrayList<>());
     }
 
     /**
@@ -133,7 +135,7 @@
      *                 instantiating views.
      * @param objects The objects to represent in the ListView.
      */
-    public ArrayAdapter(Context context, @LayoutRes int resource, @NonNull T[] objects) {
+    public ArrayAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull T[] objects) {
         this(context, resource, 0, Arrays.asList(objects));
     }
 
@@ -146,8 +148,8 @@
      * @param textViewResourceId The id of the TextView within the layout resource to be populated
      * @param objects The objects to represent in the ListView.
      */
-    public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId,
-            @NonNull T[] objects) {
+    public ArrayAdapter(@NonNull Context context, @LayoutRes int resource,
+            @IdRes int textViewResourceId, @NonNull T[] objects) {
         this(context, resource, textViewResourceId, Arrays.asList(objects));
     }
 
@@ -159,7 +161,8 @@
      *                 instantiating views.
      * @param objects The objects to represent in the ListView.
      */
-    public ArrayAdapter(Context context, @LayoutRes int resource, @NonNull List<T> objects) {
+    public ArrayAdapter(@NonNull Context context, @LayoutRes int resource,
+            @NonNull List<T> objects) {
         this(context, resource, 0, objects);
     }
 
@@ -172,8 +175,8 @@
      * @param textViewResourceId The id of the TextView within the layout resource to be populated
      * @param objects The objects to represent in the ListView.
      */
-    public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId,
-            @NonNull List<T> objects) {
+    public ArrayAdapter(@NonNull Context context, @LayoutRes int resource,
+            @IdRes int textViewResourceId, @NonNull List<T> objects) {
         mContext = context;
         mInflater = LayoutInflater.from(context);
         mResource = mDropDownResource = resource;
@@ -186,7 +189,7 @@
      *
      * @param object The object to add at the end of the array.
      */
-    public void add(T object) {
+    public void add(@Nullable T object) {
         synchronized (mLock) {
             if (mOriginalValues != null) {
                 mOriginalValues.add(object);
@@ -201,8 +204,17 @@
      * Adds the specified Collection at the end of the array.
      *
      * @param collection The Collection to add at the end of the array.
+     * @throws UnsupportedOperationException if the <tt>addAll</tt> operation
+     *         is not supported by this list
+     * @throws ClassCastException if the class of an element of the specified
+     *         collection prevents it from being added to this list
+     * @throws NullPointerException if the specified collection contains one
+     *         or more null elements and this list does not permit null
+     *         elements, or if the specified collection is null
+     * @throws IllegalArgumentException if some property of an element of the
+     *         specified collection prevents it from being added to this list
      */
-    public void addAll(Collection<? extends T> collection) {
+    public void addAll(@NonNull Collection<? extends T> collection) {
         synchronized (mLock) {
             if (mOriginalValues != null) {
                 mOriginalValues.addAll(collection);
@@ -235,7 +247,7 @@
      * @param object The object to insert into the array.
      * @param index The index at which the object must be inserted.
      */
-    public void insert(T object, int index) {
+    public void insert(@Nullable T object, int index) {
         synchronized (mLock) {
             if (mOriginalValues != null) {
                 mOriginalValues.add(index, object);
@@ -251,7 +263,7 @@
      *
      * @param object The object to remove.
      */
-    public void remove(T object) {
+    public void remove(@Nullable T object) {
         synchronized (mLock) {
             if (mOriginalValues != null) {
                 mOriginalValues.remove(object);
@@ -282,7 +294,7 @@
      * @param comparator The comparator used to sort the objects contained
      *        in this adapter.
      */
-    public void sort(Comparator<? super T> comparator) {
+    public void sort(@NonNull Comparator<? super T> comparator) {
         synchronized (mLock) {
             if (mOriginalValues != null) {
                 Collections.sort(mOriginalValues, comparator);
@@ -293,9 +305,6 @@
         if (mNotifyOnChange) notifyDataSetChanged();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void notifyDataSetChanged() {
         super.notifyDataSetChanged();
@@ -326,21 +335,17 @@
      *
      * @return The Context associated with this adapter.
      */
-    public Context getContext() {
+    public @NonNull Context getContext() {
         return mContext;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public int getCount() {
         return mObjects.size();
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public T getItem(int position) {
+    @Override
+    public @Nullable T getItem(int position) {
         return mObjects.get(position);
     }
 
@@ -351,28 +356,25 @@
      *
      * @return The position of the specified item.
      */
-    public int getPosition(T item) {
+    public int getPosition(@Nullable T item) {
         return mObjects.indexOf(item);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public long getItemId(int position) {
         return position;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public View getView(int position, View convertView, ViewGroup parent) {
+    @Override
+    public @NonNull View getView(int position, @Nullable View convertView,
+            @NonNull ViewGroup parent) {
         return createViewFromResource(mInflater, position, convertView, parent, mResource);
     }
 
-    private View createViewFromResource(LayoutInflater inflater, int position, View convertView,
-            ViewGroup parent, int resource) {
-        View view;
-        TextView text;
+    private @NonNull View createViewFromResource(@NonNull LayoutInflater inflater, int position,
+            @Nullable View convertView, @NonNull ViewGroup parent, int resource) {
+        final View view;
+        final TextView text;
 
         if (convertView == null) {
             view = inflater.inflate(resource, parent, false);
@@ -387,6 +389,12 @@
             } else {
                 //  Otherwise, find the TextView field within the layout
                 text = (TextView) view.findViewById(mFieldId);
+
+                if (text == null) {
+                    throw new RuntimeException("Failed to find view with ID "
+                            + mContext.getResources().getResourceName(mFieldId)
+                            + " in item layout");
+                }
             }
         } catch (ClassCastException e) {
             Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
@@ -394,9 +402,9 @@
                     "ArrayAdapter requires the resource ID to be a TextView", e);
         }
 
-        T item = getItem(position);
+        final T item = getItem(position);
         if (item instanceof CharSequence) {
-            text.setText((CharSequence)item);
+            text.setText((CharSequence) item);
         } else {
             text.setText(item.toString());
         }
@@ -426,7 +434,7 @@
      * @see #getDropDownView(int, View, ViewGroup)
      */
     @Override
-    public void setDropDownViewTheme(Resources.Theme theme) {
+    public void setDropDownViewTheme(@Nullable Resources.Theme theme) {
         if (theme == null) {
             mDropDownInflater = null;
         } else if (theme == mInflater.getContext().getTheme()) {
@@ -438,12 +446,13 @@
     }
 
     @Override
-    public Resources.Theme getDropDownViewTheme() {
+    public @Nullable Resources.Theme getDropDownViewTheme() {
         return mDropDownInflater == null ? null : mDropDownInflater.getContext().getTheme();
     }
 
     @Override
-    public View getDropDownView(int position, View convertView, ViewGroup parent) {
+    public View getDropDownView(int position, @Nullable View convertView,
+            @NonNull ViewGroup parent) {
         final LayoutInflater inflater = mDropDownInflater == null ? mInflater : mDropDownInflater;
         return createViewFromResource(inflater, position, convertView, parent, mDropDownResource);
     }
@@ -458,16 +467,14 @@
      *
      * @return An ArrayAdapter<CharSequence>.
      */
-    public static ArrayAdapter<CharSequence> createFromResource(Context context,
+    public static @NonNull ArrayAdapter<CharSequence> createFromResource(@NonNull Context context,
             @ArrayRes int textArrayResId, @LayoutRes int textViewResId) {
-        CharSequence[] strings = context.getResources().getTextArray(textArrayResId);
-        return new ArrayAdapter<CharSequence>(context, textViewResId, strings);
+        final CharSequence[] strings = context.getResources().getTextArray(textArrayResId);
+        return new ArrayAdapter<>(context, textViewResId, strings);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public Filter getFilter() {
+    @Override
+    public @NonNull Filter getFilter() {
         if (mFilter == null) {
             mFilter = new ArrayFilter();
         }
@@ -482,31 +489,31 @@
     private class ArrayFilter extends Filter {
         @Override
         protected FilterResults performFiltering(CharSequence prefix) {
-            FilterResults results = new FilterResults();
+            final FilterResults results = new FilterResults();
 
             if (mOriginalValues == null) {
                 synchronized (mLock) {
-                    mOriginalValues = new ArrayList<T>(mObjects);
+                    mOriginalValues = new ArrayList<>(mObjects);
                 }
             }
 
             if (prefix == null || prefix.length() == 0) {
-                ArrayList<T> list;
+                final ArrayList<T> list;
                 synchronized (mLock) {
-                    list = new ArrayList<T>(mOriginalValues);
+                    list = new ArrayList<>(mOriginalValues);
                 }
                 results.values = list;
                 results.count = list.size();
             } else {
-                String prefixString = prefix.toString().toLowerCase();
+                final String prefixString = prefix.toString().toLowerCase();
 
-                ArrayList<T> values;
+                final ArrayList<T> values;
                 synchronized (mLock) {
-                    values = new ArrayList<T>(mOriginalValues);
+                    values = new ArrayList<>(mOriginalValues);
                 }
 
                 final int count = values.size();
-                final ArrayList<T> newValues = new ArrayList<T>();
+                final ArrayList<T> newValues = new ArrayList<>();
 
                 for (int i = 0; i < count; i++) {
                     final T value = values.get(i);
@@ -517,11 +524,8 @@
                         newValues.add(value);
                     } else {
                         final String[] words = valueText.split(" ");
-                        final int wordCount = words.length;
-
-                        // Start at index 0, in case valueText starts with space(s)
-                        for (int k = 0; k < wordCount; k++) {
-                            if (words[k].startsWith(prefixString)) {
+                        for (String word : words) {
+                            if (word.startsWith(prefixString)) {
                                 newValues.add(value);
                                 break;
                             }
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 7d57cb8..6a4e36a 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -1116,7 +1116,7 @@
     protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
         super.onFocusChanged(focused, direction, previouslyFocusedRect);
 
-        if (mTemporaryDetach) {
+        if (isTemporarilyDetached()) {
             // If we are temporarily in the detach state, then do nothing.
             return;
         }
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index cde7604..66896ab 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -430,9 +430,11 @@
      * Sets whether to show the week number.
      *
      * @param showWeekNumber True to show the week number.
+     * @deprecated No longer used by Material-style CalendarView.
      *
      * @attr ref android.R.styleable#CalendarView_showWeekNumber
      */
+    @Deprecated
     public void setShowWeekNumber(boolean showWeekNumber) {
         mDelegate.setShowWeekNumber(showWeekNumber);
     }
@@ -441,9 +443,11 @@
      * Gets whether to show the week number.
      *
      * @return True if showing the week number.
+     * @deprecated No longer used by Material-style CalendarView.
      *
      * @attr ref android.R.styleable#CalendarView_showWeekNumber
      */
+    @Deprecated
     public boolean getShowWeekNumber() {
         return mDelegate.getShowWeekNumber();
     }
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 442fb33..f540479 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -404,7 +404,7 @@
 
     @Override
     public int getUnfocusedMonthDateColor() {
-        return mFocusedMonthDateColor;
+        return mUnfocusedMonthDateColor;
     }
 
     @Override
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 6e3dbd8..0c5edc5 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -75,8 +75,6 @@
  */
 @Widget
 public class DatePicker extends FrameLayout {
-    private static final String LOG_TAG = DatePicker.class.getSimpleName();
-
     private static final int MODE_SPINNER = 1;
     private static final int MODE_CALENDAR = 2;
 
@@ -341,7 +339,9 @@
      *
      * @return {@code true} if the calendar view is shown
      * @see #getCalendarView()
+     * @deprecated Not supported by Material-style {@code calendar} mode
      */
+    @Deprecated
     public boolean getCalendarViewShown() {
         return mDelegate.getCalendarViewShown();
     }
@@ -349,13 +349,18 @@
     /**
      * Returns the {@link CalendarView} used by this picker.
      * <p>
-     * <strong>Note:</strong> This method returns {@code null} when the
+     * <strong>Note:</strong> This method throws an
+     * {@link UnsupportedOperationException} when the
      * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
      * to {@code calendar}.
      *
      * @return the calendar view
      * @see #getCalendarViewShown()
+     * @deprecated Not supported by Material-style {@code calendar} mode
+     * @throws UnsupportedOperationException if called when the picker is
+     *         displayed in {@code calendar} mode
      */
+    @Deprecated
     public CalendarView getCalendarView() {
         return mDelegate.getCalendarView();
     }
@@ -369,7 +374,9 @@
      *
      * @param shown {@code true} to show the calendar view, {@code false} to
      *              hide it
+     * @deprecated Not supported by Material-style {@code calendar} mode
      */
+    @Deprecated
     public void setCalendarViewShown(boolean shown) {
         mDelegate.setCalendarViewShown(shown);
     }
@@ -382,7 +389,9 @@
      * to {@code calendar}.
      *
      * @return {@code true} if the spinners are shown
+     * @deprecated Not supported by Material-style {@code calendar} mode
      */
+    @Deprecated
     public boolean getSpinnersShown() {
         return mDelegate.getSpinnersShown();
     }
@@ -396,7 +405,9 @@
      *
      * @param shown {@code true} to show the spinners, {@code false} to hide
      *              them
+     * @deprecated Not supported by Material-style {@code calendar} mode
      */
+    @Deprecated
     public void setSpinnersShown(boolean shown) {
         mDelegate.setSpinnersShown(shown);
     }
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 5adac01..332e89c 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -378,9 +378,9 @@
         mCurrentDate.set(Calendar.MONTH, monthOfYear);
         mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
 
-        mDateChangedListener = callBack;
-
         onDateChanged(false, false);
+
+        mDateChangedListener = callBack;
     }
 
     @Override
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index 255de79..d8a3c56 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -244,6 +244,7 @@
         setDate(year, monthOfYear, dayOfMonth);
         updateSpinners();
         updateCalendarView();
+
         mOnDateChangedListener = onDateChangedListener;
     }
 
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 8ce2f9c..97936e7 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -148,18 +148,22 @@
 
     void setCalendarTextColor(ColorStateList calendarTextColor) {
         mCalendarTextColor = calendarTextColor;
+        notifyDataSetChanged();
     }
 
     void setDaySelectorColor(ColorStateList selectorColor) {
         mDaySelectorColor = selectorColor;
+        notifyDataSetChanged();
     }
 
     void setMonthTextAppearance(int resId) {
         mMonthTextAppearance = resId;
+        notifyDataSetChanged();
     }
 
     void setDayOfWeekTextAppearance(int resId) {
         mDayOfWeekTextAppearance = resId;
+        notifyDataSetChanged();
     }
 
     int getDayOfWeekTextAppearance() {
@@ -168,6 +172,7 @@
 
     void setDayTextAppearance(int resId) {
         mDayTextAppearance = resId;
+        notifyDataSetChanged();
     }
 
     int getDayTextAppearance() {
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 434e3eb..ad35550 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -155,6 +155,9 @@
     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
         switch (action) {
             case AccessibilityNodeInfo.ACTION_SET_TEXT: {
+                if (!isEnabled()) {
+                    return false;
+                }
                 CharSequence text = (arguments != null) ? arguments.getCharSequence(
                         AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE) : null;
                 setText(text);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 59d857c..440ef21 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -218,7 +218,6 @@
     boolean mShowSoftInputOnFocus = true;
     private boolean mPreserveSelection;
     private boolean mRestartActionModeOnNextRefresh;
-    boolean mTemporaryDetach;
 
     boolean mIsBeingLongClicked;
 
@@ -367,7 +366,6 @@
             showError();
             mShowErrorAfterAttach = false;
         }
-        mTemporaryDetach = false;
 
         final ViewTreeObserver observer = mTextView.getViewTreeObserver();
         // No need to create the controller.
@@ -429,7 +427,6 @@
 
         hideCursorAndSpanControllers();
         stopTextActionModeWithPreservingSelection();
-        mTemporaryDetach = false;
     }
 
     private void discardTextDisplayLists() {
@@ -1212,7 +1209,7 @@
                 stopTextActionModeWithPreservingSelection();
             } else {
                 hideCursorAndSpanControllers();
-                if (mTemporaryDetach) {
+                if (mTextView.isTemporarilyDetached()) {
                     stopTextActionModeWithPreservingSelection();
                 } else {
                     stopTextActionMode();
@@ -1781,6 +1778,18 @@
         if (translate) canvas.translate(0, -cursorOffsetVertical);
     }
 
+    void invalidateHandlesAndActionMode() {
+        if (mSelectionModifierCursorController != null) {
+            mSelectionModifierCursorController.invalidateHandles();
+        }
+        if (mInsertionPointCursorController != null) {
+            mInsertionPointCursorController.invalidateHandle();
+        }
+        if (mTextActionMode != null) {
+            mTextActionMode.invalidate();
+        }
+    }
+
     /**
      * Invalidates all the sub-display lists that overlap the specified character range
      */
@@ -1866,9 +1875,9 @@
         if (hasSelection) {
             hideInsertionPointCursorController();
             if (mTextActionMode == null) {
-                if (mRestartActionModeOnNextRefresh || mTextView.isInExtractedMode()) {
+                if (mRestartActionModeOnNextRefresh) {
                     // To avoid distraction, newly start action mode only when selection action
-                    // mode is being restarted or in full screen extracted mode.
+                    // mode is being restarted.
                     startSelectionActionMode();
                 }
             } else if (selectionController == null || !selectionController.isActive()) {
@@ -3465,7 +3474,6 @@
                 popupBackground.getPadding(mTempRect);
                 width += mTempRect.left + mTempRect.right;
             }
-            mSuggestionListView.getLayoutParams().width = width;
             mPopupWindow.setWidth(width);
         }
 
@@ -3640,6 +3648,9 @@
             }
 
             if (menu.hasVisibleItems() || mode.getCustomView() != null) {
+                if (mHasSelection && !mTextView.hasTransientState()) {
+                    mTextView.setHasTransientState(true);
+                }
                 return true;
             } else {
                 return false;
@@ -4104,6 +4115,14 @@
             setMeasuredDimension(getPreferredWidth(), getPreferredHeight());
         }
 
+        @Override
+        public void invalidate() {
+            super.invalidate();
+            if (isShowing()) {
+                positionAtCursorOffset(getCurrentCursorOffset(), true);
+            }
+        };
+
         private int getPreferredWidth() {
             return Math.max(mDrawable.getIntrinsicWidth(), mMinSize);
         }
@@ -4170,7 +4189,12 @@
             return mTextView.getOffsetAtCoordinate(line, x);
         }
 
-        protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
+        /**
+         * @param offset Cursor offset. Must be in [-1, length].
+         * @param forceUpdatePosition whether to force update the position.  This should be true
+         * when If the parent has been scrolled, for example.
+         */
+        protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) {
             // A HandleView relies on the layout, which may be nulled by external methods
             Layout layout = mTextView.getLayout();
             if (layout == null) {
@@ -4181,7 +4205,7 @@
             layout = mTextView.getLayout();
 
             boolean offsetChanged = offset != mPreviousOffset;
-            if (offsetChanged || parentScrolled) {
+            if (offsetChanged || forceUpdatePosition) {
                 if (offsetChanged) {
                     updateSelection(offset);
                     addPositionToTouchUpFilter(offset);
@@ -4782,13 +4806,9 @@
             mPrevX = x;
         }
 
-        /**
-         * @param offset Cursor offset. Must be in [-1, length].
-         * @param parentScrolled If the parent has been scrolled or not.
-         */
         @Override
-        protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
-            super.positionAtCursorOffset(offset, parentScrolled);
+        protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) {
+            super.positionAtCursorOffset(offset, forceUpdatePosition);
             mInWord = (offset != -1) && !getWordIteratorWithText().isBoundary(offset);
         }
 
@@ -4875,11 +4895,12 @@
 
         @Override
         protected int getOffsetAtCoordinate(@NonNull Layout layout, int line, float x) {
-            final int primaryOffset = layout.getOffsetForHorizontal(line, x, true);
+            final float localX = mTextView.convertToLocalHorizontalCoordinate(x);
+            final int primaryOffset = layout.getOffsetForHorizontal(line, localX, true);
             if (!layout.isLevelBoundary(primaryOffset)) {
                 return primaryOffset;
             }
-            final int secondaryOffset = layout.getOffsetForHorizontal(line, x, false);
+            final int secondaryOffset = layout.getOffsetForHorizontal(line, localX, false);
             final int currentOffset = getCurrentCursorOffset();
             final int primaryDiff = Math.abs(primaryOffset - currentOffset);
             final int secondaryDiff = Math.abs(secondaryOffset - currentOffset);
@@ -5013,6 +5034,12 @@
         public boolean isActive() {
             return mHandle != null && mHandle.isShowing();
         }
+
+        public void invalidateHandle() {
+            if (mHandle != null) {
+                mHandle.invalidate();
+            }
+        }
     }
 
     class SelectionModifierCursorController implements CursorController {
@@ -5417,6 +5444,15 @@
         public boolean isActive() {
             return mStartHandle != null && mStartHandle.isShowing();
         }
+
+        public void invalidateHandles() {
+            if (mStartHandle != null) {
+                mStartHandle.invalidate();
+            }
+            if (mEndHandle != null) {
+                mEndHandle.invalidate();
+            }
+        }
     }
 
     private class CorrectionHighlighter {
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index fe8916b..9ac4917 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -16,17 +16,15 @@
 
 package android.widget;
 
-import java.util.ArrayList;
+import com.android.internal.R;
 
+import android.annotation.AttrRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StyleRes;
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.PorterDuff;
 import android.graphics.Rect;
-import android.graphics.Region;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.Gravity;
@@ -36,8 +34,7 @@
 import android.view.ViewHierarchyEncoder;
 import android.widget.RemoteViews.RemoteView;
 
-import com.android.internal.R;
-
+import java.util.ArrayList;
 
 /**
  * FrameLayout is designed to block out an area on the screen to display
@@ -75,31 +72,29 @@
     @ViewDebug.ExportedProperty(category = "padding")
     private int mForegroundPaddingBottom = 0;
 
-    private final Rect mSelfBounds = new Rect();
-    private final Rect mOverlayBounds = new Rect();
-    
-    private final ArrayList<View> mMatchParentChildren = new ArrayList<View>(1);
-    
-    public FrameLayout(Context context) {
+    private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
+
+    public FrameLayout(@NonNull Context context) {
         super(context);
     }
-    
-    public FrameLayout(Context context, @Nullable AttributeSet attrs) {
+
+    public FrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
         this(context, attrs, 0);
     }
 
-    public FrameLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+    public FrameLayout(@NonNull Context context, @Nullable AttributeSet attrs,
+            @AttrRes int defStyleAttr) {
         this(context, attrs, defStyleAttr, 0);
     }
 
-    public FrameLayout(
-            Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+    public FrameLayout(@NonNull Context context, @Nullable AttributeSet attrs,
+            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
         final TypedArray a = context.obtainStyledAttributes(
-                attrs, com.android.internal.R.styleable.FrameLayout, defStyleAttr, defStyleRes);
-        
-        if (a.getBoolean(com.android.internal.R.styleable.FrameLayout_measureAllChildren, false)) {
+                attrs, R.styleable.FrameLayout, defStyleAttr, defStyleRes);
+
+        if (a.getBoolean(R.styleable.FrameLayout_measureAllChildren, false)) {
             setMeasureAllChildren(true);
         }
 
@@ -171,10 +166,6 @@
             mPaddingBottom + mForegroundPaddingBottom;
     }
 
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int count = getChildCount();
@@ -264,17 +255,13 @@
             }
         }
     }
- 
-    /**
-     * {@inheritDoc}
-     */
+
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         layoutChildren(left, top, right, bottom, false /* no force left gravity */);
     }
 
-    void layoutChildren(int left, int top, int right, int bottom,
-                                  boolean forceLeftGravity) {
+    void layoutChildren(int left, int top, int right, int bottom, boolean forceLeftGravity) {
         final int count = getChildCount();
 
         final int parentLeft = getPaddingLeftWithForeground();
@@ -378,12 +365,9 @@
         return mMeasureAllChildren;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public LayoutParams generateLayoutParams(AttributeSet attrs) {
-        return new FrameLayout.LayoutParams(getContext(), attrs);        
+        return new FrameLayout.LayoutParams(getContext(), attrs);
     }
 
     @Override
@@ -391,9 +375,6 @@
         return false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
         return p instanceof LayoutParams;
@@ -431,34 +412,30 @@
      * Per-child layout information for layouts that support margins.
      * See {@link android.R.styleable#FrameLayout_Layout FrameLayout Layout Attributes}
      * for a list of all child view attributes that this class supports.
-     * 
+     *
      * @attr ref android.R.styleable#FrameLayout_Layout_layout_gravity
      */
     public static class LayoutParams extends MarginLayoutParams {
         /**
          * The gravity to apply with the View to which these layout parameters
          * are associated.
+         * <p>
+         * The default value is {@code Gravity.TOP | Gravity.START}
          *
          * @see android.view.Gravity
-         * 
          * @attr ref android.R.styleable#FrameLayout_Layout_layout_gravity
          */
-        public int gravity = -1;
+        public int gravity = DEFAULT_CHILD_GRAVITY;
 
-        /**
-         * {@inheritDoc}
-         */
-        public LayoutParams(Context c, AttributeSet attrs) {
+        public LayoutParams(@NonNull Context c, @Nullable AttributeSet attrs) {
             super(c, attrs);
 
-            TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout_Layout);
-            gravity = a.getInt(com.android.internal.R.styleable.FrameLayout_Layout_layout_gravity, -1);
+            final TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.FrameLayout_Layout);
+            gravity = a.getInt(R.styleable.FrameLayout_Layout_layout_gravity,
+                    DEFAULT_CHILD_GRAVITY);
             a.recycle();
         }
 
-        /**
-         * {@inheritDoc}
-         */
         public LayoutParams(int width, int height) {
             super(width, height);
         }
@@ -468,9 +445,9 @@
          * and weight.
          *
          * @param width the width, either {@link #MATCH_PARENT},
-         *        {@link #WRAP_CONTENT} or a fixed size in pixels
+         *              {@link #WRAP_CONTENT} or a fixed size in pixels
          * @param height the height, either {@link #MATCH_PARENT},
-         *        {@link #WRAP_CONTENT} or a fixed size in pixels
+         *               {@link #WRAP_CONTENT} or a fixed size in pixels
          * @param gravity the gravity
          *
          * @see android.view.Gravity
@@ -480,17 +457,11 @@
             this.gravity = gravity;
         }
 
-        /**
-         * {@inheritDoc}
-         */
-        public LayoutParams(ViewGroup.LayoutParams source) {
+        public LayoutParams(@NonNull ViewGroup.LayoutParams source) {
             super(source);
         }
 
-        /**
-         * {@inheritDoc}
-         */
-        public LayoutParams(ViewGroup.MarginLayoutParams source) {
+        public LayoutParams(@NonNull ViewGroup.MarginLayoutParams source) {
             super(source);
         }
 
@@ -500,7 +471,7 @@
          *
          * @param source The layout params to copy from.
          */
-        public LayoutParams(LayoutParams source) {
+        public LayoutParams(@NonNull LayoutParams source) {
             super(source);
 
             this.gravity = source.gravity;
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 0206577..222a040 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -911,17 +911,11 @@
         }
 
         if (mDrawable != null) {
-            // It's possible for this method to be invoked from the constructor before
-            // subclass constructors have run. Drawables can and should trigger invalidations
-            // and other activity with their callback on visibility changes, which shouldn't
-            // happen before subclass constructors finish. However, we won't have set the
-            // drawable as visible until the view becomes attached. This guard below keeps
-            // multiple calls to this method from constructors from causing issues.
-            if (mDrawable.isVisible()) {
-                mDrawable.setVisible(false, false);
-            }
             mDrawable.setCallback(null);
             unscheduleDrawable(mDrawable);
+            if (isAttachedToWindow()) {
+                mDrawable.setVisible(false, false);
+            }
         }
 
         mDrawable = d;
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 7658cc8..bfc87f2 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1673,7 +1673,7 @@
                     focusLayoutRestoreView = findFocus();
                     if (focusLayoutRestoreView != null) {
                         // Tell it we are going to mess with it.
-                        focusLayoutRestoreView.onStartTemporaryDetach();
+                        focusLayoutRestoreView.dispatchStartTemporaryDetach();
                     }
                 }
                 requestFocus();
@@ -1850,7 +1850,7 @@
             // our view hierarchy.
             if (focusLayoutRestoreView != null
                     && focusLayoutRestoreView.getWindowToken() != null) {
-                focusLayoutRestoreView.onFinishTemporaryDetach();
+                focusLayoutRestoreView.dispatchFinishTemporaryDetach();
             }
             
             mLayoutMode = LAYOUT_NORMAL;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 92631da..0d8d8ed 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1214,6 +1214,7 @@
         final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff,
                 p.width, p.height, gravity);
         updateAboveAnchor(aboveAnchor);
+        p.accessibilityIdOfAnchor = (anchor != null) ? anchor.getAccessibilityViewId() : -1;
 
         invokePopup(p);
     }
@@ -1494,7 +1495,7 @@
      *
      * @param anchor the view on which the popup window must be anchored
      * @param outParams the layout parameters used to display the drop down
-     * @param xOffset absolute horizontal offset from the top of the anchor
+     * @param xOffset absolute horizontal offset from the left of the anchor
      * @param yOffset absolute vertical offset from the top of the anchor
      * @param gravity horizontal gravity specifying popup alignment
      * @return true if the popup is translated upwards to fit on screen
@@ -1523,6 +1524,8 @@
 
         // Let the window manager know to align the top to y.
         outParams.gravity = Gravity.LEFT | Gravity.TOP;
+        outParams.width = width;
+        outParams.height = height;
 
         final int[] screenLocation = mTmpScreenLocation;
         anchor.getLocationOnScreen(screenLocation);
@@ -1530,100 +1533,154 @@
         final Rect displayFrame = new Rect();
         anchor.getWindowVisibleDisplayFrame(displayFrame);
 
-        boolean onTop = false;
+        // First, attempt to fit the popup vertically without resizing.
+        final boolean fitsVertical = tryFitVertical(outParams, yOffset, height,
+                anchorHeight, drawingLocation[1], screenLocation[1], displayFrame.top,
+                displayFrame.bottom, false);
 
-        final View root = anchor.getRootView();
-        final int screenY = screenLocation[1] + anchorHeight + yOffset;
-        final boolean tooFarDown = screenY + height > displayFrame.bottom;
-        final boolean tooFarRight = outParams.x + width > root.getWidth();
-        if (tooFarDown || tooFarRight) {
-            // If the popup extends beyond the visible area, try to scroll the
-            // parent so that it is fully visible.
-            if (mAllowScrollingAnchorParent) {
-                final int scrollX = anchor.getScrollX();
-                final int scrollY = anchor.getScrollY();
-                final Rect r = new Rect(scrollX, scrollY, scrollX + width + xOffset,
-                        scrollY + height + anchorHeight + yOffset);
-                anchor.requestRectangleOnScreen(r, true);
-            }
+        // Next, attempt to fit the popup horizontally without resizing.
+        final boolean fitsHorizontal = tryFitHorizontal(outParams, xOffset, width,
+                anchorWidth, drawingLocation[0], screenLocation[0], displayFrame.left,
+                displayFrame.right, false);
 
-            // Update for the new anchor position.
-            anchor.getLocationInWindow(drawingLocation);
-            outParams.x = drawingLocation[0] + xOffset;
-            outParams.y = drawingLocation[1] + anchorHeight + yOffset;
+        // If the popup still doesn't fit, attempt to scroll the parent.
+        if (!fitsVertical || !fitsHorizontal) {
+            final int scrollX = anchor.getScrollX();
+            final int scrollY = anchor.getScrollY();
+            final Rect r = new Rect(scrollX, scrollY, scrollX + width + xOffset,
+                    scrollY + height + anchorHeight + yOffset);
+            if (mAllowScrollingAnchorParent && anchor.requestRectangleOnScreen(r, true)) {
+                // Reset for the new anchor position.
+                anchor.getLocationInWindow(drawingLocation);
+                outParams.x = drawingLocation[0] + xOffset;
+                outParams.y = drawingLocation[1] + anchorHeight + yOffset;
 
-            // Preserve the gravity adjustment.
-            if (hgrav == Gravity.RIGHT) {
-                outParams.x -= width - anchorWidth;
-            }
-
-            final int newScreenY = screenLocation[1] + anchorHeight + yOffset;
-            final boolean stillTooFarDown = newScreenY + height > displayFrame.bottom;
-            if (stillTooFarDown) {
-                // If the popup is still too far down, re-evaluate the space
-                // available and decide whether the pop-up will go above or
-                // below the anchor.
-                anchor.getLocationOnScreen(screenLocation);
-
-                final int below = displayFrame.bottom - screenLocation[1] - anchorHeight - yOffset;
-                final int above = screenLocation[1] - displayFrame.top + yOffset;
-                onTop = above > below;
-
-                if (onTop) {
-                    // Move everything up.
-                    if (mOverlapAnchor) {
-                        yOffset += anchorHeight;
-                    }
-                    outParams.y = drawingLocation[1] - height + yOffset;
+                // Preserve the gravity adjustment.
+                if (hgrav == Gravity.RIGHT) {
+                    outParams.x -= width - anchorWidth;
                 }
             }
+
+            // Try to fit the popup again and allowing resizing.
+            tryFitVertical(outParams, yOffset, height, anchorHeight, drawingLocation[1],
+                    screenLocation[1], displayFrame.top, displayFrame.bottom, mClipToScreen);
+            tryFitHorizontal(outParams, xOffset, width, anchorWidth, drawingLocation[0],
+                    screenLocation[0], displayFrame.left, displayFrame.right, mClipToScreen);
         }
 
-        if (mClipToScreen) {
-            // Use screen coordinates for comparison against display frame.
-            final int winOffsetX = screenLocation[0] - drawingLocation[0];
-            final int winOffsetY = screenLocation[1] - drawingLocation[1];
-            outParams.x += winOffsetX;
-            outParams.y += winOffsetY;
+        // Return whether the popup's top edge is above the anchor's top edge.
+        return outParams.y < drawingLocation[1];
+    }
 
-            final int right = outParams.x + width;
-            if (right > displayFrame.right) {
-                // The popup is too far right, move it back in.
-                outParams.x -= right - displayFrame.right;
-            }
-
-            if (outParams.x < displayFrame.left) {
-                // The popup is too far left, move it back in and clip if it's
-                // still too large.
-                outParams.x = displayFrame.left;
-
-                final int displayFrameWidth = displayFrame.width();
-                width = Math.min(width, displayFrameWidth);
-            }
-
-            final int bottom = outParams.y + height;
-            if (bottom > displayFrame.bottom) {
-                // The popup is too far down, move it back in.
-                outParams.y -= bottom - displayFrame.bottom;
-            }
-
-            if (outParams.y < displayFrame.top) {
-                // The popup is too far up, move it back in and clip if
-                // it's still too large.
-                outParams.y = displayFrame.top;
-
-                final int displayFrameHeight = displayFrame.height();
-                height = Math.min(height, displayFrameHeight);
-            }
-
-            outParams.x -= winOffsetX;
-            outParams.y -= winOffsetY;
+    private boolean tryFitVertical(@NonNull LayoutParams outParams, int yOffset, int height,
+            int anchorHeight, int drawingLocationY, int screenLocationY, int displayFrameTop,
+            int displayFrameBottom, boolean allowResize) {
+        final int anchorTopInScreen = screenLocationY + anchorHeight + yOffset;
+        final int spaceBelow = displayFrameBottom - anchorTopInScreen;
+        if (height <= spaceBelow) {
+            return true;
         }
 
-        outParams.width = width;
+        final int spaceAbove = displayFrameTop + anchorTopInScreen - anchorHeight;
+        if (height <= spaceAbove) {
+            // Move everything up.
+            if (mOverlapAnchor) {
+                yOffset += anchorHeight;
+            }
+            outParams.y = drawingLocationY - height + yOffset;
+
+            return true;
+        }
+
+        if (positionInDisplayVertical(outParams, height, drawingLocationY, screenLocationY,
+                displayFrameTop, displayFrameBottom, allowResize)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private boolean positionInDisplayVertical(@NonNull LayoutParams outParams, int height,
+            int drawingLocationY, int screenLocationY, int displayFrameTop, int displayFrameBottom,
+            boolean canResize) {
+        boolean fitsInDisplay = true;
+
+        final int winOffsetY = screenLocationY - drawingLocationY;
+        outParams.y += winOffsetY;
         outParams.height = height;
 
-        return onTop;
+        final int bottom = outParams.y + height;
+        if (bottom > displayFrameBottom) {
+            // The popup is too far down, move it back in.
+            outParams.y -= bottom - displayFrameBottom;
+        }
+
+        if (outParams.y < displayFrameTop) {
+            // The popup is too far up, move it back in and clip if
+            // it's still too large.
+            outParams.y = displayFrameTop;
+
+            final int displayFrameHeight = displayFrameBottom - displayFrameTop;
+            if (canResize && height > displayFrameHeight) {
+                outParams.height = displayFrameHeight;
+            } else {
+                fitsInDisplay = false;
+            }
+        }
+
+        outParams.y -= winOffsetY;
+
+        return fitsInDisplay;
+    }
+
+    private boolean tryFitHorizontal(@NonNull LayoutParams outParams, int xOffset, int width,
+            int anchorWidth, int drawingLocationX, int screenLocationX, int displayFrameLeft,
+            int displayFrameRight, boolean allowResize) {
+        final int anchorLeftInScreen = screenLocationX + xOffset;
+        final int spaceRight = displayFrameRight - anchorLeftInScreen;
+        if (width <= spaceRight) {
+            return true;
+        }
+
+        if (positionInDisplayHorizontal(outParams, width, drawingLocationX, screenLocationX,
+                displayFrameLeft, displayFrameRight, allowResize)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private boolean positionInDisplayHorizontal(@NonNull LayoutParams outParams, int width,
+            int drawingLocationX, int screenLocationX, int displayFrameLeft, int displayFrameRight,
+            boolean canResize) {
+        boolean fitsInDisplay = true;
+
+        // Use screen coordinates for comparison against display frame.
+        final int winOffsetX = screenLocationX - drawingLocationX;
+        outParams.x += winOffsetX;
+
+        final int right = outParams.x + width;
+        if (right > displayFrameRight) {
+            // The popup is too far right, move it back in.
+            outParams.x -= right - displayFrameRight;
+        }
+
+        if (outParams.x < displayFrameLeft) {
+            // The popup is too far left, move it back in and clip if it's
+            // still too large.
+            outParams.x = displayFrameLeft;
+
+            final int displayFrameWidth = displayFrameRight - displayFrameLeft;
+            if (canResize && width > displayFrameWidth) {
+                outParams.width = displayFrameWidth;
+            } else {
+                fitsInDisplay = false;
+            }
+        }
+
+        outParams.x -= winOffsetX;
+
+        return fitsInDisplay;
     }
 
     /**
@@ -1984,6 +2041,13 @@
             update = true;
         }
 
+        int newAccessibilityIdOfAnchor =
+                (mAnchor != null) ? mAnchor.get().getAccessibilityViewId() : -1;
+        if (newAccessibilityIdOfAnchor != p.accessibilityIdOfAnchor) {
+            p.accessibilityIdOfAnchor = newAccessibilityIdOfAnchor;
+            update = true;
+        }
+
         if (update) {
             setLayoutDirectionFromAnchor();
             mWindowManager.updateViewLayout(mDecorView, p);
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 8bd63df..6d2cea6 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.ColorInt;
+import android.app.ActivityManager.StackId;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
 import android.app.Application;
@@ -228,6 +229,11 @@
 
         public boolean onClickHandler(View view, PendingIntent pendingIntent,
                 Intent fillInIntent) {
+            return onClickHandler(view, pendingIntent, fillInIntent, StackId.INVALID_STACK_ID);
+        }
+
+        public boolean onClickHandler(View view, PendingIntent pendingIntent,
+                Intent fillInIntent, int launchStackId) {
             try {
                 // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
                 Context context = view.getContext();
@@ -239,6 +245,10 @@
                             0, 0,
                             view.getMeasuredWidth(), view.getMeasuredHeight());
                 }
+
+                if (launchStackId != StackId.INVALID_STACK_ID) {
+                    opts.setLaunchStackId(launchStackId);
+                }
                 context.startIntentSender(
                         pendingIntent.getIntentSender(), fillInIntent,
                         Intent.FLAG_ACTIVITY_NEW_TASK,
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7602416..48fd58b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -330,10 +330,6 @@
     private int mCurTextColor;
     private int mCurHintTextColor;
     private boolean mFreezesText;
-    private boolean mDispatchTemporaryDetach;
-
-    /** Whether this view is temporarily detached from the parent view. */
-    boolean mTemporaryDetach;
 
     private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
     private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
@@ -3354,7 +3350,10 @@
         mShadowColor = color;
 
         // Will change text clip region
-        if (mEditor != null) mEditor.invalidateTextDisplayList();
+        if (mEditor != null) {
+            mEditor.invalidateTextDisplayList();
+            mEditor.invalidateHandlesAndActionMode();
+        }
         invalidate();
     }
 
@@ -5406,8 +5405,6 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
 
-        mTemporaryDetach = false;
-
         if (mEditor != null) mEditor.onAttachedToWindow();
 
         if (mPreDrawListenerDetached) {
@@ -8289,14 +8286,12 @@
                     newSelEnd = Selection.getSelectionEnd(buf);
                 }
 
-                if (newSelStart == newSelEnd && hasTransientState()) {
-                    setHasTransientState(false);
-                } else if (newSelStart != newSelEnd && !hasTransientState()) {
-                    setHasTransientState(true);
-                }
-
                 if (mEditor != null) {
                     mEditor.refreshTextActionMode();
+                    if (!hasSelection() && mEditor.mTextActionMode == null && hasTransientState()) {
+                        // User generated selection has been removed.
+                        setHasTransientState(false);
+                    }
                 }
                 onSelectionChanged(newSelStart, newSelEnd);
             }
@@ -8314,6 +8309,7 @@
             if (mEditor != null) {
                 if (oldStart >= 0) mEditor.invalidateTextDisplayList(mLayout, oldStart, oldEnd);
                 if (newStart >= 0) mEditor.invalidateTextDisplayList(mLayout, newStart, newEnd);
+                mEditor.invalidateHandlesAndActionMode();
             }
         }
 
@@ -8368,40 +8364,9 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public void dispatchFinishTemporaryDetach() {
-        mDispatchTemporaryDetach = true;
-        super.dispatchFinishTemporaryDetach();
-        mDispatchTemporaryDetach = false;
-    }
-
-    @Override
-    public void onStartTemporaryDetach() {
-        super.onStartTemporaryDetach();
-        // Only track when onStartTemporaryDetach() is called directly,
-        // usually because this instance is an editable field in a list
-        if (!mDispatchTemporaryDetach) mTemporaryDetach = true;
-
-        // Tell the editor that we are temporarily detached. It can use this to preserve
-        // selection state as needed.
-        if (mEditor != null) mEditor.mTemporaryDetach = true;
-    }
-
-    @Override
-    public void onFinishTemporaryDetach() {
-        super.onFinishTemporaryDetach();
-        // Only track when onStartTemporaryDetach() is called directly,
-        // usually because this instance is an editable field in a list
-        if (!mDispatchTemporaryDetach) mTemporaryDetach = false;
-        if (mEditor != null) mEditor.mTemporaryDetach = false;
-    }
-
     @Override
     protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
-        if (mTemporaryDetach) {
+        if (isTemporarilyDetached()) {
             // If we are temporarily in the detach state, then do nothing.
             super.onFocusChanged(focused, direction, previouslyFocusedRect);
             return;
@@ -9096,6 +9061,9 @@
 
         if (mBufferType == BufferType.EDITABLE) {
             info.setEditable(true);
+            if (isEnabled()) {
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT);
+            }
         }
 
         if (mEditor != null) {
@@ -9227,6 +9195,17 @@
                     }
                 }
             } return false;
+            case AccessibilityNodeInfo.ACTION_SET_TEXT: {
+                if (!isEnabled() || (mBufferType != BufferType.EDITABLE)) {
+                    return false;
+                }
+                CharSequence text = (arguments != null) ? arguments.getCharSequence(
+                        AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE) : null;
+                setText(text);
+                if (text != null && text.length() > 0) {
+                    Selection.setSelection((Spannable) mText, text.length());
+                }
+            } return true;
             default: {
                 return super.performAccessibilityActionInternal(action, arguments);
             }
@@ -9235,52 +9214,12 @@
 
     private boolean performAccessibilityActionClick(Bundle arguments) {
         boolean handled = false;
-        boolean processed = false;
 
         if (!isEnabled()) {
             return false;
         }
 
-        if (arguments != null && arguments.containsKey(
-                AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT)) {
-            int spanIndex = arguments.getInt(
-                    AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_SPAN_INDEX_INT, -1);
-            if (spanIndex >= 0 && hasSpannableText()) {
-                ClickableSpan[] spans = ((Spannable) mText).getSpans(0,
-                        mText.length(), ClickableSpan.class);
-                if (spans != null && spans.length > spanIndex && spans[spanIndex] != null) {
-                    // Simulate View.onTouchEvent for an ACTION_UP event
-                    if (isFocusable() && !isFocused()) {
-                        requestFocus();
-                    }
-                    spans[spanIndex].onClick(this);
-                    handled = true;
-                }
-            }
-            processed = true;
-        }
-
-        if (!processed && arguments != null &&  arguments.containsKey(
-                AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT)) {
-            int characterIndex = arguments.getInt(
-                    AccessibilityNodeInfo.ACTION_ARGUMENT_CLICK_CHARACTER_INDEX_INT, -1);
-            if (characterIndex >= 0 && hasSpannableText()) {
-                ClickableSpan[] spans = ((Spannable) mText).getSpans(characterIndex,
-                        characterIndex, ClickableSpan.class);
-                // click only on the first span to keep parity with onTouch() implementation
-                if (spans != null && spans.length > 0 && spans[0] != null) {
-                    // Simulate View.onTouchEvent for an ACTION_UP event
-                    if (isFocusable() && !isFocused()) {
-                        requestFocus();
-                    }
-                    spans[0].onClick(this);
-                    handled = true;
-                }
-            }
-            processed = true;
-        }
-
-        if (!processed && (isClickable() || isLongClickable())) {
+        if (isClickable() || isLongClickable()) {
             // Simulate View.onTouchEvent for an ACTION_UP event
             if (isFocusable() && !isFocused()) {
                 requestFocus();
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 5b0a90a..9cdb73a 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.annotation.StyleRes;
+import android.annotation.TestApi;
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -976,6 +977,15 @@
     }
 
     /**
+     * @hide
+     */
+    @Nullable
+    @TestApi
+    public View getNavigationView() {
+        return mNavButtonView;
+    }
+
+    /**
      * Return the Menu shown in the toolbar.
      *
      * <p>Applications that wish to populate the toolbar's menu can do so from here. To use
diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java
index 36db5d7..a9d5113 100644
--- a/core/java/com/android/internal/app/LocaleHelper.java
+++ b/core/java/com/android/internal/app/LocaleHelper.java
@@ -219,7 +219,7 @@
         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 (mCountryMode || (lhs.isSuggested() == rhs.isSuggested())) {
+            if (lhs.isSuggested() == rhs.isSuggested()) {
                 // They are in the same "bucket" (suggested / others), so we compare the text
                 return mCollator.compare(
                         removePrefixForCompare(lhs.getLocale(), lhs.getLabel(mCountryMode)),
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index c4e6675..7803e52 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -31,8 +31,9 @@
     private static boolean sFullyInitialized = false;
 
     public static class LocaleInfo {
-        private static final int SUGGESTION_TYPE_NONE = 0x00;
-        private static final int SUGGESTION_TYPE_SIM = 0x01;
+        private static final int SUGGESTION_TYPE_NONE = 0;
+        private static final int SUGGESTION_TYPE_SIM = 1 << 0;
+        private static final int SUGGESTION_TYPE_CFG = 1 << 1;
 
         private final Locale mLocale;
         private final Locale mParent;
@@ -273,6 +274,22 @@
         final HashSet<String> localizedLocales = new HashSet<>();
         for (String localeId : LocalePicker.getSystemAssetLocales()) {
             LocaleInfo li = new LocaleInfo(localeId);
+            final String country = li.getLocale().getCountry();
+            // All this is to figure out if we should suggest a country
+            if (!country.isEmpty()) {
+                LocaleInfo cachedLocale = null;
+                if (sLocaleCache.containsKey(li.getId())) { // the simple case, e.g. fr-CH
+                    cachedLocale = sLocaleCache.get(li.getId());
+                } else { // e.g. zh-TW localized, zh-Hant-TW in cache
+                    final String langScriptCtry = li.getLangScriptKey() + "-" + country;
+                    if (sLocaleCache.containsKey(langScriptCtry)) {
+                        cachedLocale = sLocaleCache.get(langScriptCtry);
+                    }
+                }
+                if (cachedLocale != null) {
+                    cachedLocale.mSuggestionFlags |= LocaleInfo.SUGGESTION_TYPE_CFG;
+                }
+            }
             localizedLocales.add(li.getLangScriptKey());
         }
 
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 0e02ed6..ff680e2 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -243,10 +243,6 @@
             return;
         }
 
-        // Prevent the Resolver window from becoming the top fullscreen window and thus from taking
-        // control of the system bars.
-        getWindow().clearFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR);
-
         final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel);
         if (rdl != null) {
             rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() {
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index 98102ea..e2d29e3 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -49,6 +49,7 @@
     private static final int TYPE_HEADER_SUGGESTED = 0;
     private static final int TYPE_HEADER_ALL_OTHERS = 1;
     private static final int TYPE_LOCALE = 2;
+    private static final int MIN_REGIONS_FOR_SUGGESTIONS = 6;
 
     private ArrayList<LocaleStore.LocaleInfo> mLocaleOptions;
     private ArrayList<LocaleStore.LocaleInfo> mOriginalLocaleOptions;
@@ -171,7 +172,15 @@
     }
 
     private boolean showHeaders() {
-        if (mCountryMode) { // never show suggestions in country mode
+        // We don't want to show suggestions for locales with very few regions
+        // (e.g. Romanian, with 2 regions)
+        // So we put a (somewhat) arbitrary limit.
+        //
+        // The initial idea was to make that limit dependent on the screen height.
+        // But that would mean rotating the screen could make the suggestions disappear,
+        // as the number of countries that fits on the screen would be different in portrait
+        // and landscape mode.
+        if (mCountryMode && mLocaleOptions.size() < MIN_REGIONS_FOR_SUGGESTIONS) {
             return false;
         }
         return mSuggestionCount != 0 && mSuggestionCount != mLocaleOptions.size();
diff --git a/core/java/com/android/internal/app/procstats/SparseMappingTable.java b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
index 64c49a2..7252276 100644
--- a/core/java/com/android/internal/app/procstats/SparseMappingTable.java
+++ b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
@@ -28,7 +28,7 @@
 
 /**
  * Class that contains a set of tables mapping byte ids to long values.
- * 
+ *
  * This class is used to store the ProcessStats data.  This data happens to be
  * a set of very sparse tables, that is mostly append or overwrite, with infrequent
  * resets of the data.
@@ -59,11 +59,11 @@
     // Where the "index into array" part of the data appears in an offset integer.
     private static final int INDEX_SHIFT = 16;
     private static final int INDEX_MASK = 0xffff;
-    
+
     private int mSequence;
     private int mNextIndex;
     private final ArrayList<long[]> mLongs = new ArrayList<long[]>();
-    
+
     /**
      * A table of data as stored in a SparseMappingTable.
      */
@@ -377,20 +377,24 @@
             // since we were created or reset.
             if (mSequence == UNINITIALIZED_SEQUENCE) {
                 logOrThrow("mSequence == UNINITIALIZED_SEQUENCE in"
-                        + " SparseMappingTable.Table.  mParent.mSequence=" + mParent.mSequence);
+                        + " SparseMappingTable.Table.  -- "
+                        + dumpInternalState());
+                return;
             }
 
             // Assert that our sequence number matches mParent's.  If it isn't that means
-            // we have been reset and our 
+            // we have been reset and our
             if (mSequence != mParent.mSequence) {
                 if (mSequence < mParent.mSequence) {
                     logOrThrow("Sequence mismatch. SparseMappingTable.resetTable()"
                             + " called but not Table.resetTable() -- "
                             + dumpInternalState());
+                    return;
                 } else if (mSequence > mParent.mSequence) {
                     logOrThrow("Sequence mismatch. Table.resetTable()"
                             + " called but not SparseMappingTable.resetTable() -- "
                             + dumpInternalState());
+                    return;
                 }
             }
         }
@@ -423,7 +427,7 @@
 
         /**
          * Check that all the keys are valid locations in the long arrays.
-         * 
+         *
          * If any aren't, log it and return false. Else return true.
          */
         private boolean validateKeys(boolean log) {
@@ -580,7 +584,7 @@
             i++;
         }
     }
-        
+
     /**
      * Extract the id from a key.
      */
@@ -611,7 +615,7 @@
      * this is a debug build.)
      */
     private static void logOrThrow(String message) {
-        logOrThrow(message, null);
+        logOrThrow(message, new RuntimeException("Stack trace"));
     }
 
     /**
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index 5a195cb..4260e50 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -33,8 +33,8 @@
     //
     // for AppWidgetHost
     //
-    int[] startListening(IAppWidgetHost host, String callingPackage, int hostId,
-            out List<RemoteViews> updatedViews);
+    ParceledListSlice startListening(IAppWidgetHost host, String callingPackage, int hostId,
+            in int[] appWidgetIds, out int[] updatedIds);
     void stopListening(String callingPackage, int hostId);
     int allocateAppWidgetId(String callingPackage, int hostId);
     void deleteAppWidgetId(String callingPackage, int appWidgetId);
diff --git a/core/java/com/android/internal/os/BackgroundThread.java b/core/java/com/android/internal/os/BackgroundThread.java
index d6f7b20..cffba01 100644
--- a/core/java/com/android/internal/os/BackgroundThread.java
+++ b/core/java/com/android/internal/os/BackgroundThread.java
@@ -18,6 +18,7 @@
 
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.Trace;
 
 /**
  * Shared singleton background thread for each process.
@@ -34,6 +35,7 @@
         if (sInstance == null) {
             sInstance = new BackgroundThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 14ebe22..79138b7 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -85,6 +85,7 @@
     public static final String POWER_WIFI_CONTROLLER_IDLE = "wifi.controller.idle";
     public static final String POWER_WIFI_CONTROLLER_RX = "wifi.controller.rx";
     public static final String POWER_WIFI_CONTROLLER_TX = "wifi.controller.tx";
+    public static final String POWER_WIFI_CONTROLLER_TX_LEVELS = "wifi.controller.tx_levels";
     public static final String POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE = "wifi.controller.voltage";
 
     public static final String POWER_BLUETOOTH_CONTROLLER_IDLE = "bluetooth.controller.idle";
@@ -287,9 +288,15 @@
         };
 
         for (int i = 0; i < configResIds.length; i++) {
+            String key = configResIdKeys[i];
+            // if we already have some of these parameters in power_profile.xml, ignore the
+            // value in config.xml
+            if ((sPowerMap.containsKey(key) && (Double) sPowerMap.get(key) > 0)) {
+                continue;
+            }
             int value = resources.getInteger(configResIds[i]);
             if (value > 0) {
-                sPowerMap.put(configResIdKeys[i], (double) value);
+                sPowerMap.put(key, (double) value);
             }
         }
     }
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index e330de2..171a264 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -50,9 +50,12 @@
      * Called when the device has finished going to sleep.
      *
      * @param why {@link #OFF_BECAUSE_OF_USER}, {@link #OFF_BECAUSE_OF_ADMIN},
-     * or {@link #OFF_BECAUSE_OF_TIMEOUT}.
+     *            or {@link #OFF_BECAUSE_OF_TIMEOUT}.
+     * @param cameraGestureTriggered whether the camera gesture was triggered between
+     *                               {@link #onStartedGoingToSleep} and this method; if it's been
+     *                               triggered, we shouldn't lock the device.
      */
-    void onFinishedGoingToSleep(int reason);
+    void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered);
 
     /**
      * Called when the device has started waking up.
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index d80b63a..0f257d7 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -24,6 +24,7 @@
 import android.app.SearchManager;
 import android.os.UserHandle;
 
+import android.text.TextUtils;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.IRotationWatcher.Stub;
@@ -514,6 +515,11 @@
             mDecorContentParent.setWindowTitle(title);
         }
         mTitle = title;
+        WindowManager.LayoutParams params = getAttributes();
+        if (!TextUtils.equals(title, params.getTitle())) {
+            params.setTitle(title);
+            dispatchWindowAttributesChanged(getAttributes());
+        }
     }
 
     @Override
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index ee73b90..bed5a2e 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -238,6 +238,14 @@
         return total;
     }
 
+    public static int[] convertToIntArray(List<Integer> list) {
+        int[] array = new int[list.size()];
+        for (int i = 0; i < list.size(); i++) {
+            array[i] = list.get(i);
+        }
+        return array;
+    }
+
     /**
      * Adds value to given array if not already present, providing set-like
      * behavior.
diff --git a/core/java/com/android/internal/util/FastXmlSerializer.java b/core/java/com/android/internal/util/FastXmlSerializer.java
index 7a04080..3c1d2d6 100644
--- a/core/java/com/android/internal/util/FastXmlSerializer.java
+++ b/core/java/com/android/internal/util/FastXmlSerializer.java
@@ -28,6 +28,7 @@
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
 import java.nio.charset.IllegalCharsetNameException;
 import java.nio.charset.UnsupportedCharsetException;
 
@@ -38,14 +39,14 @@
  */
 public class FastXmlSerializer implements XmlSerializer {
     private static final String ESCAPE_TABLE[] = new String[] {
-        null,     null,     null,     null,     null,     null,     null,     null,  // 0-7
-        null,     null,     null,     null,     null,     null,     null,     null,  // 8-15
-        null,     null,     null,     null,     null,     null,     null,     null,  // 16-23
-        null,     null,     null,     null,     null,     null,     null,     null,  // 24-31
-        null,     null,     "&quot;", null,     null,     null,     "&amp;",  null,  // 32-39
-        null,     null,     null,     null,     null,     null,     null,     null,  // 40-47
-        null,     null,     null,     null,     null,     null,     null,     null,  // 48-55
-        null,     null,     null,     null,     "&lt;",   null,     "&gt;",   null,  // 56-63
+        "&#0;",   "&#1;",   "&#2;",   "&#3;",  "&#4;",    "&#5;",   "&#6;",  "&#7;",  // 0-7
+        "&#8;",   "&#9;",   "&#10;",  "&#11;", "&#12;",   "&#13;",  "&#14;", "&#15;", // 8-15
+        "&#16;",  "&#17;",  "&#18;",  "&#19;", "&#20;",   "&#21;",  "&#22;", "&#23;", // 16-23
+        "&#24;",  "&#25;",  "&#26;",  "&#27;", "&#28;",   "&#29;",  "&#30;", "&#31;", // 24-31
+        null,     null,     "&quot;", null,     null,     null,     "&amp;",  null,   // 32-39
+        null,     null,     null,     null,     null,     null,     null,     null,   // 40-47
+        null,     null,     null,     null,     null,     null,     null,     null,   // 48-55
+        null,     null,     null,     null,     "&lt;",   null,     "&gt;",   null,   // 56-63
     };
 
     private static final int BUFFER_LEN = 8192;
@@ -310,7 +311,9 @@
             throw new IllegalArgumentException();
         if (true) {
             try {
-                mCharset = Charset.forName(encoding).newEncoder();
+                mCharset = Charset.forName(encoding).newEncoder()
+                        .onMalformedInput(CodingErrorAction.REPLACE)
+                        .onUnmappableCharacter(CodingErrorAction.REPLACE);
             } catch (IllegalCharsetNameException e) {
                 throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
                         encoding).initCause(e));
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index 7c85246..1ead5b3 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -191,6 +191,21 @@
      * Ensures that that the argument numeric value is non-negative.
      *
      * @param value a numeric long value
+     * @return the validated numeric value
+     * @throws IllegalArgumentException if {@code value} was negative
+     */
+    public static long checkArgumentNonnegative(final long value) {
+        if (value < 0) {
+            throw new IllegalArgumentException();
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that that the argument numeric value is non-negative.
+     *
+     * @param value a numeric long value
      * @param errorMessage the exception message to use if the check fails
      * @return the validated numeric value
      * @throws IllegalArgumentException if {@code value} was negative
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 29a9c8e..ddca51f 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -346,7 +346,15 @@
     private void showMenu(@NonNull MenuBuilder menu) {
         final LayoutInflater inflater = LayoutInflater.from(mContext);
         final MenuAdapter adapter = new MenuAdapter(menu, inflater, mOverflowOnly);
-        adapter.setForceShowIcon(mForceShowIcon);
+
+        // Apply "force show icon" setting; if the menu being shown is the top level menu, apply the
+        // setting set on this CascadingMenuPopup by its creating code. If it's a submenu, or if no
+        // "force" setting was explicitly set, determine the setting by examining the items.
+        if (!isShowing() && mForceShowIcon) {
+            adapter.setForceShowIcon(mForceShowIcon);
+        } else {
+            adapter.setForceShowIcon(MenuPopup.shouldPreserveIconSpacing(menu));
+        }
 
         final int menuWidth = measureIndividualMenuWidth(adapter, null, mContext, mMenuMaxWidth);
         final MenuPopupWindow popupWindow = createPopupWindow();
diff --git a/core/java/com/android/internal/view/menu/MenuPopup.java b/core/java/com/android/internal/view/menu/MenuPopup.java
index 42b1a56..16e4156 100644
--- a/core/java/com/android/internal/view/menu/MenuPopup.java
+++ b/core/java/com/android/internal/view/menu/MenuPopup.java
@@ -183,4 +183,25 @@
         }
         return (MenuAdapter) adapter;
     }
+
+    /**
+     * Returns whether icon spacing needs to be preserved for the given menu, based on whether any
+     * of its items contains an icon.
+     * @param menu
+     * @return Whether to preserve icon spacing.
+     */
+    protected static boolean shouldPreserveIconSpacing(MenuBuilder menu) {
+      boolean preserveIconSpacing = false;
+      final int count = menu.size();
+
+      for (int i = 0; i < count; i++) {
+          MenuItem childItem = menu.getItem(i);
+          if (childItem.isVisible() && childItem.getIcon() != null) {
+              preserveIconSpacing = true;
+              break;
+          }
+      }
+
+      return preserveIconSpacing;
+    }
 }
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 8ced36f..d8ed92d 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -266,7 +266,7 @@
             final MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu,
                     mShownAnchorView, mOverflowOnly, mPopupStyleAttr, mPopupStyleRes);
             subPopup.setPresenterCallback(mPresenterCallback);
-            subPopup.setForceShowIcon(mAdapter.getForceShowIcon());
+            subPopup.setForceShowIcon(MenuPopup.shouldPreserveIconSpacing(subMenu));
 
             // Pass responsibility for handling onDismiss to the submenu.
             subPopup.setOnDismissListener(mOnDismissListener);
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index da223a6..1848fe8 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1460,6 +1460,7 @@
                 super(Preconditions.checkNotNull(popup).mContext);
                 this.mPopup = popup;
                 setScrollBarDefaultDelayBeforeFade(ViewConfiguration.getScrollDefaultDelay() * 3);
+                setScrollIndicators(View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM);
             }
 
             @Override
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index b07e36a..21c4d12 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -33,9 +33,12 @@
     void setLockPassword(in String password, in String savedPassword, int userId);
     VerifyCredentialResponse checkPassword(in String password, int userId);
     VerifyCredentialResponse verifyPassword(in String password, long challenge, int userId);
+    VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId);
     boolean checkVoldPassword(int userId);
     boolean havePattern(int userId);
     boolean havePassword(int userId);
+    void setSeparateProfileChallengeEnabled(int userId, boolean enabled, String managedUserPassword);
+    boolean getSeparateProfileChallengeEnabled(int userId);
     void registerStrongAuthTracker(in IStrongAuthTracker tracker);
     void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
     void requireStrongAuth(int strongAuthReason, int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index 4880664..713f56f 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -145,6 +145,43 @@
     }
 
     /**
+     * Verify a password asynchronously.
+     *
+     * @param utils The LockPatternUtils instance to use.
+     * @param password The password to check.
+     * @param challenge The challenge to verify against the pattern.
+     * @param userId The user to check against the pattern.
+     * @param callback The callback to be invoked with the verification result.
+     */
+    public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils,
+            final String password,
+            final boolean isPattern,
+            final long challenge,
+            final int userId,
+            final OnVerifyCallback callback) {
+        AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
+            private int mThrottleTimeout;
+
+            @Override
+            protected byte[] doInBackground(Void... args) {
+                try {
+                    return utils.verifyTiedProfileChallenge(password, isPattern, challenge, userId);
+                } catch (RequestThrottledException ex) {
+                    mThrottleTimeout = ex.getTimeoutMs();
+                    return null;
+                }
+            }
+
+            @Override
+            protected void onPostExecute(byte[] result) {
+                callback.onVerified(result, mThrottleTimeout);
+            }
+        };
+        task.execute();
+        return task;
+    }
+
+    /**
      * Checks a password asynchronously.
      *
      * @param utils The LockPatternUtils instance to use.
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 9d14478..bceeaca 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -137,8 +137,6 @@
     private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
     private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged";
 
-    private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
-
     // Maximum allowed number of repeated or ordered characters in a sequence before we'll
     // consider it a complex PIN/password.
     public static final int MAX_ALLOWED_SEQUENCE = 3;
@@ -377,6 +375,36 @@
         }
     }
 
+
+    /**
+     * Check to see if a password matches the saved password.
+     * If password matches, return an opaque attestation that the challenge
+     * was verified.
+     *
+     * @param password The password to check.
+     * @param challenge The challenge to verify against the password
+     * @return the attestation that the challenge was verified, or null.
+     */
+    public byte[] verifyTiedProfileChallenge(String password, boolean isPattern, long challenge,
+            int userId) throws RequestThrottledException {
+        throwIfCalledOnMainThread();
+        try {
+            VerifyCredentialResponse response =
+                    getLockSettings().verifyTiedProfileChallenge(password, isPattern, challenge,
+                            userId);
+
+            if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+                return response.getPayload();
+            } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
+                throw new RequestThrottledException(response.getTimeout());
+            } else {
+                return null;
+            }
+        } catch (RemoteException re) {
+            return null;
+        }
+    }
+
     /**
      * Check to see if a password matches the saved password.  If no password exists,
      * always returns true.
@@ -785,6 +813,7 @@
             }
 
             getLockSettings().setLockPassword(password, savedPassword, userHandle);
+            getLockSettings().setSeparateProfileChallengeEnabled(userHandle, true, null);
             int computedQuality = computePasswordQuality(password);
 
             // Update the device encryption password.
@@ -919,11 +948,23 @@
     /**
      * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
      * for user handles that do not belong to a managed profile.
+     *
+     * @param userHandle Managed profile user id
+     * @param enabled True if separate challenge is enabled
+     * @param managedUserPassword Managed profile previous password. Null when {@param enabled} is
+     *            true
      */
-    public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled) {
+    public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
+            String managedUserPassword) {
         UserInfo info = getUserManager().getUserInfo(userHandle);
         if (info.isManagedProfile()) {
-            setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userHandle);
+            try {
+                getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
+                        managedUserPassword);
+                onAfterChangingPassword(userHandle);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Couldn't update work profile challenge enabled");
+            }
         }
     }
 
@@ -935,7 +976,13 @@
         if (info == null || !info.isManagedProfile()) {
             return false;
         }
-        return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userHandle);
+        try {
+            return getLockSettings().getSeparateProfileChallengeEnabled(userHandle);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Couldn't get separate profile challenge enabled");
+            // Default value is false
+            return false;
+        }
     }
 
     /**
@@ -1099,7 +1146,8 @@
                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
                 || mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX
                 || mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
-                || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+                || mode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX
+                || mode == DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
         return passwordEnabled && savedPasswordExists(userId);
     }
 
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index c4347f8..25b487e 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -17,9 +17,14 @@
 
 package com.android.internal.widget;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -85,6 +90,10 @@
     private final float mMinFlingVelocity;
     private final OverScroller mScroller;
     private final VelocityTracker mVelocityTracker;
+    private final Drawable mScrollIndicatorDrawable;
+    private final Drawable mFakeForeground;
+
+    private View mButtonBar;
 
     private OnDismissedListener mOnDismissedListener;
     private RunOnDismissedListener mRunOnDismissedListener;
@@ -106,6 +115,8 @@
                 }
             };
 
+    private final int[] mTempOffset = new int[2];
+
     public ResolverDrawerLayout(Context context) {
         this(context, null);
     }
@@ -127,6 +138,9 @@
                 mMaxCollapsedHeight);
         a.recycle();
 
+        mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
+        mFakeForeground = new ColorDrawable(Color.TRANSPARENT);
+
         mScroller = new OverScroller(context, AnimationUtils.loadInterpolator(context,
                 android.R.interpolator.decelerate_quint));
         mVelocityTracker = VelocityTracker.obtain();
@@ -138,6 +152,13 @@
         setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
     }
 
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mButtonBar = findViewById(R.id.button_bar);
+    }
+
     public void setSmallCollapsed(boolean smallCollapsed) {
         mSmallCollapsed = smallCollapsed;
         requestLayout();
@@ -202,8 +223,7 @@
             }
             final boolean isCollapsedNew = mCollapseOffset != 0;
             if (isCollapsedOld != isCollapsedNew) {
-                notifyViewAccessibilityStateChangedIfNeeded(
-                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+                onCollapsedChanged(isCollapsedNew);
             }
         } else {
             // Start out collapsed at first unless we restored state for otherwise
@@ -442,8 +462,7 @@
             mTopOffset += dy;
             final boolean isCollapsedNew = newPos != 0;
             if (isCollapsedOld != isCollapsedNew) {
-                notifyViewAccessibilityStateChangedIfNeeded(
-                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+                onCollapsedChanged(isCollapsedNew);
             }
             postInvalidateOnAnimation();
             return dy;
@@ -451,6 +470,14 @@
         return 0;
     }
 
+    private void onCollapsedChanged(boolean isCollapsed) {
+        notifyViewAccessibilityStateChangedIfNeeded(
+                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+
+        // Set a fake foreground so that we receive onDrawForeground().
+        setForeground(isCollapsed ? mFakeForeground : null);
+    }
+
     void dispatchOnDismissed() {
         if (mOnDismissedListener != null) {
             mOnDismissedListener.onDismissed();
@@ -709,6 +736,23 @@
     }
 
     @Override
+    public void onDrawForeground(Canvas canvas) {
+        if (isCollapsed() && mButtonBar != null) {
+            // Draw the scroll indicator directly above the button bar.
+            final int height = mScrollIndicatorDrawable.getIntrinsicHeight();
+            mButtonBar.getLocationInWindow(mTempOffset);
+            final int barTop = mTempOffset[1];
+            getLocationInWindow(mTempOffset);
+            final int myTop = mTempOffset[1];
+            final int top = (barTop - myTop) - height;
+            mScrollIndicatorDrawable.setBounds(0, top, getWidth(), top + height);
+            mScrollIndicatorDrawable.draw(canvas);
+        }
+
+        super.onDrawForeground(canvas);
+    }
+
+    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int sourceWidth = MeasureSpec.getSize(widthMeasureSpec);
         int widthSize = sourceWidth;
diff --git a/core/java/com/android/server/backup/ShortcutBackupHelper.java b/core/java/com/android/server/backup/ShortcutBackupHelper.java
new file mode 100644
index 0000000..0b3f2ae
--- /dev/null
+++ b/core/java/com/android/server/backup/ShortcutBackupHelper.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.backup;
+
+import android.app.backup.BlobBackupHelper;
+import android.content.Context;
+import android.content.pm.IShortcutService;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.Slog;
+
+public class ShortcutBackupHelper extends BlobBackupHelper {
+    private static final String TAG = "ShortcutBackupAgent";
+    private static final int BLOB_VERSION = 1;
+
+    private static final String KEY_USER_FILE = "shortcutuser.xml";
+
+    public ShortcutBackupHelper() {
+        super(BLOB_VERSION, KEY_USER_FILE);
+    }
+
+    private IShortcutService getShortcutService() {
+        return IShortcutService.Stub.asInterface(
+                ServiceManager.getService(Context.SHORTCUT_SERVICE));
+    }
+
+    @Override
+    protected byte[] getBackupPayload(String key) {
+        switch (key) {
+            case KEY_USER_FILE:
+                try {
+                    return getShortcutService().getBackupPayload(UserHandle.USER_SYSTEM);
+                } catch (Exception e) {
+                    Slog.wtf(TAG, "Backup failed", e);
+                }
+                break;
+            default:
+                Slog.w(TAG, "Unknown key: " + key);
+        }
+        return null;
+    }
+
+    @Override
+    protected void applyRestoredPayload(String key, byte[] payload) {
+        switch (key) {
+            case KEY_USER_FILE:
+                try {
+                    getShortcutService().applyRestore(payload, UserHandle.USER_SYSTEM);
+                } catch (Exception e) {
+                    Slog.wtf(TAG, "Restore failed", e);
+                }
+                break;
+            default:
+                Slog.w(TAG, "Unknown key: " + key);
+        }
+    }
+}
diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java
index 181ed51..2d12fcd 100644
--- a/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -17,9 +17,9 @@
 package com.android.server.backup;
 
 import android.app.IWallpaperManager;
+import android.app.backup.BackupAgentHelper;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
-import android.app.backup.BackupAgentHelper;
 import android.app.backup.FullBackup;
 import android.app.backup.FullBackupDataOutput;
 import android.app.backup.WallpaperBackupHelper;
@@ -48,6 +48,7 @@
     private static final String NOTIFICATION_HELPER = "notifications";
     private static final String PERMISSION_HELPER = "permissions";
     private static final String USAGE_STATS_HELPER = "usage_stats";
+    private static final String SHORTCUT_MANAGER_HELPER = "shortcut_manager";
 
     // These paths must match what the WallpaperManagerService uses.  The leaf *_FILENAME
     // are also used in the full-backup file format, so must not change unless steps are
@@ -100,6 +101,7 @@
         addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
         addHelper(PERMISSION_HELPER, new PermissionBackupHelper());
         addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this));
+        addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper());
         super.onBackup(oldState, data, newState);
     }
 
@@ -138,6 +140,7 @@
         addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
         addHelper(PERMISSION_HELPER, new PermissionBackupHelper());
         addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this));
+        addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper());
 
         try {
             super.onRestore(data, appVersionCode, newState);
diff --git a/core/java/com/android/server/net/NetlinkTracker.java b/core/java/com/android/server/net/NetlinkTracker.java
index d45982e..5b421d9 100644
--- a/core/java/com/android/server/net/NetlinkTracker.java
+++ b/core/java/com/android/server/net/NetlinkTracker.java
@@ -102,6 +102,19 @@
     }
 
     @Override
+    public void interfaceRemoved(String iface) {
+        maybeLog("interfaceRemoved", iface);
+        if (mInterfaceName.equals(iface)) {
+            // Our interface was removed. Clear our LinkProperties and tell our owner that they are
+            // now empty. Note that from the moment that the interface is removed, any further
+            // interface-specific messages (e.g., RTM_DELADDR) will not reach us, because the netd
+            // code that parses them will not be able to resolve the ifindex to an interface name.
+            clearLinkProperties();
+            mCallback.update();
+        }
+    }
+
+    @Override
     public void addressUpdated(String iface, LinkAddress address) {
         if (mInterfaceName.equals(iface)) {
             maybeLog("addressUpdated", iface, address);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index c6112d9..8a512a6 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -103,7 +103,6 @@
     android_util_jar_StrictJarFile.cpp \
     android_graphics_Canvas.cpp \
     android_graphics_Picture.cpp \
-    android/graphics/AvoidXfermode.cpp \
     android/graphics/Bitmap.cpp \
     android/graphics/BitmapFactory.cpp \
     android/graphics/Camera.cpp \
diff --git a/core/jni/android/graphics/AvoidXfermode.cpp b/core/jni/android/graphics/AvoidXfermode.cpp
deleted file mode 100644
index 9ca1f26..0000000
--- a/core/jni/android/graphics/AvoidXfermode.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "AvoidXfermode.h"
-#include "SkColorPriv.h"
-#include "SkReadBuffer.h"
-#include "SkWriteBuffer.h"
-#include "SkString.h"
-
-AvoidXfermode::AvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) {
-    if (tolerance > 255) {
-        tolerance = 255;
-    }
-    fTolerance = SkToU8(tolerance);
-    fOpColor = opColor;
-    fDistMul = (256 << 14) / (tolerance + 1);
-    fMode = mode;
-}
-
-SkFlattenable* AvoidXfermode::CreateProc(SkReadBuffer& buffer) {
-    const SkColor color = buffer.readColor();
-    const unsigned tolerance = buffer.readUInt();
-    const unsigned mode = buffer.readUInt();
-    return Create(color, tolerance, (Mode)mode);
-}
-
-void AvoidXfermode::flatten(SkWriteBuffer& buffer) const {
-    buffer.writeColor(fOpColor);
-    buffer.writeUInt(fTolerance);
-    buffer.writeUInt(fMode);
-}
-
-// returns 0..31
-static unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b) {
-    SkASSERT(r <= SK_R16_MASK);
-    SkASSERT(g <= SK_G16_MASK);
-    SkASSERT(b <= SK_B16_MASK);
-
-    unsigned dr = SkAbs32(SkGetPackedR16(c) - r);
-    unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS);
-    unsigned db = SkAbs32(SkGetPackedB16(c) - b);
-
-    return SkMax32(dr, SkMax32(dg, db));
-}
-
-// returns 0..255
-static unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b) {
-    SkASSERT(r <= 0xFF);
-    SkASSERT(g <= 0xFF);
-    SkASSERT(b <= 0xFF);
-
-    unsigned dr = SkAbs32(SkGetPackedR32(c) - r);
-    unsigned dg = SkAbs32(SkGetPackedG32(c) - g);
-    unsigned db = SkAbs32(SkGetPackedB32(c) - b);
-
-    return SkMax32(dr, SkMax32(dg, db));
-}
-
-static int scale_dist_14(int dist, uint32_t mul, uint32_t sub) {
-    int tmp = dist * mul - sub;
-    int result = (tmp + (1 << 13)) >> 14;
-
-    return result;
-}
-
-static inline unsigned Accurate255To256(unsigned x) {
-    return x + (x >> 7);
-}
-
-void AvoidXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count,
-                             const SkAlpha aa[]) const {
-    unsigned    opR = SkColorGetR(fOpColor);
-    unsigned    opG = SkColorGetG(fOpColor);
-    unsigned    opB = SkColorGetB(fOpColor);
-    uint32_t    mul = fDistMul;
-    uint32_t    sub = (fDistMul - (1 << 14)) << 8;
-
-    int MAX, mask;
-
-    if (kTargetColor_Mode == fMode) {
-        mask = -1;
-        MAX = 255;
-    } else {
-        mask = 0;
-        MAX = 0;
-    }
-
-    for (int i = 0; i < count; i++) {
-        int d = color_dist32(dst[i], opR, opG, opB);
-        // now reverse d if we need to
-        d = MAX + (d ^ mask) - mask;
-        SkASSERT((unsigned)d <= 255);
-        d = Accurate255To256(d);
-
-        d = scale_dist_14(d, mul, sub);
-        SkASSERT(d <= 256);
-
-        if (d > 0) {
-            if (aa) {
-                d = SkAlphaMul(d, Accurate255To256(*aa++));
-                if (0 == d) {
-                    continue;
-                }
-            }
-            dst[i] = SkFourByteInterp256(src[i], dst[i], d);
-        }
-    }
-}
-
-static inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale) {
-    SkASSERT(scale <= 32);
-    scale <<= 3;
-
-    return SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale),
-                        SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale),
-                        SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale));
-}
-
-void AvoidXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
-                             const SkAlpha aa[]) const {
-    unsigned    opR = SkColorGetR(fOpColor) >> (8 - SK_R16_BITS);
-    unsigned    opG = SkColorGetG(fOpColor) >> (8 - SK_G16_BITS);
-    unsigned    opB = SkColorGetB(fOpColor) >> (8 - SK_R16_BITS);
-    uint32_t    mul = fDistMul;
-    uint32_t    sub = (fDistMul - (1 << 14)) << SK_R16_BITS;
-
-    int MAX, mask;
-
-    if (kTargetColor_Mode == fMode) {
-        mask = -1;
-        MAX = 31;
-    } else {
-        mask = 0;
-        MAX = 0;
-    }
-
-    for (int i = 0; i < count; i++) {
-        int d = color_dist16(dst[i], opR, opG, opB);
-        // now reverse d if we need to
-        d = MAX + (d ^ mask) - mask;
-        SkASSERT((unsigned)d <= 31);
-        // convert from 0..31 to 0..32
-        d += d >> 4;
-        d = scale_dist_14(d, mul, sub);
-        SkASSERT(d <= 32);
-
-        if (d > 0) {
-            if (aa) {
-                d = SkAlphaMul(d, Accurate255To256(*aa++));
-                if (0 == d) {
-                    continue;
-                }
-            }
-            dst[i] = SkBlend3216(src[i], dst[i], d);
-        }
-    }
-}
-
-void AvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count,
-        const SkAlpha aa[]) const {
-}
-
-#ifndef SK_IGNORE_TO_STRING
-void AvoidXfermode::toString(SkString* str) const {
-    str->append("AvoidXfermode: opColor: ");
-    str->appendHex(fOpColor);
-    str->appendf("distMul: %d ", fDistMul);
-
-    static const char* gModeStrings[] = { "Avoid", "Target" };
-
-    str->appendf("mode: %s", gModeStrings[fMode]);
-}
-#endif
diff --git a/core/jni/android/graphics/AvoidXfermode.h b/core/jni/android/graphics/AvoidXfermode.h
deleted file mode 100644
index 8b7fb71..0000000
--- a/core/jni/android/graphics/AvoidXfermode.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef AvoidXfermode_DEFINED
-#define AvoidXfermode_DEFINED
-
-#include "SkColor.h"
-#include "SkTypes.h"
-#include "SkXfermode.h"
-
-/** \class AvoidXfermode
-
-    This xfermode will draw the src everywhere except on top of the specified
-    color.
-*/
-class AvoidXfermode : public SkXfermode {
-public:
-    enum Mode {
-        kAvoidColor_Mode,   //!< draw everywhere except on the opColor
-        kTargetColor_Mode   //!< draw only on top of the opColor
-    };
-
-    /** This xfermode draws, or doesn't draw, based on the destination's
-        distance from an op-color.
-
-        There are two modes, and each mode interprets a tolerance value.
-
-        Avoid: In this mode, drawing is allowed only on destination pixels that
-               are different from the op-color.
-               Tolerance near 0: avoid any colors even remotely similar to the op-color
-               Tolerance near 255: avoid only colors nearly identical to the op-color
-
-        Target: In this mode, drawing only occurs on destination pixels that
-                are similar to the op-color
-                Tolerance near 0: draw only on colors that are nearly identical to the op-color
-                Tolerance near 255: draw on any colors even remotely similar to the op-color
-     */
-    static AvoidXfermode* Create(SkColor opColor, U8CPU tolerance, Mode mode) {
-        return new AvoidXfermode(opColor, tolerance, mode);
-    }
-
-    // overrides from SkXfermode
-    void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
-            const SkAlpha aa[]) const override;
-    void xfer16(uint16_t dst[], const SkPMColor src[], int count,
-            const SkAlpha aa[]) const override;
-    void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
-            const SkAlpha aa[]) const override;
-
-    SK_TO_STRING_OVERRIDE()
-    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(AvoidXfermode)
-
-protected:
-    AvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode);
-    void flatten(SkWriteBuffer&) const override;
-
-private:
-    SkColor     fOpColor;
-    uint32_t    fDistMul;   // x.14 cached from fTolerance
-    uint8_t     fTolerance;
-    Mode        fMode;
-
-    typedef SkXfermode INHERITED;
-};
-
-#endif
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 27b9830..22a81d4 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -251,13 +251,6 @@
 
 void Bitmap::reconfigure(const SkImageInfo& info, size_t rowBytes,
         SkColorTable* ctable) {
-    {
-        android::AutoMutex _lock(mLock);
-        if (mPinnedRefCount) {
-            ALOGW("Called reconfigure on a bitmap that is in use! This may"
-                    " cause graphical corruption!");
-        }
-    }
     mPixelRef->reconfigure(info, rowBytes, ctable);
 }
 
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 27d8fed..f46f45c 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -768,6 +768,22 @@
         return false;
     }
 
+    // Returns true if the given string is exact one pair of regional indicators.
+    static bool isFlag(const jchar* str, size_t length) {
+        const jchar RI_LEAD_SURROGATE = 0xD83C;
+        const jchar RI_TRAIL_SURROGATE_MIN = 0xDDE6;
+        const jchar RI_TRAIL_SURROGATE_MAX = 0xDDFF;
+
+        if (length != 4) {
+            return false;
+        }
+        if (str[0] != RI_LEAD_SURROGATE || str[2] != RI_LEAD_SURROGATE) {
+            return false;
+        }
+        return RI_TRAIL_SURROGATE_MIN <= str[1] && str[1] <= RI_TRAIL_SURROGATE_MAX &&
+            RI_TRAIL_SURROGATE_MIN <= str[3] && str[3] <= RI_TRAIL_SURROGATE_MAX;
+    }
+
     static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle,
             jint bidiFlags, jstring string) {
         const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
@@ -817,13 +833,32 @@
             // in joining scripts, such as Arabic and Mongolian.
             return false;
         }
-        return nGlyphs > 0 && !layoutContainsNotdef(layout);
+
+        if (nGlyphs == 0 || layoutContainsNotdef(layout)) {
+            return false;  // The collection doesn't have a glyph.
+        }
+
+        if (nChars == 2 && isFlag(str.get(), str.size())) {
+            // Some font may have a special glyph for unsupported regional indicator pairs.
+            // To return false for this case, need to compare the glyph id with the one of ZZ
+            // since ZZ is reserved for unknown or invalid territory.
+            // U+1F1FF (REGIONAL INDICATOR SYMBOL LETTER Z) is \uD83C\uDDFF in UTF16.
+            static const jchar ZZ_FLAG_STR[] = { 0xD83C, 0xDDFF, 0xD83C, 0xDDFF };
+            Layout zzLayout;
+            MinikinUtils::doLayout(&zzLayout, paint, bidiFlags, typeface, ZZ_FLAG_STR, 0, 4, 4);
+            if (zzLayout.nGlyphs() != 1 || layoutContainsNotdef(zzLayout)) {
+                // The font collection doesn't have a glyph for unknown flag. Just return true.
+                return true;
+            }
+            return zzLayout.getGlyphId(0) != layout.getGlyphId(0);
+        }
+        return true;
     }
 
     static jfloat doRunAdvance(const Paint* paint, Typeface* typeface, const jchar buf[],
             jint start, jint count, jint bufSize, jboolean isRtl, jint offset) {
         int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
-        if (offset == count) {
+        if (offset == start + count) {
             return MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count,
                     bufSize, nullptr);
         }
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 2018e76..6e9830e 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -65,12 +65,12 @@
     EGLContext ctx = eglGetCurrentContext();
 
     if (dpy == EGL_NO_DISPLAY) {
-        ALOGE("isProtectedSurface: invalid current EGLDisplay");
+        ALOGI("isProtectedSurface: invalid current EGLDisplay");
         return false;
     }
 
     if (ctx == EGL_NO_CONTEXT) {
-        ALOGE("isProtectedSurface: invalid current EGLContext");
+        ALOGI("isProtectedSurface: invalid current EGLContext");
         return false;
     }
 
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index a2662f9..b04293e 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#include "jni.h"
 #include "GraphicsJNI.h"
+#include "jni.h"
 #include "core_jni_helpers.h"
-#include "log/log.h"
 
+#include "PathParser.h"
 #include "VectorDrawable.h"
 
 #include <hwui/Paint.h>
@@ -27,43 +27,15 @@
 using namespace uirenderer;
 using namespace uirenderer::VectorDrawable;
 
+/**
+ * VectorDrawable's pre-draw construction.
+ */
 static jlong createTree(JNIEnv*, jobject, jlong groupPtr) {
     VectorDrawable::Group* rootGroup = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
     VectorDrawable::Tree* tree = new VectorDrawable::Tree(rootGroup);
     return reinterpret_cast<jlong>(tree);
 }
 
-static void setTreeViewportSize(JNIEnv*, jobject, jlong treePtr,
-        jfloat viewportWidth, jfloat viewportHeight) {
-    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
-    tree->setViewportSize(viewportWidth, viewportHeight);
-}
-
-static jboolean setRootAlpha(JNIEnv*, jobject, jlong treePtr, jfloat alpha) {
-    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
-    return tree->setRootAlpha(alpha);
-}
-
-static jfloat getRootAlpha(JNIEnv*, jobject, jlong treePtr) {
-    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
-    return tree->getRootAlpha();
-}
-
-static void setAllowCaching(JNIEnv*, jobject, jlong treePtr, jboolean allowCaching) {
-    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
-    tree->setAllowCaching(allowCaching);
-}
-
-static void draw(JNIEnv* env, jobject, jlong treePtr, jlong canvasPtr,
-        jlong colorFilterPtr, jobject jrect, jboolean needsMirroring, jboolean canReuseCache) {
-    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
-    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
-    SkRect rect;
-    GraphicsJNI::jrect_to_rect(env, jrect, &rect);
-    SkColorFilter* colorFilter = reinterpret_cast<SkColorFilter*>(colorFilterPtr);
-    tree->draw(canvas, colorFilter, rect, needsMirroring, canReuseCache);
-}
-
 static jlong createEmptyFullPath(JNIEnv*, jobject) {
     VectorDrawable::FullPath* newPath = new VectorDrawable::FullPath();
     return reinterpret_cast<jlong>(newPath);
@@ -76,46 +48,6 @@
     return reinterpret_cast<jlong>(newPath);
 }
 
-static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr,
-        jfloat strokeWidth, jint strokeColor, jfloat strokeAlpha, jint fillColor, jfloat fillAlpha,
-        jfloat trimPathStart, jfloat trimPathEnd, jfloat trimPathOffset, jfloat strokeMiterLimit,
-        jint strokeLineCap, jint strokeLineJoin, jint fillType) {
-    VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    fullPath->updateProperties(strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha,
-            trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit, strokeLineCap,
-            strokeLineJoin, fillType);
-}
-
-static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
-    VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
-    SkShader* fillShader = reinterpret_cast<SkShader*>(fillGradientPtr);
-    path->setFillGradient(fillShader);
-}
-
-static void updateFullPathStrokeGradient(JNIEnv*, jobject, jlong pathPtr, jlong strokeGradientPtr) {
-    VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
-    SkShader* strokeShader = reinterpret_cast<SkShader*>(strokeGradientPtr);
-    path->setStrokeGradient(strokeShader);
-}
-
-static jboolean getFullPathProperties(JNIEnv* env, jobject, jlong fullPathPtr,
-        jbyteArray outProperties, jint length) {
-    VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    int8_t pathProperties[length];
-    bool success = fullPath->getProperties(pathProperties, length);
-    env->SetByteArrayRegion(outProperties, 0, length, reinterpret_cast<int8_t*>(&pathProperties));
-    return success;
-}
-
-static jboolean getGroupProperties(JNIEnv* env, jobject, jlong groupPtr,
-        jfloatArray outProperties, jint length) {
-    VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    float groupProperties[length];
-    bool success = group->getProperties(groupProperties, length);
-    env->SetFloatArrayRegion(outProperties, 0, length, reinterpret_cast<float*>(&groupProperties));
-    return success;
-}
-
 static jlong createEmptyClipPath(JNIEnv*, jobject) {
     VectorDrawable::ClipPath* newPath = new VectorDrawable::ClipPath();
     return reinterpret_cast<jlong>(newPath);
@@ -146,180 +78,265 @@
     env->ReleaseStringUTFChars(nameStr, nodeName);
 }
 
-static void updateGroupProperties(JNIEnv*, jobject, jlong groupPtr, jfloat rotate, jfloat pivotX,
-        jfloat pivotY, jfloat scaleX, jfloat scaleY, jfloat translateX, jfloat translateY) {
-    VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    group->updateLocalMatrix(rotate, pivotX, pivotY, scaleX, scaleY, translateX, translateY);
-}
-
 static void addChild(JNIEnv*, jobject, jlong groupPtr, jlong childPtr) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
     VectorDrawable::Node* child = reinterpret_cast<VectorDrawable::Node*>(childPtr);
     group->addChild(child);
 }
 
+static void setAllowCaching(JNIEnv*, jobject, jlong treePtr, jboolean allowCaching) {
+    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+    tree->setAllowCaching(allowCaching);
+}
+
+/**
+ * Draw
+ */
+static void draw(JNIEnv* env, jobject, jlong treePtr, jlong canvasPtr,
+        jlong colorFilterPtr, jobject jrect, jboolean needsMirroring, jboolean canReuseCache) {
+    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
+    SkRect rect;
+    GraphicsJNI::jrect_to_rect(env, jrect, &rect);
+    SkColorFilter* colorFilter = reinterpret_cast<SkColorFilter*>(colorFilterPtr);
+    tree->draw(canvas, colorFilter, rect, needsMirroring, canReuseCache);
+}
+
+/**
+ * Setters and getters for updating staging properties that can happen both pre-draw and post draw.
+ */
+static void setTreeViewportSize(JNIEnv*, jobject, jlong treePtr,
+        jfloat viewportWidth, jfloat viewportHeight) {
+    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+    tree->mutateStagingProperties()->setViewportSize(viewportWidth, viewportHeight);
+}
+
+static jboolean setRootAlpha(JNIEnv*, jobject, jlong treePtr, jfloat alpha) {
+    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+    return tree->mutateStagingProperties()->setRootAlpha(alpha);
+}
+
+static jfloat getRootAlpha(JNIEnv*, jobject, jlong treePtr) {
+    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
+    return tree->stagingProperties()->getRootAlpha();
+}
+
+static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr,
+        jfloat strokeWidth, jint strokeColor, jfloat strokeAlpha, jint fillColor, jfloat fillAlpha,
+        jfloat trimPathStart, jfloat trimPathEnd, jfloat trimPathOffset, jfloat strokeMiterLimit,
+        jint strokeLineCap, jint strokeLineJoin, jint fillType) {
+    VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
+    fullPath->mutateStagingProperties()->updateProperties(strokeWidth, strokeColor, strokeAlpha,
+            fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit,
+            strokeLineCap, strokeLineJoin, fillType);
+}
+
+static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
+    VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
+    SkShader* fillShader = reinterpret_cast<SkShader*>(fillGradientPtr);
+    path->mutateStagingProperties()->setFillGradient(fillShader);
+}
+
+static void updateFullPathStrokeGradient(JNIEnv*, jobject, jlong pathPtr, jlong strokeGradientPtr) {
+    VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
+    SkShader* strokeShader = reinterpret_cast<SkShader*>(strokeGradientPtr);
+    path->mutateStagingProperties()->setStrokeGradient(strokeShader);
+}
+
+static jboolean getFullPathProperties(JNIEnv* env, jobject, jlong fullPathPtr,
+        jbyteArray outProperties, jint length) {
+    VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
+    int8_t pathProperties[length];
+    bool success = fullPath->stagingProperties()->copyProperties(pathProperties, length);
+    env->SetByteArrayRegion(outProperties, 0, length, reinterpret_cast<int8_t*>(&pathProperties));
+    return success;
+}
+
+static jboolean getGroupProperties(JNIEnv* env, jobject, jlong groupPtr,
+        jfloatArray outProperties, jint length) {
+    VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
+    float groupProperties[length];
+    bool success = group->stagingProperties()->copyProperties(groupProperties, length);
+    env->SetFloatArrayRegion(outProperties, 0, length, reinterpret_cast<float*>(&groupProperties));
+    return success;
+}
+
+static void updateGroupProperties(JNIEnv*, jobject, jlong groupPtr, jfloat rotate, jfloat pivotX,
+        jfloat pivotY, jfloat scaleX, jfloat scaleY, jfloat translateX, jfloat translateY) {
+    VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
+    group->mutateStagingProperties()->updateProperties(rotate, pivotX, pivotY, scaleX, scaleY,
+            translateX, translateY);
+}
+
 static void setPathString(JNIEnv* env, jobject, jlong pathPtr, jstring inputStr,
         jint stringLength) {
     VectorDrawable::Path* path = reinterpret_cast<VectorDrawable::Path*>(pathPtr);
     const char* pathString = env->GetStringUTFChars(inputStr, NULL);
-    path->setPath(pathString, stringLength);
+
+    PathParser::ParseResult result;
+    PathData data;
+    PathParser::getPathDataFromString(&data, &result, pathString, stringLength);
+    path->mutateStagingProperties()->setData(data);
     env->ReleaseStringUTFChars(inputStr, pathString);
 }
 
+/**
+ * Setters and getters that should only be called from animation thread for animation purpose.
+ */
 static jfloat getRotation(JNIEnv*, jobject, jlong groupPtr) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    return group->getRotation();
+    return group->stagingProperties()->getRotation();
 }
 
 static void setRotation(JNIEnv*, jobject, jlong groupPtr, jfloat rotation) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    group->setRotation(rotation);
+    group->mutateStagingProperties()->setRotation(rotation);
 }
 
 static jfloat getPivotX(JNIEnv*, jobject, jlong groupPtr) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    return group->getPivotX();
+    return group->stagingProperties()->getPivotX();
 }
 
 static void setPivotX(JNIEnv*, jobject, jlong groupPtr, jfloat pivotX) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    group->setPivotX(pivotX);
+    group->mutateStagingProperties()->setPivotX(pivotX);
 }
 
 static jfloat getPivotY(JNIEnv*, jobject, jlong groupPtr) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    return group->getPivotY();
+    return group->stagingProperties()->getPivotY();
 }
 
 static void setPivotY(JNIEnv*, jobject, jlong groupPtr, jfloat pivotY) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    group->setPivotY(pivotY);
+    group->mutateStagingProperties()->setPivotY(pivotY);
 }
 
 static jfloat getScaleX(JNIEnv*, jobject, jlong groupPtr) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    return group->getScaleX();
+    return group->stagingProperties()->getScaleX();
 }
 
 static void setScaleX(JNIEnv*, jobject, jlong groupPtr, jfloat scaleX) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    group->setScaleX(scaleX);
+    group->mutateStagingProperties()->setScaleX(scaleX);
 }
 
 static jfloat getScaleY(JNIEnv*, jobject, jlong groupPtr) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    return group->getScaleY();
+    return group->stagingProperties()->getScaleY();
 }
 
 static void setScaleY(JNIEnv*, jobject, jlong groupPtr, jfloat scaleY) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    group->setScaleY(scaleY);
+    group->mutateStagingProperties()->setScaleY(scaleY);
 }
 
 static jfloat getTranslateX(JNIEnv*, jobject, jlong groupPtr) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    return group->getTranslateX();
+    return group->stagingProperties()->getTranslateX();
 }
 
 static void setTranslateX(JNIEnv*, jobject, jlong groupPtr, jfloat translateX) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    group->setTranslateX(translateX);
+    group->mutateStagingProperties()->setTranslateX(translateX);
 }
 
 static jfloat getTranslateY(JNIEnv*, jobject, jlong groupPtr) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    return group->getTranslateY();
+    return group->stagingProperties()->getTranslateY();
 }
 
 static void setTranslateY(JNIEnv*, jobject, jlong groupPtr, jfloat translateY) {
     VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(groupPtr);
-    group->setTranslateY(translateY);
+    group->mutateStagingProperties()->setTranslateY(translateY);
 }
 
 static void setPathData(JNIEnv*, jobject, jlong pathPtr, jlong pathDataPtr) {
     VectorDrawable::Path* path = reinterpret_cast<VectorDrawable::Path*>(pathPtr);
     PathData* pathData = reinterpret_cast<PathData*>(pathDataPtr);
-    path->setPathData(*pathData);
+    path->mutateStagingProperties()->setData(*pathData);
 }
 
 static jfloat getStrokeWidth(JNIEnv*, jobject, jlong fullPathPtr) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    return fullPath->getStrokeWidth();
+    return fullPath->stagingProperties()->getStrokeWidth();
 }
 
 static void setStrokeWidth(JNIEnv*, jobject, jlong fullPathPtr, jfloat strokeWidth) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    fullPath->setStrokeWidth(strokeWidth);
+    fullPath->mutateStagingProperties()->setStrokeWidth(strokeWidth);
 }
 
 static jint getStrokeColor(JNIEnv*, jobject, jlong fullPathPtr) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    return fullPath->getStrokeColor();
+    return fullPath->stagingProperties()->getStrokeColor();
 }
 
 static void setStrokeColor(JNIEnv*, jobject, jlong fullPathPtr, jint strokeColor) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    fullPath->setStrokeColor(strokeColor);
+    fullPath->mutateStagingProperties()->setStrokeColor(strokeColor);
 }
 
 static jfloat getStrokeAlpha(JNIEnv*, jobject, jlong fullPathPtr) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    return fullPath->getStrokeAlpha();
+    return fullPath->stagingProperties()->getStrokeAlpha();
 }
 
 static void setStrokeAlpha(JNIEnv*, jobject, jlong fullPathPtr, jfloat strokeAlpha) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    fullPath->setStrokeAlpha(strokeAlpha);
+    fullPath->mutateStagingProperties()->setStrokeAlpha(strokeAlpha);
 }
 
 static jint getFillColor(JNIEnv*, jobject, jlong fullPathPtr) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    return fullPath->getFillColor();
+    return fullPath->stagingProperties()->getFillColor();
 }
 
 static void setFillColor(JNIEnv*, jobject, jlong fullPathPtr, jint fillColor) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    fullPath->setFillColor(fillColor);
+    fullPath->mutateStagingProperties()->setFillColor(fillColor);
 }
 
 static jfloat getFillAlpha(JNIEnv*, jobject, jlong fullPathPtr) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    return fullPath->getFillAlpha();
+    return fullPath->stagingProperties()->getFillAlpha();
 }
 
 static void setFillAlpha(JNIEnv*, jobject, jlong fullPathPtr, jfloat fillAlpha) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    fullPath->setFillAlpha(fillAlpha);
+    fullPath->mutateStagingProperties()->setFillAlpha(fillAlpha);
 }
 
 static jfloat getTrimPathStart(JNIEnv*, jobject, jlong fullPathPtr) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    return fullPath->getTrimPathStart();
+    return fullPath->stagingProperties()->getTrimPathStart();
 }
 
 static void setTrimPathStart(JNIEnv*, jobject, jlong fullPathPtr, jfloat trimPathStart) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    fullPath->setTrimPathStart(trimPathStart);
+    fullPath->mutateStagingProperties()->setTrimPathStart(trimPathStart);
 }
 
 static jfloat getTrimPathEnd(JNIEnv*, jobject, jlong fullPathPtr) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    return fullPath->getTrimPathEnd();
+    return fullPath->stagingProperties()->getTrimPathEnd();
 }
 
 static void setTrimPathEnd(JNIEnv*, jobject, jlong fullPathPtr, jfloat trimPathEnd) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    fullPath->setTrimPathEnd(trimPathEnd);
+    fullPath->mutateStagingProperties()->setTrimPathEnd(trimPathEnd);
 }
 
 static jfloat getTrimPathOffset(JNIEnv*, jobject, jlong fullPathPtr) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    return fullPath->getTrimPathOffset();
+    return fullPath->stagingProperties()->getTrimPathOffset();
 }
 
 static void setTrimPathOffset(JNIEnv*, jobject, jlong fullPathPtr, jfloat trimPathOffset) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
-    fullPath->setTrimPathOffset(trimPathOffset);
+    fullPath->mutateStagingProperties()->setTrimPathOffset(trimPathOffset);
 }
 
 static const JNINativeMethod gMethods[] = {
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index 8724729..91a3b4f 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -16,23 +16,39 @@
 
 #include "context_hub.h"
 
+#define LOG_NDEBUG 0
+#define LOG_TAG "ContextHubService"
+
+#include <inttypes.h>
+#include <jni.h>
+#include <map>
+#include <queue>
 #include <string.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <stdlib.h>
 
-#include <jni.h>
+#include <cutils/log.h>
+
 #include "JNIHelp.h"
 #include "core_jni_helpers.h"
-#include "stdint.h"
-#include "stdlib.h"
+
+static constexpr int OS_APP_ID=-1;
+
+static constexpr int MIN_APP_ID=1;
+static constexpr int MAX_APP_ID=128;
+
+static constexpr size_t MSG_HEADER_SIZE=4;
+static constexpr int HEADER_FIELD_MSG_TYPE=0;
+//static constexpr int HEADER_FIELD_MSG_VERSION=1;
+static constexpr int HEADER_FIELD_HUB_HANDLE=2;
+static constexpr int HEADER_FIELD_APP_INSTANCE=3;
 
 
 namespace android {
 
 namespace {
 
-// TODO: We should share this array_length function widely around Android
-//     code.
 /*
  * Finds the length of a statically-sized array using template trickery that
  * also prevents it from being applied to the wrong type.
@@ -64,35 +80,215 @@
     jmethodID contextHubInfoSetPeakPowerDrawMw;
     jmethodID contextHubInfoSetSupportedSensors;
     jmethodID contextHubInfoSetMemoryRegions;
+    jmethodID contextHubInfoSetMaxPacketLenBytes;
 
     jmethodID contextHubServiceMsgReceiptCallback;
+    jmethodID contextHubServiceAddAppInstance;
 };
 
 struct context_hub_info_s {
-    int cookie;
+    uint32_t *cookies;
     int numHubs;
     const struct context_hub_t *hubs;
     struct context_hub_module_t *contextHubModule;
 };
 
+struct app_instance_info_s {
+    uint32_t hubHandle; // Id of the hub this app is on
+    int instanceId; // systemwide unique instance id - assigned
+    struct hub_app_info appInfo; // returned from the HAL
+    uint64_t truncName; // Possibly truncated name - logging
+};
+
 struct contextHubServiceDb_s {
     int initialized;
     context_hub_info_s hubInfo;
     jniInfo_s jniInfo;
+    std::queue<int> freeIds;
+    std::map<int, app_instance_info_s *> appInstances;
 };
 
 }  // unnamed namespace
 
 static contextHubServiceDb_s db;
 
-int context_hub_callback(uint32_t hub_id, const struct hub_message_t *msg,
+int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg,
                          void *cookie);
 
+const context_hub_t *get_hub_info(int hubHandle) {
+    if (hubHandle >= 0 && hubHandle < db.hubInfo.numHubs) {
+        return &db.hubInfo.hubs[hubHandle];
+    }
+    return nullptr;
+}
+
+static int send_msg_to_hub(const hub_message_t *msg, int hubHandle) {
+    const context_hub_t *info = get_hub_info(hubHandle);
+
+    if (info) {
+        return db.hubInfo.contextHubModule->send_message(info->hub_id, msg);
+    } else {
+        ALOGD("%s: Hub information is null for hubHandle %d", __FUNCTION__, hubHandle);
+        return -1;
+    }
+}
+
+static int set_os_app_as_destination(hub_message_t *msg, int hubHandle) {
+    const context_hub_t *info = get_hub_info(hubHandle);
+
+    if (info) {
+        msg->app = info->os_app_name;
+        return 0;
+    } else {
+        ALOGD("%s: Hub information is null for hubHandle %d", __FUNCTION__, hubHandle);
+        return -1;
+    }
+}
+
+static int get_hub_id_for_hub_handle(int hubHandle) {
+    if (hubHandle < 0 || hubHandle >= db.hubInfo.numHubs) {
+      return -1;
+    } else {
+      return db.hubInfo.hubs[hubHandle].hub_id;
+    }
+}
+
+static int get_hub_id_for_app_instance(int id) {
+    if (db.appInstances.find(id) == db.appInstances.end()) {
+        ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id);
+        return -1;
+    }
+
+    int hubHandle = db.appInstances[id]->hubHandle;
+
+    return db.hubInfo.hubs[hubHandle].hub_id;
+}
+
+static int set_dest_app(hub_message_t *msg, int id) {
+    if (db.appInstances.find(id) == db.appInstances.end()) {
+        ALOGD("%s: Cannod find app for app instance %d", __FUNCTION__, id);
+        return -1;
+    }
+
+    msg->app = db.appInstances[id]->appInfo.name;
+    return 0;
+}
+
+static void send_query_for_apps() {
+    hub_message_t msg;
+
+    msg.message_type = CONTEXT_HUB_QUERY_APPS;
+    msg.message_len  = 0;
+
+    for (int i = 0; i < db.hubInfo.numHubs; i++ ) {
+        ALOGD("Sending query for apps to hub %d", i);
+        set_os_app_as_destination(&msg, i);
+        if (send_msg_to_hub(&msg, i) != 0) {
+          ALOGW("Could not query hub %i for apps", i);
+        }
+    }
+}
+
+static int return_id(int id) {
+    // Note : This method is not thread safe.
+    // id returned is guarenteed to be in use
+    db.freeIds.push(id);
+    return 0;
+}
+
+static int generate_id(void) {
+    // Note : This method is not thread safe.
+    int retVal = -1;
+
+    if (!db.freeIds.empty()) {
+        retVal = db.freeIds.front();
+        db.freeIds.pop();
+    }
+
+    return retVal;
+}
+
+int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *env) {
+    // Not checking if the apps are indeed distinct
+
+    app_instance_info_s *entry;
+    void *appName;
+    hub_app_name_t *name;
+
+    assert(appInfo && appInfo->name && appInfo->name->app_name);
+
+    entry = (app_instance_info_s *) malloc(sizeof(app_instance_info_s));
+    appName = malloc(appInfo->name->app_name_len);
+    name = (hub_app_name_t *) malloc(sizeof(hub_app_name_t));
+
+    int appInstanceHandle = generate_id();
+
+    if (appInstanceHandle < 0 || !appName || !entry || !name) {
+        ALOGE("Cannot find resources to add app instance %d, %p, %p",
+            appInstanceHandle, appName, entry);
+
+        free(appName);
+        free(entry);
+        free(name);
+
+        if (appInstanceHandle >= 0) {
+            return_id(appInstanceHandle);
+        }
+
+        return -1;
+    }
+
+    memcpy(&(entry->appInfo), appInfo, sizeof(entry->appInfo));
+    memcpy(appName, appInfo->name->app_name, appInfo->name->app_name_len);
+    name->app_name = appName;
+    name->app_name_len = appInfo->name->app_name_len;
+    entry->appInfo.name = name;
+    entry->truncName = 0;
+    memcpy(&(entry->truncName), name->app_name,
+           sizeof(entry->truncName) < name->app_name_len ?
+           sizeof(entry->truncName) : name->app_name_len);
+
+    // Not checking for sanity of hubId
+    entry->hubHandle = hubHandle;
+    entry->instanceId = appInstanceHandle;
+    db.appInstances[appInstanceHandle] = entry;
+
+    // Finally - let the service know of this app instance
+    env->CallIntMethod(db.jniInfo.jContextHubService,
+                       db.jniInfo.contextHubServiceAddAppInstance,
+                       hubHandle, entry->instanceId, entry->truncName,
+                       entry->appInfo.version);
+
+    ALOGW("Added App 0x%" PRIx64 " on hub Handle %" PRId32
+          " as appInstance %d, original name_length %" PRId32, entry->truncName,
+          entry->hubHandle, appInstanceHandle, name->app_name_len);
+
+    return appInstanceHandle;
+}
+
+int delete_app_instance(int id) {
+    if (db.appInstances.find(id) == db.appInstances.end()) {
+        return -1;
+    }
+
+    return_id(id);
+
+    if (db.appInstances[id]) {
+        // Losing the const cast below. This is intentional.
+        free((void *)db.appInstances[id]->appInfo.name->app_name);
+        free((void *)db.appInstances[id]->appInfo.name);
+        free(db.appInstances[id]);
+        db.appInstances.erase(id);
+    }
+
+    return 0;
+}
+
+
 static void initContextHubService() {
     int err = 0;
-    db.hubInfo.hubs = NULL;
+    db.hubInfo.hubs = nullptr;
     db.hubInfo.numHubs = 0;
-    db.hubInfo.cookie = 0;
     int i;
 
     err = hw_get_module(CONTEXT_HUB_MODULE_ID,
@@ -103,26 +299,45 @@
             strerror(-err));
     }
 
-    if (db.hubInfo.contextHubModule) {
-      ALOGD("Fetching hub info");
-      db.hubInfo.numHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule,
-                                                                 &db.hubInfo.hubs);
+    // Prep for storing app info
+    for(i = MIN_APP_ID; i <= MAX_APP_ID; i++) {
+        db.freeIds.push(i);
+    }
 
-      if (db.hubInfo.numHubs > 0) {
-        for (i = 0; i < db.hubInfo.numHubs; i++) {
-          // TODO : Event though one cookie is OK for now, lets change
-          // this to be one per hub
-          db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id,
-                                                          context_hub_callback,
-                                                          &db.hubInfo.cookie);
+    if (db.hubInfo.contextHubModule) {
+        int retNumHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule,
+                                                                 &db.hubInfo.hubs);
+        ALOGD("ContextHubModule returned %d hubs ", retNumHubs);
+        db.hubInfo.numHubs = retNumHubs;
+
+        if (db.hubInfo.numHubs > 0) {
+            db.hubInfo.numHubs = retNumHubs;
+            db.hubInfo.cookies = (uint32_t *)malloc(sizeof(uint32_t) * db.hubInfo.numHubs);
+
+            if (!db.hubInfo.cookies) {
+                ALOGW("Ran out of memory allocating cookies, bailing");
+                return;
+            }
+
+            for (i = 0; i < db.hubInfo.numHubs; i++) {
+                db.hubInfo.cookies[i] = db.hubInfo.hubs[i].hub_id;
+                if (db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id,
+                                                                    context_hub_callback,
+                                                                    &db.hubInfo.cookies[i]) == 0) {
+                }
+            }
         }
-      }
+
+        send_query_for_apps();
+    } else {
+        ALOGW("No Context Hub Module present");
     }
 }
 
 static int onMessageReceipt(int *header, int headerLen, char *msg, int msgLen) {
     JNIEnv *env;
-    if ((db.jniInfo.vm)->AttachCurrentThread(&env, NULL) != JNI_OK) {
+
+    if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
       return -1;
     }
 
@@ -132,28 +347,134 @@
     env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
     env->SetIntArrayRegion(jheader, 0, headerLen, (jint *)header);
 
-
-    return env->CallIntMethod(db.jniInfo.jContextHubService,
+    return (env->CallIntMethod(db.jniInfo.jContextHubService,
                           db.jniInfo.contextHubServiceMsgReceiptCallback,
-                          jheader, jmsg);
+                          jheader, jmsg) != 0);
 }
 
-int context_hub_callback(uint32_t hub_id, const struct hub_message_t *msg,
+int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) {
+    int i;
+    JNIEnv *env;
+    if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
+            return -1;
+    }
+
+    int numApps = msgLen/sizeof(hub_app_info);
+    hub_app_info *info = (hub_app_info *)malloc(msgLen); // handle possible alignment
+
+    if (!info) {
+        return -1;
+    }
+
+    memcpy(info, msg, msgLen);
+    for (i = 0; i < numApps; i++) {
+        add_app_instance(info, hubHandle, env);
+        info++;
+    }
+
+    free(info);
+
+    return 0;
+}
+
+
+int handle_os_message(uint32_t msgType, uint32_t hubHandle,
+                      char *msg, int msgLen) {
+    int retVal;
+
+    //ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
+    //      hubHandle, msgType, msgLen);
+
+    switch(msgType) {
+        case CONTEXT_HUB_APPS_ENABLE:
+            retVal = 0;
+            break;
+
+        case CONTEXT_HUB_APPS_DISABLE:
+            retVal = 0;
+            break;
+
+        case CONTEXT_HUB_LOAD_APP:
+            retVal = 0;
+            break;
+
+        case CONTEXT_HUB_UNLOAD_APP:
+            retVal = 0;
+            break;
+
+        case CONTEXT_HUB_QUERY_APPS:
+            retVal = handle_query_apps_response(msg, msgLen, hubHandle);
+            break;
+
+        case CONTEXT_HUB_QUERY_MEMORY:
+            retVal = 0;
+            break;
+
+        case CONTEXT_HUB_LOAD_OS:
+            retVal = 0;
+            break;
+
+        default:
+            retVal = -1;
+            break;
+
+    }
+
+    return retVal;
+}
+
+static bool sanity_check_cookie(void *cookie, uint32_t hub_id) {
+    int *ptr = (int *)cookie;
+
+    if (!ptr || *ptr >= db.hubInfo.numHubs) {
+        return false;
+    }
+
+    if (db.hubInfo.hubs[*ptr].hub_id != hub_id) {
+        return false;
+    } else {
+        return true;
+    }
+}
+
+int context_hub_callback(uint32_t hubId,
+                         const struct hub_message_t *msg,
                          void *cookie) {
-  int msgHeader[4];
+    int msgHeader[MSG_HEADER_SIZE];
 
-  msgHeader[0] = msg->message_type;
-  msgHeader[1] = 0; // TODO : HAL does not have a version field
-  msgHeader[2] = hub_id;
+    if (!msg) {
+        return -1;
+    }
 
-  onMessageReceipt(msgHeader, sizeof(msgHeader), (char *)msg->message, msg->message_len); // TODO : Populate this
-  return 0;
+    msgHeader[HEADER_FIELD_MSG_TYPE] = msg->message_type;
+
+    if (!sanity_check_cookie(cookie, hubId)) {
+        ALOGW("Incorrect cookie %" PRId32 " for cookie %p! Bailing",
+              hubId, cookie);
+
+        return -1;
+    }
+
+    msgHeader[HEADER_FIELD_HUB_HANDLE] = *(uint32_t*)cookie;
+
+    if (msgHeader[HEADER_FIELD_MSG_TYPE] < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE &&
+        msgHeader[HEADER_FIELD_MSG_TYPE] != 0 ) {
+        handle_os_message(msgHeader[HEADER_FIELD_MSG_TYPE],
+                          msgHeader[HEADER_FIELD_HUB_HANDLE],
+                          (char *)msg->message,
+                          msg->message_len);
+    } else {
+        onMessageReceipt(msgHeader, sizeof(msgHeader),
+                         (char *)msg->message, msg->message_len);
+    }
+
+    return 0;
 }
 
 static int init_jni(JNIEnv *env, jobject instance) {
 
     if (env->GetJavaVM(&db.jniInfo.vm) != JNI_OK) {
-      return -1;
+        return -1;
     }
 
     db.jniInfo.jContextHubService = env->NewGlobalRef(instance);
@@ -167,7 +488,6 @@
     db.jniInfo.memoryRegionsClass =
             env->FindClass("android/hardware/location/MemoryRegion");
 
-    //TODO :: Add error checking
     db.jniInfo.contextHubInfoCtor =
             env->GetMethodID(db.jniInfo.contextHubInfoClass, "<init>", "()V");
     db.jniInfo.contextHubInfoSetId =
@@ -209,6 +529,9 @@
     db.jniInfo.contextHubInfoSetMemoryRegions =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
                                 "setMemoryRegions", "([Landroid/hardware/location/MemoryRegion;)V");
+    db.jniInfo.contextHubInfoSetMaxPacketLenBytes =
+             env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setMaxPacketLenBytes", "(I)V");
 
 
     db.jniInfo.contextHubServiceMsgReceiptCallback =
@@ -218,6 +541,11 @@
             env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName",
             "(Ljava/lang/String;)V");
 
+    db.jniInfo.contextHubServiceAddAppInstance =
+                 env->GetMethodID(db.jniInfo.contextHubServiceClass,
+                                    "addAppInstance", "(IIJI)I");
+
+
 
     return 0;
 }
@@ -245,20 +573,29 @@
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPlatformVersion, hub->platform_version);
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchainVersion, hub->toolchain_version);
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakMips, hub->peak_mips);
-    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetStoppedPowerDrawMw, hub->stopped_power_draw_mw);
-    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSleepPowerDrawMw, hub->sleep_power_draw_mw);
-    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakPowerDrawMw, hub->peak_power_draw_mw);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetStoppedPowerDrawMw,
+                        hub->stopped_power_draw_mw);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSleepPowerDrawMw,
+                        hub->sleep_power_draw_mw);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakPowerDrawMw,
+                        hub->peak_power_draw_mw);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMaxPacketLenBytes,
+                        hub->max_supported_msg_len);
+
 
     // TODO : jintBuf = env->NewIntArray(hub->num_connected_sensors);
-    // TODO : env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, hub->connected_sensors);
+    // TODO : env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors,
+    //                               hub->connected_sensors);
     jintBuf = env->NewIntArray(array_length(dummyConnectedSensors));
     env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, dummyConnectedSensors);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf);
 
     // We are not getting the memory regions from the CH Hal - change this when it is available
-    jmemBuf = env->NewObjectArray(0, db.jniInfo.memoryRegionsClass, NULL);
+    jmemBuf = env->NewObjectArray(0, db.jniInfo.memoryRegionsClass, nullptr);
     // Note the zero size above. We do not need to set any elements
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMemoryRegions, jmemBuf);
 
+
     return jHub;
 }
 
@@ -267,18 +604,18 @@
     jobject hub;
     jobjectArray retArray;
 
-    initContextHubService();
-
     if (init_jni(env, instance) < 0) {
-        return NULL;
+        return nullptr;
     }
 
-    // Note : The service is clamping the number of hubs to 1
-    db.hubInfo.numHubs = 1;
-
     initContextHubService();
 
-    retArray = env->NewObjectArray(db.hubInfo.numHubs, db.jniInfo.contextHubInfoClass, NULL);
+    if (db.hubInfo.numHubs > 1) {
+      ALOGW("Clamping the number of hubs to 1");
+      db.hubInfo.numHubs = 1;
+    }
+
+    retArray = env->NewObjectArray(db.hubInfo.numHubs, db.jniInfo.contextHubInfoClass, nullptr);
 
     for(int i = 0; i < db.hubInfo.numHubs; i++) {
         hub = constructJContextHubInfo(env, &db.hubInfo.hubs[i]);
@@ -290,29 +627,41 @@
 
 static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_,
                               jbyteArray data_) {
-    hub_message_t msg;
-    hub_app_name_t dest;
-    uint8_t os_name[8];
-
-    memset(os_name, 0, sizeof(os_name));
+    jint retVal = -1; // Default to failure
 
     jint *header = env->GetIntArrayElements(header_, 0);
-    //int numHeaderElements = env->GetArrayLength(header_);
+    unsigned int numHeaderElements = env->GetArrayLength(header_);
     jbyte *data = env->GetByteArrayElements(data_, 0);
     int dataBufferLength = env->GetArrayLength(data_);
 
-    /* Assume an int - thats all we understand */
-    dest.app_name_len = array_length(os_name); // TODO : Check this
-    //dest.app_name = &header[1];
-    dest.app_name = os_name;
 
-    msg.app = &dest;
+    if (numHeaderElements >= MSG_HEADER_SIZE) {
+        bool setAddressSuccess;
+        int hubId;
+        hub_message_t msg;
 
-    msg.message_type = header[3];
-    msg.message_len = dataBufferLength;
-    msg.message = data;
+        if (header[HEADER_FIELD_APP_INSTANCE] == OS_APP_ID) {
+            setAddressSuccess = (set_os_app_as_destination(&msg, header[HEADER_FIELD_HUB_HANDLE]) == 0);
+            hubId = get_hub_id_for_hub_handle(header[HEADER_FIELD_HUB_HANDLE]);
+        } else {
+            setAddressSuccess = (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0);
+            hubId = get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]);
+        }
 
-    jint retVal = db.hubInfo.contextHubModule->send_message(header[0], &msg);
+        if (setAddressSuccess && hubId >= 0) {
+            msg.message_type = header[HEADER_FIELD_MSG_TYPE];
+            msg.message_len = dataBufferLength;
+            msg.message = data;
+            retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
+        } else {
+          ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
+                header[HEADER_FIELD_APP_INSTANCE],
+                header[HEADER_FIELD_HUB_HANDLE],
+                (int)setAddressSuccess);
+        }
+    } else {
+        ALOGD("Malformed header len");
+    }
 
     env->ReleaseIntArrayElements(header_, header, 0);
     env->ReleaseByteArrayElements(data_, data, 0);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0a4ef98..9a2e39c7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -348,6 +348,8 @@
     <protected-broadcast android:name="android.app.action.DEVICE_OWNER_CHANGED" />
 
     <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_AVAILABILITY_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_AVAILABLE" />
+    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNAVAILABLE" />
 
     <!-- Added in N -->
     <protected-broadcast android:name="android.intent.action.ANR" />
@@ -399,7 +401,6 @@
     <protected-broadcast android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" />
 
     <protected-broadcast android:name="com.android.bluetooth.btservice.action.ALARM_WAKEUP" />
-    <protected-broadcast android:name="com.android.ims.IMS_SERVICE_UP" />
     <protected-broadcast android:name="com.android.server.action.NETWORK_STATS_POLL" />
     <protected-broadcast android:name="com.android.server.action.NETWORK_STATS_UPDATED" />
     <protected-broadcast android:name="com.android.server.NetworkTimeUpdateService.action.POLL" />
@@ -459,8 +460,15 @@
     <protected-broadcast android:name="android.net.wifi.PASSPOINT_ICON_RECEIVED" />
     <protected-broadcast android:name="com.android.server.notification.CountdownConditionProvider" />
 
-    <!-- @hide UCE service Notification -->
+    <protected-broadcast android:name="com.android.ims.IMS_SERVICE_UP" />
+    <protected-broadcast android:name="com.android.ims.IMS_INCOMING_CALL" />
     <protected-broadcast android:name="com.android.ims.internal.uce.UCE_SERVICE_UP" />
+    <protected-broadcast android:name="com.android.intent.action.IMS_FEATURE_CHANGED" />
+    <protected-broadcast android:name="com.android.intent.action.IMS_CONFIG_CHANGED" />
+
+    <protected-broadcast android:name="com.android.internal.location.ALARM_WAKEUP" />
+    <protected-broadcast android:name="com.android.internal.location.ALARM_TIMEOUT" />
+    <protected-broadcast android:name="android.intent.action.GLOBAL_BUTTON" />
 
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
@@ -845,14 +853,14 @@
     -->
     <permission android:name="android.permission.ACCESS_UCE_PRESENCE_SERVICE"
         android:permissionGroup="android.permission-group.PHONE"
-        android:protectionLevel="dangerous"/>
+        android:protectionLevel="signatureOrSystem"/>
 
     <!-- @hide Allows an application to Access UCE-OPTIONS.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_UCE_OPTIONS_SERVICE"
         android:permissionGroup="android.permission-group.PHONE"
-        android:protectionLevel="dangerous"/>
+        android:protectionLevel="signatureOrSystem"/>
 
 
 
@@ -2004,6 +2012,11 @@
     <permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows but does not guarantee access to user passwords at the conclusion of add
+         account -->
+    <permission android:name="android.permission.GET_PASSWORD_PRIVILEGED"
+        android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows applications to RW to diagnostic resources.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DIAGNOSTIC"
@@ -2984,6 +2997,16 @@
     <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Required to make calls to {@link android.service.vr.IVrManager}.
+         @hide -->
+    <permission android:name="android.permission.ACCESS_VR_MANAGER"
+            android:protectionLevel="signature" />
+
+    <!-- Allows an application to whitelist tasks during lock task mode
+         @hide <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"
+        android:protectionLevel="signature|setup" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/anim/slide_in_enter_micro.xml b/core/res/res/anim/slide_in_enter_micro.xml
index 14a5290..c70874c 100644
--- a/core/res/res/anim/slide_in_enter_micro.xml
+++ b/core/res/res/anim/slide_in_enter_micro.xml
@@ -19,7 +19,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:zAdjustment="top">
-    <translate android:fromYDelta="5%p" android:toXDelta="0"
+    <translate android:fromYDelta="5%p" android:toYDelta="0"
                android:duration="417"
                android:interpolator="@android:interpolator/launch_task_micro_ydelta" />
     <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml
index 30b5a79..ac37c4a 100644
--- a/core/res/res/layout/notification_material_action_list.xml
+++ b/core/res/res/layout/notification_material_action_list.xml
@@ -17,9 +17,7 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/actions_container"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="-16dp"
-        android:layout_marginEnd="-16dp">
+        android:layout_height="wrap_content">
     <LinearLayout
             android:id="@+id/actions"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 0bbaa24..992e88e 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -42,7 +42,7 @@
         android:singleLine="true"
         />
     <TextView
-        android:id="@+id/sub_text_divider"
+        android:id="@+id/header_text_divider"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="@style/TextAppearance.Material.Notification.Info"
@@ -51,26 +51,7 @@
         android:text="@string/notification_header_divider_symbol"
         android:visibility="gone"/>
     <TextView
-        android:id="@+id/header_sub_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
-        android:layout_marginStart="2dp"
-        android:layout_marginEnd="2dp"
-        android:visibility="gone"
-        android:singleLine="true"/>
-    <TextView
-        android:id="@+id/content_info_divider"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
-        android:layout_marginStart="2dp"
-        android:layout_marginEnd="2dp"
-        android:text="@string/notification_header_divider_symbol"
-        android:singleLine="true"
-        android:visibility="gone"/>
-    <TextView
-        android:id="@+id/header_content_info"
+        android:id="@+id/header_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="@style/TextAppearance.Material.Notification.Info"
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 d53fb5f..c54fa18 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -60,9 +60,5 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
     />
-    <include
-        layout="@layout/notification_material_action_list"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        />
+    <include layout="@layout/notification_material_action_list" />
 </LinearLayout>
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index 50aec6b..d87b9d9 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -27,8 +27,6 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_gravity="top"
-            android:paddingStart="@dimen/notification_content_margin_start"
-            android:paddingEnd="@dimen/notification_content_margin_end"
             android:layout_marginTop="@dimen/notification_content_margin_top"
             android:clipToPadding="false"
             android:orientation="vertical"
@@ -37,6 +35,8 @@
             android:id="@+id/notification_main_column"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/notification_content_margin_start"
+            android:layout_marginEnd="@dimen/notification_content_margin_end"
             android:orientation="vertical">
             <include layout="@layout/notification_template_part_line1"/>
             <include layout="@layout/notification_template_progress"/>
@@ -50,14 +50,15 @@
                 android:layout_weight="1"
                 android:layout_marginTop="13dp"
                 android:layout_marginBottom="16dp"
+                android:layout_marginStart="@dimen/notification_content_margin_start"
+                android:layout_marginEnd="@dimen/notification_content_margin_end"
                 android:scaleType="centerCrop"
                 />
+
         <ViewStub android:layout="@layout/notification_material_reply_text"
                 android:id="@+id/notification_material_reply_container"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginStart="-16dp"
-                android:layout_marginEnd="-16dp"
                 />
         <include layout="@layout/notification_material_action_list" />
     </LinearLayout>
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 fdfefe1..3638b20 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -22,38 +22,45 @@
     android:tag="bigText"
     >
     <include layout="@layout/notification_template_header" />
+
     <LinearLayout
-        android:id="@+id/notification_main_column"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="top"
-        android:paddingStart="@dimen/notification_content_margin_start"
-        android:paddingEnd="@dimen/notification_content_margin_end"
-        android:layout_marginTop="@dimen/notification_content_margin_top"
-        android:clipToPadding="false"
-        android:minHeight="@dimen/notification_min_content_height"
-        android:orientation="vertical"
-        >
-        <include layout="@layout/notification_template_part_line1" />
-        <include layout="@layout/notification_template_progress" />
-        <com.android.internal.widget.ImageFloatingTextView android:id="@+id/big_text"
             android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_marginTop="0.5dp"
-            android:paddingBottom="@dimen/notification_content_margin_bottom"
-            android:textAppearance="@style/TextAppearance.Material.Notification"
-            android:singleLine="false"
-            android:layout_weight="1"
-            android:gravity="top"
-            android:visibility="gone"
-            />
+            android:layout_height="match_parent"
+            android:layout_gravity="top"
+            android:layout_marginTop="@dimen/notification_content_margin_top"
+            android:clipToPadding="false"
+            android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/notification_main_column"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="top"
+            android:paddingStart="@dimen/notification_content_margin_start"
+            android:paddingEnd="@dimen/notification_content_margin_end"
+            android:clipToPadding="false"
+            android:minHeight="@dimen/notification_min_content_height"
+            android:orientation="vertical"
+            >
+            <include layout="@layout/notification_template_part_line1" />
+            <include layout="@layout/notification_template_progress" />
+            <com.android.internal.widget.ImageFloatingTextView android:id="@+id/big_text"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginTop="0.5dp"
+                android:paddingBottom="@dimen/notification_content_margin_bottom"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
+                android:singleLine="false"
+                android:layout_weight="1"
+                android:gravity="top"
+                android:visibility="gone"
+                />
+        </LinearLayout>
+
         <ViewStub android:layout="@layout/notification_material_reply_text"
                 android:id="@+id/notification_material_reply_container"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginStart="-16dp"
-                android:layout_marginEnd="-16dp"
-        />
+                android:layout_height="wrap_content" />
         <include layout="@layout/notification_material_action_list" />
     </LinearLayout>
     <include layout="@layout/notification_template_right_icon" />
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index 86902db..ce9acda 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -23,87 +23,99 @@
     >
     <include layout="@layout/notification_template_header" />
     <LinearLayout
-        android:id="@+id/notification_main_column"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="top"
-        android:paddingStart="@dimen/notification_content_margin_start"
-        android:paddingEnd="@dimen/notification_content_margin_end"
-        android:layout_marginTop="@dimen/notification_content_margin_top"
-        android:minHeight="@dimen/notification_min_content_height"
-        android:clipToPadding="false"
-        android:orientation="vertical"
-        >
-        <include layout="@layout/notification_template_part_line1"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-        <include layout="@layout/notification_template_progress"
+            android:layout_height="match_parent"
+            android:layout_gravity="top"
+            android:layout_marginTop="@dimen/notification_content_margin_top"
+            android:clipToPadding="false"
+            android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/notification_main_column"
             android:layout_width="match_parent"
-            android:layout_height="15dp"
-            android:layout_marginTop="4dp"/>
-        <TextView android:id="@+id/inbox_text0"
-            android:textAppearance="@style/TextAppearance.Material.Notification"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text1"
-            android:textAppearance="@style/TextAppearance.Material.Notification"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text2"
-            android:textAppearance="@style/TextAppearance.Material.Notification"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text3"
-            android:textAppearance="@style/TextAppearance.Material.Notification"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text4"
-            android:textAppearance="@style/TextAppearance.Material.Notification"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text5"
-            android:textAppearance="@style/TextAppearance.Material.Notification"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
-        <TextView android:id="@+id/inbox_text6"
-            android:textAppearance="@style/TextAppearance.Material.Notification"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:visibility="gone"
-            android:layout_weight="1"
-            />
+            android:layout_height="wrap_content"
+            android:layout_gravity="top"
+            android:paddingStart="@dimen/notification_content_margin_start"
+            android:paddingEnd="@dimen/notification_content_margin_end"
+            android:minHeight="@dimen/notification_min_content_height"
+            android:clipToPadding="false"
+            android:orientation="vertical"
+            >
+            <include layout="@layout/notification_template_part_line1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+            <include layout="@layout/notification_template_progress"
+                android:layout_width="match_parent"
+                android:layout_height="15dp"
+                android:layout_marginTop="4dp"/>
+            <TextView android:id="@+id/inbox_text0"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text1"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text2"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text3"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text4"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text5"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text6"
+                android:textAppearance="@style/TextAppearance.Material.Notification"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+        </LinearLayout>
+        <ViewStub android:layout="@layout/notification_material_reply_text"
+                android:id="@+id/notification_material_reply_container"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
         <include layout="@layout/notification_material_action_list" />
     </LinearLayout>
     <include layout="@layout/notification_template_right_icon" />
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index 4b8640c..fe43e1c 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -30,33 +30,37 @@
         android:layout_height="wrap_content"
         android:layout_alwaysShow="true"
         android:elevation="8dp"
-        android:background="@color/white" >
-        <TextView android:id="@+id/profile_button"
-                  android:layout_width="wrap_content"
-                  android:layout_height="48dp"
-                  android:layout_marginEnd="8dp"
-                  android:paddingStart="8dp"
-                  android:paddingEnd="8dp"
-                  android:visibility="gone"
-                  style="?attr/borderlessButtonStyle"
-                  android:textAppearance="?attr/textAppearanceButton"
-                  android:textColor="@color/material_deep_teal_500"
-                  android:gravity="center_vertical"
-                  android:layout_alignParentTop="true"
-                  android:layout_alignParentRight="true"
-                  android:singleLine="true"/>
-        <TextView android:id="@+id/title"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:minHeight="56dp"
-                  android:textAppearance="?attr/textAppearanceMedium"
-                  android:gravity="start|center_vertical"
-                  android:paddingStart="?attr/dialogPreferredPadding"
-                  android:paddingEnd="?attr/dialogPreferredPadding"
-                  android:paddingTop="8dp"
-                  android:layout_below="@id/profile_button"
-                  android:layout_alignParentLeft="true"
-                  android:paddingBottom="8dp" />
+        android:background="@color/white">
+
+        <TextView
+            android:id="@+id/profile_button"
+            android:layout_width="wrap_content"
+            android:layout_height="48dp"
+            android:layout_marginEnd="8dp"
+            android:paddingStart="8dp"
+            android:paddingEnd="8dp"
+            android:visibility="gone"
+            style="?attr/borderlessButtonStyle"
+            android:textAppearance="?attr/textAppearanceButton"
+            android:textColor="@color/material_deep_teal_500"
+            android:gravity="center_vertical"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentRight="true"
+            android:singleLine="true" />
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:minHeight="56dp"
+            android:textAppearance="?attr/textAppearanceMedium"
+            android:gravity="start|center_vertical"
+            android:paddingStart="?attr/dialogPreferredPadding"
+            android:paddingEnd="?attr/dialogPreferredPadding"
+            android:paddingTop="8dp"
+            android:layout_below="@id/profile_button"
+            android:layout_alignParentLeft="true"
+            android:paddingBottom="8dp" />
     </RelativeLayout>
 
     <ListView
@@ -68,21 +72,23 @@
         android:background="@color/white"
         android:elevation="8dp"
         android:nestedScrollingEnabled="true"
+        android:scrollIndicators="top|bottom"
         android:divider="@null" />
 
-    <TextView android:id="@+id/empty"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              android:layout_alwaysShow="true"
-              android:text="@string/noApplications"
-              android:padding="32dp"
-              android:gravity="center"
-              android:visibility="gone" />
+    <TextView
+        android:id="@+id/empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alwaysShow="true"
+        android:text="@string/noApplications"
+        android:padding="32dp"
+        android:gravity="center"
+        android:visibility="gone" />
 
     <LinearLayout
         android:id="@+id/button_bar"
         android:visibility="gone"
-        style="?android:attr/buttonBarStyle"
+        style="?attr/buttonBarStyle"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_ignoreOffset="true"
@@ -97,26 +103,30 @@
         android:paddingStart="12dp"
         android:paddingEnd="12dp"
         android:elevation="8dp">
-        <Button android:id="@+id/button_once"
-                android:layout_width="wrap_content"
-                android:layout_gravity="start"
-                android:maxLines="2"
-                style="?android:attr/buttonBarNegativeButtonStyle"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                android:layout_height="wrap_content"
-                android:enabled="false"
-                android:text="@string/activity_resolver_use_once"
-                android:onClick="onButtonClick" />
-        <Button android:id="@+id/button_always"
-                android:layout_width="wrap_content"
-                android:layout_gravity="end"
-                android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                style="?android:attr/buttonBarPositiveButtonStyle"
-                android:layout_height="wrap_content"
-                android:enabled="false"
-                android:text="@string/activity_resolver_use_always"
-                android:onClick="onButtonClick" />
+
+        <Button
+            android:id="@+id/button_once"
+            android:layout_width="wrap_content"
+            android:layout_gravity="start"
+            android:maxLines="2"
+            style="?attr/buttonBarNegativeButtonStyle"
+            android:minHeight="@dimen/alert_dialog_button_bar_height"
+            android:layout_height="wrap_content"
+            android:enabled="false"
+            android:text="@string/activity_resolver_use_once"
+            android:onClick="onButtonClick" />
+
+        <Button
+            android:id="@+id/button_always"
+            android:layout_width="wrap_content"
+            android:layout_gravity="end"
+            android:maxLines="2"
+            android:minHeight="@dimen/alert_dialog_button_bar_height"
+            style="?attr/buttonBarPositiveButtonStyle"
+            android:layout_height="wrap_content"
+            android:enabled="false"
+            android:text="@string/activity_resolver_use_always"
+            android:onClick="onButtonClick" />
     </LinearLayout>
 
 </com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 31361e5..ed7ef5e 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -22,8 +22,7 @@
     android:layout_height="match_parent"
     android:maxWidth="@dimen/resolver_max_width"
     android:maxCollapsedHeight="144dp"
-    android:id="@id/contentPanel"
-    >
+    android:id="@id/contentPanel">
 
     <LinearLayout
         android:layout_width="match_parent"
@@ -31,66 +30,75 @@
         android:layout_alwaysShow="true"
         android:orientation="vertical"
         android:background="@color/white"
-        android:elevation="8dp" >
+        android:elevation="8dp">
 
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="64dp"
-            android:orientation="horizontal" >
+            android:orientation="horizontal">
 
-            <ImageView android:id="@+id/icon"
-                       android:layout_width="24dp"
-                       android:layout_height="24dp"
-                       android:layout_gravity="start|top"
-                       android:layout_marginStart="16dp"
-                       android:layout_marginEnd="16dp"
-                       android:layout_marginTop="20dp"
-                       android:scaleType="fitCenter" />
-            <TextView android:id="@+id/title"
-                      android:layout_width="0dp"
-                      android:layout_weight="1"
-                      android:layout_height="?android:attr/listPreferredItemHeight"
-                      android:layout_marginStart="16dp"
-                      android:textAppearance="?android:attr/textAppearanceMedium"
-                      android:gravity="start|center_vertical"
-                      android:paddingEnd="16dp" />
-            <LinearLayout android:id="@+id/profile_button"
-                          android:layout_width="wrap_content"
-                          android:layout_height="48dp"
-                          android:layout_marginTop="4dp"
-                          android:layout_marginEnd="4dp"
-                          android:paddingStart="8dp"
-                          android:paddingEnd="8dp"
-                          android:paddingTop="4dp"
-                          android:paddingBottom="4dp"
-                          android:focusable="true"
-                          android:visibility="gone"
-                          style="?attr/borderlessButtonStyle">
-                <ImageView android:id="@+id/icon"
-                           android:layout_width="24dp"
-                           android:layout_height="24dp"
-                           android:layout_gravity="start|center_vertical"
-                           android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
-                           android:layout_marginTop="12dp"
-                           android:layout_marginBottom="12dp"
-                           android:scaleType="fitCenter" />
-                <TextView android:id="@id/text1"
-                          android:layout_width="wrap_content"
-                          android:layout_height="wrap_content"
-                          android:layout_gravity="start|center_vertical"
-                          android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
-                          android:textAppearance="?attr/textAppearanceButton"
-                          android:textColor="?attr/textColorPrimary"
-                          android:minLines="1"
-                          android:maxLines="1"
-                          android:ellipsize="marquee" />
+            <ImageView
+                android:id="@+id/icon"
+                android:layout_width="24dp"
+                android:layout_height="24dp"
+                android:layout_gravity="start|top"
+                android:layout_marginStart="16dp"
+                android:layout_marginEnd="16dp"
+                android:layout_marginTop="20dp"
+                android:scaleType="fitCenter" />
+
+            <TextView
+                android:id="@+id/title"
+                android:layout_width="0dp"
+                android:layout_weight="1"
+                android:layout_height="?attr/listPreferredItemHeight"
+                android:layout_marginStart="16dp"
+                android:textAppearance="?attr/textAppearanceMedium"
+                android:gravity="start|center_vertical"
+                android:paddingEnd="16dp" />
+
+            <LinearLayout
+                android:id="@+id/profile_button"
+                android:layout_width="wrap_content"
+                android:layout_height="48dp"
+                android:layout_marginTop="4dp"
+                android:layout_marginEnd="4dp"
+                android:paddingStart="8dp"
+                android:paddingEnd="8dp"
+                android:paddingTop="4dp"
+                android:paddingBottom="4dp"
+                android:focusable="true"
+                android:visibility="gone"
+                style="?attr/borderlessButtonStyle">
+
+                <ImageView
+                    android:id="@+id/icon"
+                    android:layout_width="24dp"
+                    android:layout_height="24dp"
+                    android:layout_gravity="start|center_vertical"
+                    android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
+                    android:layout_marginTop="12dp"
+                    android:layout_marginBottom="12dp"
+                    android:scaleType="fitCenter" />
+
+                <TextView
+                    android:id="@id/text1"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="start|center_vertical"
+                    android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
+                    android:textAppearance="?attr/textAppearanceButton"
+                    android:textColor="?attr/textColorPrimary"
+                    android:minLines="1"
+                    android:maxLines="1"
+                    android:ellipsize="marquee" />
             </LinearLayout>
         </LinearLayout>
 
         <LinearLayout
             android:id="@+id/button_bar"
             android:visibility="gone"
-            style="?android:attr/buttonBarStyle"
+            style="?attr/buttonBarStyle"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_alwaysShow="true"
@@ -104,30 +112,36 @@
             android:paddingEnd="12dp"
             android:background="@color/white"
             android:elevation="8dp">
-            <Button android:id="@+id/button_once"
-                    android:layout_width="wrap_content"
-                    android:layout_gravity="start"
-                    android:maxLines="2"
-                    style="?android:attr/buttonBarNegativeButtonStyle"
-                    android:minHeight="@dimen/alert_dialog_button_bar_height"
-                    android:layout_height="wrap_content"
-                    android:enabled="false"
-                    android:text="@string/activity_resolver_use_once"
-                    android:onClick="onButtonClick" />
-            <Button android:id="@+id/button_always"
-                    android:layout_width="wrap_content"
-                    android:layout_gravity="end"
-                    android:maxLines="2"
-                    android:minHeight="@dimen/alert_dialog_button_bar_height"
-                    style="?android:attr/buttonBarPositiveButtonStyle"
-                    android:layout_height="wrap_content"
-                    android:enabled="false"
-                    android:text="@string/activity_resolver_use_always"
-                    android:onClick="onButtonClick" />
+
+            <Button
+                android:id="@+id/button_once"
+                android:layout_width="wrap_content"
+                android:layout_gravity="start"
+                android:maxLines="2"
+                style="?attr/buttonBarNegativeButtonStyle"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                android:layout_height="wrap_content"
+                android:enabled="false"
+                android:text="@string/activity_resolver_use_once"
+                android:onClick="onButtonClick" />
+
+            <Button
+                android:id="@+id/button_always"
+                android:layout_width="wrap_content"
+                android:layout_gravity="end"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height"
+                style="?attr/buttonBarPositiveButtonStyle"
+                android:layout_height="wrap_content"
+                android:enabled="false"
+                android:text="@string/activity_resolver_use_always"
+                android:onClick="onButtonClick" />
         </LinearLayout>
-        <View android:layout_width="match_parent"
-              android:layout_height="1dp"
-              android:background="?android:attr/dividerVertical" />
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="?attr/dividerVertical" />
     </LinearLayout>
 
     <ListView
@@ -140,6 +154,6 @@
         android:elevation="8dp"
         android:nestedScrollingEnabled="true"
         android:divider="@null"
-        />
+        android:scrollIndicators="top|bottom" />
 
 </com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 7ca52a3..2a16a1e 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Inhoud word versteek volgens beleid"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Skakel oor na persoonlik"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Skakel oor na werk"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakte"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"in te gaan by jou kontakte"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Ligging"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Ander sleutelborde"</string>
     <string name="show_ime" msgid="2506087537466597099">"Hou dit op die skerm terwyl fisieke sleutelbord aktief is"</string>
     <string name="hardware" msgid="194658061510127999">"Wys virtuele sleutelbord"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Stel fisieke sleutelbord op"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om taal en uitleg te kies"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidate"</u></string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 200ec30..0668c35 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ይዘቶች በመመሪያ ተደብቀዋል"</string>
     <string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"ወደ የግል ቀይር"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"ወደ ሥራ ቀይር"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"ዕውቂያዎች"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"የእርስዎ እውቂያዎች ላይ ይድረሱባቸው"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"መገኛ አካባቢ"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"ሌሎች ቁልፍ ሰሌዳዎች"</string>
     <string name="show_ime" msgid="2506087537466597099">"አካላዊ የቁልፍ ሰሌዳ ገቢር ሆኖ ሳለ በማያ ገጽ ላይ አቆየው"</string>
     <string name="hardware" msgid="194658061510127999">"ምናባዊ የቁልፍ ሰሌዳን አሳይ"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"አካላዊ ቁልፍ ሰሌዳን ያዋቅሩ"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ቋንቋ እና አቀማመጥን ለመምረጥ መታ ያድርጉ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ዕጩዎች"</u></string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d812787..6a7c76c 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -241,10 +241,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"تم إخفاء المحتويات بواسطة السياسة"</string>
     <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏نظام Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"التبديل إلى الشخصي"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"التبديل إلى العمل"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"جهات الاتصال"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"الوصول إلى جهات اتصالك"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"الموقع"</string>
@@ -1095,13 +1093,10 @@
     <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="5673193194563164021">"لوحات المفاتيح الأخرى"</string>
     <string name="show_ime" msgid="2506087537466597099">"استمرار عرضها على الشاشة أثناء نشاط لوحة المفاتيح الفعلية"</string>
     <string name="hardware" msgid="194658061510127999">"إظهار لوحة المفاتيح الظاهرية"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"تهيئة لوحة المفاتيح الفعلية"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"انقر لاختيار لغة وتنسيق"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"العناصر المرشحة"</u></string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 5479958..e76ce87 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistemi"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Şəxsi profilə keçirin"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"İş profilinə keçirin"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktlar"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"kontaktlarınıza daxil olun"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Yer"</string>
@@ -1063,13 +1061,10 @@
     <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PAYLAŞIN"</string>
     <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RƏDD EDİN"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Klaviaturanı dəyişin"</string>
-    <string name="configure_input_methods" msgid="5673193194563164021">"Digər klaviaturalar"</string>
     <string name="show_ime" msgid="2506087537466597099">"Fiziki klaviatura aktiv olduğu halda ekranda saxlayın"</string>
     <string name="hardware" msgid="194658061510127999">"Virtual klaviaturanı göstərin"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fiziki klaviaturanı konfiqurasiya edin"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dil və tərtibatı seçmək üçün tıklayın"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCÇDEƏFGĞHXIİJKQLMNOÖPRSŞTUÜVYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCÇDEƏFGĞHİIJKLMNOÖPQRSŞTUÜVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"namizədlər"</u></string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 9f9b5b8..9231e9a 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -235,10 +235,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj je sakriven smernicama"</string>
     <string name="safeMode" msgid="2788228061547930246">"Bezbedni režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Pređi na Lični profil"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Pređi na profil za Work"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakti"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupi kontaktima"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string>
@@ -1071,13 +1069,10 @@
     <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="5673193194563164021">"Druge tastature"</string>
     <string name="show_ime" msgid="2506087537466597099">"Zadrži ga na ekranu dok je fizička tastatura aktivna"</string>
     <string name="hardware" msgid="194658061510127999">"Prikaži virtuelnu tastaturu"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurišite fizičku tastaturu"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste izabrali jezik i raspored"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index 6848fda..8a23529 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -237,10 +237,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Змесціва, схаванае ў адпаведнасці з палітыкай"</string>
     <string name="safeMode" msgid="2788228061547930246">"Бяспечны рэжым"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Сістэма Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Пераключыцца на асабісты"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Пераключыцца на працоўны"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Кантакты"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"атрымліваць доступ да вашых кантактаў"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Месцазнаходжанне"</string>
@@ -1063,8 +1061,8 @@
     <string name="no_permissions" msgid="7283357728219338112">"Дазволу не патрабуецца"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"за гэта можа спаганяцца плата"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ОК"</string>
-    <string name="usb_charging_notification_title" msgid="6895185153353640787">"Зарадка гэтай прылады па USB"</string>
-    <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Падача сілкавання падключанай прыладзе па USB"</string>
+    <string name="usb_charging_notification_title" msgid="6895185153353640787">"Па USB зараджаецца гэта прыладу"</string>
+    <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Па USB падачецца сілкаванне падключанай прыладзе"</string>
     <string name="usb_mtp_notification_title" msgid="8396264943589760855">"USB для перадачы файлаў"</string>
     <string name="usb_ptp_notification_title" msgid="1347328437083192112">"USB для перадачы фота"</string>
     <string name="usb_midi_notification_title" msgid="4850904915889144654">"USB для MIDI"</string>
@@ -1079,13 +1077,10 @@
     <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="5673193194563164021">"Іншыя праграмныя клавіятуры"</string>
     <string name="show_ime" msgid="2506087537466597099">"Захоўваць яе на экране ў той час, калі фізічная клавіятура актыўная"</string>
     <string name="hardware" msgid="194658061510127999">"Паказаць віртуальную клавіятуру"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Наладжванне фізічнай клавіятуры"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Дакраніцеся, каб выбраць мову і раскладку"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШ\'ЫЬЭЮЯ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"кандыдат."</u></string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 4f8f80c..76c7002 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Съдържанието е скрито чрез правило"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Превключване към личния потребителски профил"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Превключване към служебния пoтребителски профил"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакти"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"има достъп до контактите ви"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Местоположение"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Други клавиатури"</string>
     <string name="show_ime" msgid="2506087537466597099">"Показване на екрана, докато физическата клавиатура е активна"</string>
     <string name="hardware" msgid="194658061510127999">"Показване на вирт. клавиатура"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Конфигуриране на физическата клавиатура"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Докоснете, за да изберете език и подредба"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 13284cf..620e532 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"নীতির কারণে সামগ্রী লুকানো আছে"</string>
     <string name="safeMode" msgid="2788228061547930246">"নিরাপদ মোড"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android সিস্টেম"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"ব্যক্তিগততে পাল্টান"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"কর্মস্থানে পাল্টান"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"পরিচিতি"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"আপনার পরিচিতিগুলিতে অ্যাক্সেস করুন"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"অবস্থান"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"অন্যান্য কীবোর্ড"</string>
     <string name="show_ime" msgid="2506087537466597099">"ফিজিক্যাল কীবোর্ড সক্রিয় থাকার সময় এটিকে স্ক্রীনে রাখুন"</string>
     <string name="hardware" msgid="194658061510127999">"ভার্চুয়াল কীবোর্ড দেখান"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ফিজিক্যাল কীবোর্ড কনফিগার করুন"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ভাষা এবং লেআউট নির্বাচন করুন আলতো চাপ দিন"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"প্রার্থীরা"</u></string>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index bbc72d5..82639af 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -235,10 +235,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Prebacite se na lični"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Prebacite se na radni"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakti"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupa vašim kontaktima"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string>
@@ -1071,13 +1069,10 @@
     <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="5673193194563164021">"Ostale tastature"</string>
     <string name="show_ime" msgid="2506087537466597099">"Prikaži na ekranu dok je fizička tastatura aktivna"</string>
     <string name="hardware" msgid="194658061510127999">"Prikaži virtualnu tastaturu"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguriraj fizičku tastaturu"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite za odabir jezika i rasporeda"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 07ba682..6fcadfa 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Canvia al perfil personal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Canvia al perfil professional"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactes"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"accedir als contactes"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Ubicació"</string>
@@ -1048,7 +1046,7 @@
     <string name="perm_costs_money" msgid="4902470324142151116">"pot ser que comporti càrrecs"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"D\'acord"</string>
     <string name="usb_charging_notification_title" msgid="6895185153353640787">"L\'USB està carregant el dispositiu"</string>
-    <string name="usb_supplying_notification_title" msgid="5310642257296510271">"L\'USB subministra energia al dispositiu inserit"</string>
+    <string name="usb_supplying_notification_title" msgid="5310642257296510271">"L\'USB subministra energia al dispositiu connectat"</string>
     <string name="usb_mtp_notification_title" msgid="8396264943589760855">"USB per transferir fitxers"</string>
     <string name="usb_ptp_notification_title" msgid="1347328437083192112">"USB per transferir fotos"</string>
     <string name="usb_midi_notification_title" msgid="4850904915889144654">"USB per a MIDI"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Altres teclats"</string>
     <string name="show_ime" msgid="2506087537466597099">"El deixa a la pantalla mentre el teclat físic està actiu"</string>
     <string name="hardware" msgid="194658061510127999">"Mostra el teclat virtual"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura el teclat físic"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca per seleccionar l\'idioma i el disseny"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0a9aa2b..127d38b 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -237,10 +237,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Obsah skrytý zásadami"</string>
     <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Přepnout na osobní profil"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Přepnout na pracovní profil"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakty"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"přístup ke kontaktům"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Poloha"</string>
@@ -1079,13 +1077,10 @@
     <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="5673193194563164021">"Další klávesnice"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ponechat na obrazovce, když je aktivní fyzická klávesnice"</string>
     <string name="hardware" msgid="194658061510127999">"Zobrazit virtuální klávesnici"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurace fyzické klávesnice"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozvržení"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index dd2d223..407f1f8 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Indholdet er skjult af politikken"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Skift til Tilpasset"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Skift til arbejde"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktpersoner"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"have adgang til dine kontaktpersoner"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Placering"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Andre tastaturer"</string>
     <string name="show_ime" msgid="2506087537466597099">"Behold den på skærmen, mens det fysiske tastatur er aktivt"</string>
     <string name="hardware" msgid="194658061510127999">"Vis virtuelt tastatur"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurer fysisk tastatur"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryk for at vælge sprog og layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b32bea6..e539a28 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Inhalte aufgrund der Richtlinien ausgeblendet"</string>
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Zu \"Privat\" wechseln"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Zu \"Arbeit\" wechseln"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakte"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"auf Kontakte zuzugreifen"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Standort"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Weitere Tastaturen"</string>
     <string name="show_ime" msgid="2506087537466597099">"Auf dem Display einblenden, wenn die physische Tastatur aktiv ist"</string>
     <string name="hardware" msgid="194658061510127999">"Virtuelle Tastatur einblenden"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Physische Tastatur konfigurieren"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Zum Auswählen von Sprache und Layout tippen"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"Kandidaten"</u></string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 71351a3..1e891d0 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Το περιεχόμενο είναι κρυφό βάσει πολιτικής"</string>
     <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Μετάβαση σε προσωπικό προφίλ"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Μετάβαση σε προφίλ εργασίας"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Επαφές"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"πρόσβαση στις επαφές σας"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Τοποθεσία"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Άλλα πληκτρολόγια"</string>
     <string name="show_ime" msgid="2506087537466597099">"Να παραμένει στην οθόνη όταν είναι ενεργό το φυσικό πληκτρολόγιο"</string>
     <string name="hardware" msgid="194658061510127999">"Εμφάνιση εικονικού πληκτρολ."</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Διαμόρφωση φυσικού πληκτρολογίου"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Πατήστε για να επιλέξετε γλώσσα και διάταξη"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"υποψήφιοι"</u></string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index c222397..b94222c 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Location"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Other keyboards"</string>
     <string name="show_ime" msgid="2506087537466597099">"Keep it on screen while physical keyboard is active"</string>
     <string name="hardware" msgid="194658061510127999">"Show virtual keyboard"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configure physical keyboard"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidates"</u></string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index c222397..b94222c 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Location"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Other keyboards"</string>
     <string name="show_ime" msgid="2506087537466597099">"Keep it on screen while physical keyboard is active"</string>
     <string name="hardware" msgid="194658061510127999">"Show virtual keyboard"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configure physical keyboard"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidates"</u></string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index c222397..b94222c 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Switch to Personal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Switch to Work"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"access your contacts"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Location"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Other keyboards"</string>
     <string name="show_ime" msgid="2506087537466597099">"Keep it on screen while physical keyboard is active"</string>
     <string name="hardware" msgid="194658061510127999">"Show virtual keyboard"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configure physical keyboard"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidates"</u></string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index afd5f6c..0bfb9e0 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Cambiar al perfil personal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Cambiar al perfil de trabajo"</string>
     <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>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Otros teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Mantener en la pantalla cuando el teclado físico está activo"</string>
     <string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura el teclado físico"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Presiona para seleccionar el idioma y el diseño"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 3d5682c..99202ab 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenidos ocultos por política"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Cambiar a perfil personal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Cambiar a perfil de trabajo"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder a tus contactos"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Ubicación"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Otros teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Debe seguir en pantalla mientras el teclado físico esté activo"</string>
     <string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura el teclado físico"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar el idioma y el diseño"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 7b2e108..b1cc971 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sisu on eeskirjadega peidetud"</string>
     <string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Lülita isiklikule profiilile"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Lülita tööprofiilile"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktid"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"juurdepääs kontaktidele"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Asukoht"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Muud klaviatuurid"</string>
     <string name="show_ime" msgid="2506087537466597099">"Hoia seda ekraanil, kui füüsiline klaviatuur on aktiivne"</string>
     <string name="hardware" msgid="194658061510127999">"Virtuaalse klaviatuuri kuvam."</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Füüsilise klaviatuuri seadistamine"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Puudutage keele ja paigutuse valimiseks"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaadid"</u></string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 5bcaed1..ea666d9 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Gidalerro batzuk ezkutatu dira, gidalerroei jarraiki"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modu segurua"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistema"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Aldatu profil pertsonalera"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Aldatu laneko profilera"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktuak"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"kontaktuak atzitzeko"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Kokapena"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Beste teklatu batzuk"</string>
     <string name="show_ime" msgid="2506087537466597099">"Erakutsi pantailan teklatu fisikoa aktibo dagoen bitartean"</string>
     <string name="hardware" msgid="194658061510127999">"Erakutsi teklatu birtuala"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguratu teklatu fisikoa"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Hizkuntza eta diseinua hautatzeko, sakatu hau"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"hautagaiak"</u></string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 7688af4..df9d78f 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"محتوا بر اساس خط‌مشی پنهان شده است"</string>
     <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏سیستم Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"رفتن به نمایه شخصی"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"رفتن به نمایه کاری"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"مخاطبین"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"دسترسی به مخاطبین شما"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"مکان"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"صفحه‌کلیدهای دیگر"</string>
     <string name="show_ime" msgid="2506087537466597099">"وقتی صفحه‌کلید فیزیکی فعال است این ویرایشگر را روی صفحه نگه‌می‌دارد"</string>
     <string name="hardware" msgid="194658061510127999">"نمایش صفحه‌کلید مجازی"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"پیکربندی صفحه‌کلید فیزیکی"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"برای انتخاب زبان و چیدمان ضربه بزنید"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"داوطلبین"</u></string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 9105842..c869961 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Siirry henkilökohtaiseen profiiliin"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Siirry työprofiiliin"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktit"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"käyttää yhteystietoja"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Sijainti"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Muut näppäimistöt"</string>
     <string name="show_ime" msgid="2506087537466597099">"Pidä näytöllä, kun fyysinen näppäimistö on aktiivinen."</string>
     <string name="hardware" msgid="194658061510127999">"Näytä virtuaalinen näppäimistö"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Määritä fyysinen näppäimistö"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Valitse kieli ja asettelu koskettamalla."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaatit"</u></string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 222501f..efc8af3 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Passer au profil personnel"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Passer au profil professionnel"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"accéder à vos contacts"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Localisation"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Autres claviers"</string>
     <string name="show_ime" msgid="2506087537466597099">"Afficher lorsque le clavier physique est activé"</string>
     <string name="hardware" msgid="194658061510127999">"Afficher le clavier virtuel"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurer le clavier physique"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Touchez pour sélectionner la langue et la configuration du clavier"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 1b8e03c..4e83fa9 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Passer au profil personnel"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Passer au profil professionnel"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacts"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"accéder à vos contacts"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Position"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Autres claviers"</string>
     <string name="show_ime" msgid="2506087537466597099">"Afficher lorsque le clavier physique est activé"</string>
     <string name="hardware" msgid="194658061510127999">"Afficher le clavier virtuel"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurer le clavier physique"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Appuyer pour sélectionner la langue et la disposition"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index ae5cc61..2fa6087 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Cambiar ao perfil persoal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Cambiar ao perfil de traballo"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceder aos teus contactos"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Localización"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Outros teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Manteno na pantalla mentres o teclado físico estea activo"</string>
     <string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura o teclado físico"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar o idioma e o deseño"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 0487612..0b9f4ad 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"નીતિ દ્વારા સામગ્રી છુપાવાઈ"</string>
     <string name="safeMode" msgid="2788228061547930246">"સુરક્ષિત મોડ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android સિસ્ટમ"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"વ્યક્તિગત પર સ્વિચ કરો"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"કાર્ય પર સ્વિચ કરો"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"સંપર્કો"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"તમારા સંપર્કોને ઍક્સેસ કરો"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"સ્થાન"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"અન્ય કીબોર્ડ્સ"</string>
     <string name="show_ime" msgid="2506087537466597099">"જ્યારે ભૌતિક કીબોર્ડ સક્રિય હોય ત્યારે તેને સ્ક્રીન પર રાખો"</string>
     <string name="hardware" msgid="194658061510127999">"વર્ચ્યુઅલ કીબોર્ડ બતાવો"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ભૌતિક કીબોર્ડ ગોઠવો"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ભાષા અને લેઆઉટ પસંદ કરવા માટે ટૅપ કરો"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ઉમેદવારો"</u></string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f007f89..474e81e 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"सामग्री पॉलिसी के द्वारा छिपी हुई है"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफ़ाइल में स्विच करें"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"कार्य प्रोफ़ाइल में स्विच करें"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"संपर्क"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"अपने संपर्कों को ऐक्सेस करें"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"स्थान"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"अन्य कीबोर्ड"</string>
     <string name="show_ime" msgid="2506087537466597099">"भौतिक कीबोर्ड के सक्रिय होने के दौरान इसे स्‍क्रीन पर बनाए रखें"</string>
     <string name="hardware" msgid="194658061510127999">"वर्चुअल कीबोर्ड दिखाएं"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"भौतिक कीबोर्ड कॉन्फ़िगर करें"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा और लेआउट चुनने के लिए टैप करें"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"उम्‍मीदवार"</u></string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index af8de3f..837aa56 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -235,10 +235,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Prijeđite na osobni"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Prijeđite na radni"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakti"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupati vašim kontaktima"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string>
@@ -1071,13 +1069,10 @@
     <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="5673193194563164021">"Ostale tipkovnice"</string>
     <string name="show_ime" msgid="2506087537466597099">"Zadržava se na zaslonu dok je fizička tipkovnica aktivna"</string>
     <string name="hardware" msgid="194658061510127999">"Prikaži virtualnu tipkovnicu"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurirajte fizičku tipkovnicu"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste odabrali jezik i raspored"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 6ae5120..0c4705d 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Átváltás személyes profilra"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Átváltás munkaprofilra"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Névjegyek"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"hozzáférés a névjegyekhez"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Helyadatok"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Más billentyűzetek"</string>
     <string name="show_ime" msgid="2506087537466597099">"Maradjon a képernyőn, amíg a billentyűzet aktív"</string>
     <string name="hardware" msgid="194658061510127999">"Virtuális billentyűzet"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Állítsa be a fizikai billentyűzetet"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Koppintson a nyelv és a billentyűzetkiosztás kiválasztásához"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"jelöltek"</u></string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 1a4a2eb..4be90da 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Բովանդակությունը թաքցվել է ըստ քաղաքականության"</string>
     <string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Անցնել անհատական պրոֆիլին"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Անցնել աշխատանքային պրոֆիլին"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Կոնտակտներ"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"կոնտակտների հասանելիություն"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Տեղադրություն"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Այլ ստեղնաշարեր"</string>
     <string name="show_ime" msgid="2506087537466597099">"Պահել էկրանին մինչդեռ ֆիզիկական ստեղնաշարն ակտիվ է"</string>
     <string name="hardware" msgid="194658061510127999">"Ցույց տալ վիրտուալ ստեղնաշարը"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Կազմաձևեք ֆիզիկական ստեղնաշարը"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Հպեք՝ լեզուն և դասավորությունն ընտրելու համար"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"թեկնածուները"</u></string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 480a845..7218617 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Konten disembunyikan menurut kebijakan"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Beralih ke Pribadi"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Beralih ke Kantor"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontak"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"mengakses kontak"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Lokasi"</string>
@@ -1047,8 +1045,8 @@
     <string name="no_permissions" msgid="7283357728219338112">"Tidak perlu izin"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"ini mungkin tidak gratis"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Oke"</string>
-    <string name="usb_charging_notification_title" msgid="6895185153353640787">"Mengisi daya perangkat ini melalui USB"</string>
-    <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Menyuplai daya melalui USB ke perangkat yang terpasang"</string>
+    <string name="usb_charging_notification_title" msgid="6895185153353640787">"Isi daya perangkat ini melalui USB"</string>
+    <string name="usb_supplying_notification_title" msgid="5310642257296510271">"Suplai daya melalui USB ke perangkat yang terpasang"</string>
     <string name="usb_mtp_notification_title" msgid="8396264943589760855">"USB untuk transfer file"</string>
     <string name="usb_ptp_notification_title" msgid="1347328437083192112">"USB untuk transfer foto"</string>
     <string name="usb_midi_notification_title" msgid="4850904915889144654">"USB untuk MIDI"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Keyboard lainnya"</string>
     <string name="show_ime" msgid="2506087537466597099">"Pertahankan di layar jika keyboard fisik masih aktif"</string>
     <string name="hardware" msgid="194658061510127999">"Tampilkan keyboard virtual"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Mengonfigurasi keyboard fisik"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketuk untuk memilih bahasa dan tata letak"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"calon"</u></string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index ce00b09..cebc4cc 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Efni falið með reglu"</string>
     <string name="safeMode" msgid="2788228061547930246">"Örugg stilling"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android kerfið"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Skipta yfir í persónulegt snið"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Skipta yfir í vinnusnið"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Tengiliðir"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"fá aðgang að tengiliðunum þínum"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Staðsetning"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Önnur lyklaborð"</string>
     <string name="show_ime" msgid="2506087537466597099">"Haltu því á skjánum meðan vélbúnaðarlyklaborðið er virkt"</string>
     <string name="hardware" msgid="194658061510127999">"Sýna sýndarlyklaborð"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Stilla vélbúnaðarlyklaborð"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ýttu til að velja tungumál og útlit"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"möguleikar"</u></string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 19fcf55..2a73990 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenuti nascosti in base alle norme"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Passa al profilo personale"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Passa al profilo di lavoro"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatti"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"accedere ai contatti"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Posizione"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Altre tastiere"</string>
     <string name="show_ime" msgid="2506087537466597099">"Tieni sullo schermo quando è attiva la tastiera fisica"</string>
     <string name="hardware" msgid="194658061510127999">"Mostra tastiera virtuale"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura la tastiera fisica"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tocca per selezionare la lingua e il layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidati"</u></string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 41acce9..80435b6 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -237,10 +237,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"התוכן מוסתר על ידי המדיניות"</string>
     <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏מערכת Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"עבור ל\'אישי\'"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"עבור ל\'עבודה\'"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"אנשי קשר"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"גישה אל אנשי הקשר"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"מיקום"</string>
@@ -1079,13 +1077,10 @@
     <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="5673193194563164021">"מקלדות אחרות"</string>
     <string name="show_ime" msgid="2506087537466597099">"השאר אותו במסך בזמן שהמקלדת הפיזית פעילה"</string>
     <string name="hardware" msgid="194658061510127999">"הצג מקלדת וירטואלית"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"הגדרת מקלדת פיזית"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"הקש כדי לבחור שפה ופריסה"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"מועמדים"</u></string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index dff30b4..394775f 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ポリシーによって非表示になっているコンテンツ"</string>
     <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"個人用に切り替える"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"仕事用に切り替える"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"連絡先"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"連絡先へのアクセス"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"位置情報"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"その他のキーボード"</string>
     <string name="show_ime" msgid="2506087537466597099">"物理キーボードが有効になっている間は、画面に表示されます"</string>
     <string name="hardware" msgid="194658061510127999">"仮想キーボードの表示"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"物理キーボードの設定"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"タップして言語とレイアウトを選択してください"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"候補"</u></string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index eaed9dd9..fcc56da 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"შიგთავსი დამალულია წესების შესაბამისად"</string>
     <string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-ის სისტემა"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"პირად პროფილზე გადართვა"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"სამსახურის პროფილზე გადართვა"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"კონტაქტები"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"თქვენს კონტაქტებზე წვდომა"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"მდებარეობა"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"სხვა კლავიატურები"</string>
     <string name="show_ime" msgid="2506087537466597099">"აქტიური ფიზიკური კლავიატურისას ეკრანზე შენარჩუნება"</string>
     <string name="hardware" msgid="194658061510127999">"ვირტუალური კლავიატურის ჩვენება"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"მოახდინეთ ფიზიკური კლავიატურის კონფიგურაცია"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"შეეხეთ ენისა და განლაგების ასარჩევად"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"კანდიდატები"</u></string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index aecf49f..6eaa770 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Мазмұн саясатқа сай жасырылған"</string>
     <string name="safeMode" msgid="2788228061547930246">"Қауіпсіз режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android жүйесі"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Жекеге ауысу"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Жұмысқа ауысу"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Контактілер"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"контактілерге кіру"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Орын"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Басқа пернетақталар"</string>
     <string name="show_ime" msgid="2506087537466597099">"Физикалық пернетақта белсенді кезде оны экранда ұстау"</string>
     <string name="hardware" msgid="194658061510127999">"Виртуалды пернетақтаны көрсету"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Физикалық пернетақтаны конфигурациялау"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тіл мен пернетақта схемасын таңдау үшін түртіңіз"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"үміткерлер"</u></string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index fb80d6e..30d3c0a 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"មាតិកាត្រូវបានលាក់ដោយផ្អែកលើគោលការណ៍"</string>
     <string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ប្រព័ន្ធ​​ Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"ប្តូរទៅផ្ទាល់ខ្លួន"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"ប្តូរទៅការងារ"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"ទំនាក់ទំនង"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ចូលប្រើទំនាក់ទំនងរបស់អ្នក"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"ទីតាំង"</string>
@@ -1065,13 +1063,10 @@
     <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="5673193194563164021">"ក្តារចុចផ្សេងទៀត"</string>
     <string name="show_ime" msgid="2506087537466597099">"ទុកវានៅលើអេក្រង់ខណៈពេលក្តារចុចពិតប្រាកដកំពុងសកម្ម"</string>
     <string name="hardware" msgid="194658061510127999">"បង្ហាញក្ដារចុចនិម្មិត"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"កំណត់រចនាសម្ព័ន្ធក្តារចុចពិតប្រាកដ"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ប៉ះដើម្បីជ្រើសភាសា និងប្លង់"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"បេក្ខជន"</u></string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index f2e5024..087b399 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ನೀತಿಯಿಂದ ಮರೆಮಾಡಲಾಗಿರುವ ವಿಷಯಗಳು"</string>
     <string name="safeMode" msgid="2788228061547930246">"ಸುರಕ್ಷಿತ ಮೋಡ್"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ಸಿಸ್ಟಂ"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"ವೈಯಕ್ತಿಕಗೆ ಬದಲಿಸಿ"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"ಕೆಲಸಕ್ಕೆ ಬದಲಿಸು"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"ಸಂಪರ್ಕಗಳು"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"ಸ್ಥಳ"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"ಇತರೆ ಕೀಬೋರ್ಡ್‌ಗಳು"</string>
     <string name="show_ime" msgid="2506087537466597099">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅದನ್ನು ಪರದೆಯ ಮೇಲೆ ಇರಿಸಿಕೊಳ್ಳಿ"</string>
     <string name="hardware" msgid="194658061510127999">"ವರ್ಚ್ಯುಯಲ್ ಕೀಬೋರ್ಡ್ ತೋರಿಸು"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್ ಕಾನ್ಫಿಗರ್ ಮಾಡಿ"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ಭಾಷೆ ಮತ್ತು ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ಅಭ್ಯರ್ಥಿಗಳು"</u></string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index dc69ee9..52de5ba 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"콘텐츠가 정책에 의해 숨겨졌습니다."</string>
     <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"개인으로 전환"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"직장으로 전환"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"주소록"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"주소록에 접근할 수 있도록"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"위치"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"기타 키보드"</string>
     <string name="show_ime" msgid="2506087537466597099">"물리적 키보드가 활성 상태인 경우 화면에 켜 둠"</string>
     <string name="hardware" msgid="194658061510127999">"가상 키보드 표시"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"물리적 키보드 설정"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"탭하여 언어와 레이아웃을 선택하세요."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"가능한 원인"</u></string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 03951a4..34cc7e5 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Тийиштүү саясат боюнча жашырылган мазмундар"</string>
     <string name="safeMode" msgid="2788228061547930246">"Коопсуз режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Тутуму"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Жеке профилге которулуу"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Жумуш профилине которулуу"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Байланыштар"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"байланыштарыңызга уруксат"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Жайгашкан жер"</string>
@@ -1064,13 +1062,10 @@
     <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="5673193194563164021">"Башка баскычтоптор"</string>
     <string name="show_ime" msgid="2506087537466597099">"Баскычтоп иштетилгенде экранда көрүнүп турсун"</string>
     <string name="hardware" msgid="194658061510127999">"Виртуалдык баскычтоп"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Аппараттык баскычтопту конфигурациялоо"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тил жана калып тандоо үчүн таптап коюңуз"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"талапкерлер"</u></string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index f64f8df..ea62f9b 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ເນື້ອຫາຖືກເຊື່ອງຕາມນະໂຍບາຍ"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"ສະລັບໄປໂປຣໄຟລ໌ສ່ວນຕົວ"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"ສະລັບໄປໂປຣໄຟລ໌ວຽ."</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"ລາຍຊື່"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ເຂົ້າ​ຫາ​ລາຍ​ຊື່​ຂອງ​ທ່ານ"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"ສະ​ຖານ​ທີ່"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"ແປ້ນພິມອື່ນໆ"</string>
     <string name="show_ime" msgid="2506087537466597099">"ເປີດໃຊ້ໃຫ້ມັນຢູ່ໃນໜ້າຈໍໃນຂະນະທີ່ໃຊ້ແປ້ນພິມພາຍນອກຢູ່"</string>
     <string name="hardware" msgid="194658061510127999">"ສະແດງແປ້ນພິມສະເໝືອນ"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ຕັ້ງຄ່າແປ້ນພິມພາຍນອກ"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ແຕະເພື່ອເລືອກພາສາ ແລະ ໂຄງແປ້ນພິມ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ຕົວເລືອກ"</u></string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 517a069..3e815ec 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -237,10 +237,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Turinys paslėptas vadovaujantis politika"</string>
     <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
     <string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Perjungti į asmeninį režimą"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Perjungti į darbo režimą"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktai"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"pasiekti kontaktus"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Vietovė"</string>
@@ -1079,13 +1077,10 @@
     <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="5673193194563164021">"Kitos klaviatūros"</string>
     <string name="show_ime" msgid="2506087537466597099">"Palikti ekrane, kol fizinė klaviatūra aktyvi"</string>
     <string name="hardware" msgid="194658061510127999">"Rodyti virtualiąją klaviatūrą"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fizinės klaviatūros konfigūravimas"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Palieskite, kad pasirinktumėte kalbą ir išdėstymą"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidatai"</u></string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 8d8f99b..56001fc 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -235,10 +235,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Pārslēgt personīgo profilu"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Pārslēgt darba profilu"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktpersonas"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"piekļūt jūsu kontaktpersonu datiem"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Atrašanās vieta"</string>
@@ -1071,13 +1069,10 @@
     <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="5673193194563164021">"Citas tastatūras"</string>
     <string name="show_ime" msgid="2506087537466597099">"Paturēt ekrānā, kamēr ir aktīva fiziskā tastatūra"</string>
     <string name="hardware" msgid="194658061510127999">"Virtuālās tastatūras rādīšana"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fiziskās tastatūras konfigurēšana"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Pieskarieties, lai atlasītu valodu un izkārtojumu"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidāti"</u></string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 71c1951..060a9fa 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содржините се скриени поради политиката"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбеден режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Систем Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Префрлете на личен профил"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Префрли на работен профил"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакти"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"пристапува до контактите"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Локација"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Други тастатури"</string>
     <string name="show_ime" msgid="2506087537466597099">"Прикажувај го на екранот додека е активна физичката тастатура"</string>
     <string name="hardware" msgid="194658061510127999">"Прикажи виртуелна тастатура"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Конфигурирајте физичка тастатура"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Допрете за избирање јазик и распоред"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 92f9282..f6ff1d8 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"നയം അനുസരിച്ച് ഉള്ളടക്കം മറച്ചിരിക്കുന്നു"</string>
     <string name="safeMode" msgid="2788228061547930246">"സുരക്ഷിത മോഡ്"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android സിസ്റ്റം"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"വ്യക്തിഗത പ്രൊഫൈലിലേക്ക് മാറുക"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് മാറുക"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"കോൺടാക്റ്റുകൾ"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ ആക്‌സസ്സ് ചെയ്യുക"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"ലൊക്കേഷൻ"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"മറ്റ് കീബോർഡുകൾ"</string>
     <string name="show_ime" msgid="2506087537466597099">"ഫിസിക്കൽ കീബോർഡ് സജീവമായിരിക്കുമ്പോൾ സ്ക്രീനിൽ നിലനിർത്തുക"</string>
     <string name="hardware" msgid="194658061510127999">"വെർച്വൽ കീബോർഡ് കാണിക്കുക"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ഫിസിക്കൽ കീബോർഡ് കോൺഫിഗർ ചെയ്യുക"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ഭാഷയും ലേഔട്ടും തിരഞ്ഞെടുക്കുന്നതിന് ടാപ്പുചെയ്യുക"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"കാൻഡിഡേറ്റുകൾ"</u></string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index c1cba4f..75105e6 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Удирдамжийн дагуу нуусан агуулга"</string>
     <string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Андройд систем"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"\"Хувийн\" руу шилжих"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"\"Ажлын\" руу шилжих"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Харилцагчдын хаяг"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"харилцагч руугаа хандах"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Байршил"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Бусад гар"</string>
     <string name="show_ime" msgid="2506087537466597099">"Бодит гар идэвхтэй үед үүнийг дэлгэцэнд харуулна уу"</string>
     <string name="hardware" msgid="194658061510127999">"Хийсвэр гарыг харуулах"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Биет гарыг хэлбэрт оруулах"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Хэл болон бүдүүвчийг сонгохын тулд дарна уу"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"нэр дэвшигч"</u></string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index f41e6ed..8a3e564 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"धोरणाद्वारे सामग्री लपविली"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"वैयक्तिकवर स्विच करा"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"कार्यावर स्विच करा"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"संपर्क"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"आपल्या संपर्कांवर प्रवेश"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"स्थान"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"इतर कीबोर्ड"</string>
     <string name="show_ime" msgid="2506087537466597099">"भौतिक कीबोर्ड सक्रिय असताना त्यास स्क्रीनवर ठेवा"</string>
     <string name="hardware" msgid="194658061510127999">"व्हर्च्युअल कीबोर्ड दर्शवा"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"वास्तविक कीबोर्ड कॉन्फिगर करा"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा आणि लेआउट निवडण्यासाठी टॅप करा"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"उमेदवार"</u></string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 9a69bf9..5db9c77 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Kandungan disembunyikan oleh dasar"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Beralih kepada Peribadi"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Beralih kepada Kerja"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kenalan"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"mengakses kenalan anda"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Lokasi"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Papan kekunci lain"</string>
     <string name="show_ime" msgid="2506087537466597099">"Pastikannya pada skrin, semasa papan kekunci fizikal aktif"</string>
     <string name="hardware" msgid="194658061510127999">"Tunjukkan papan kekunci maya"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurasikan papan kekunci fizikal"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketik untuk memilih bahasa dan susun atur"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"calon"</u></string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index b3c80d5..5e5ec4e 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"မူဝါဒမှ အကြောင်းအရာများကို ဝှက်ထားသည်"</string>
     <string name="safeMode" msgid="2788228061547930246">"အန္တရာယ်ကင်းမှု စနစ်(Safe mode)"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android စနစ်"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"ကိုယ်ပိုင်သီးသန့်အဖြစ် ပြောင်းပါ"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"အလုပ်သို့ ပြောင်းပါ"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"အဆက်အသွယ်များ"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"သင့် အဆက်အသွယ်များအား ဝင်ရောက်သုံးရန်"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"တည်နေရာ"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"အခြားကီးဘုတ်များ"</string>
     <string name="show_ime" msgid="2506087537466597099">"စက်၏ကီးဘုတ်ကိုအသုံးပြုနေစဉ် ၎င်းကိုမျက်နှာပြင်ပေါ်တွင် ထားပါ"</string>
     <string name="hardware" msgid="194658061510127999">"ကီးဘုတ်အတုပြရန်"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ရုပ်ပိုင်းဆိုင်ရာ အသွင်အပြင်ကို ပြင်ဆင်သတ်မှတ်ပါ"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ဘာသာစကားနှင့် အသွင်အပြင်ရွေးချယ်ရန် တို့ပါ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ရွေးချယ်ခံမည့်သူ"</u></string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index bebf593..cfccdeb 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Innholdet er skjult i henhold til retningslinjene"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Bytt til den personlige profilen"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Bytt til jobbprofilen"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakter"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"se kontaktene dine"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Posisjon"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Andre tastaturoppsett"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ha den på skjermen mens det fysiske tastaturet er aktivt"</string>
     <string name="hardware" msgid="194658061510127999">"Vis det virtuelle tastaturet"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurer et fysisk tastatur"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trykk for å velge språk og layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="candidates_style" msgid="4333913089637062257">"TAG_FONT"<u>"kandidater"</u>"CLOSE_FONT"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 24bb1f0..fb817b5 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"नीतिद्वारा लुकाइएका सामग्री"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"एन्ड्रोइड प्रणाली"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"व्यक्तिगत प्रोफाइलमा स्विच गर्नुहोस्"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"कार्य प्रोफाइलमा स्विच गर्नुहोस्"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"सम्पर्कहरू"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"तपाईँको सम्पर्कमा पहुँच गर्नुहोस्"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"स्थान"</string>
@@ -1069,13 +1067,10 @@
     <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="5673193194563164021">"अन्य किबोर्डहरू"</string>
     <string name="show_ime" msgid="2506087537466597099">"भौतिक किबोर्ड सक्रिय हुँदा यसलाई स्क्रिनमा राख्नुहोस्"</string>
     <string name="hardware" msgid="194658061510127999">"भर्चुअल किबोर्ड देखाउनुहोस्"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"फिजिकल किबोर्डलाई कन्फिगर गर्नुहोस्"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा र लेआउट चयन गर्न ट्याप गर्नुहोस्"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"उम्मेदवार"</u></string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5759cad..3de8496 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Content verborgen op basis van beleid"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Overschakelen naar persoonlijk profiel"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Overschakelen naar werkprofiel"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contacten"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"toegang krijgen tot je contacten"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Locatie"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Andere toetsenborden"</string>
     <string name="show_ime" msgid="2506087537466597099">"Dit op het scherm weergeven terwijl het fysieke toetsenbord actief is"</string>
     <string name="hardware" msgid="194658061510127999">"Virtueel toetsenbord tonen"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fysiek toetsenbord configureren"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om een taal en indeling te selecteren"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaten"</u></string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index b984760..87f973f 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ਨੀਤੀ ਦੁਆਰਾ ਸਮੱਗਰੀ ਲੁਕਾਈ ਗਈ"</string>
     <string name="safeMode" msgid="2788228061547930246">"ਸੁਰੱਖਿਅਤ ਮੋਡ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"ਨਿੱਜੀ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"ਕੰਮ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"ਸੰਪਰਕ"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ਆਪਣੇ ਸੰਪਰਕਾਂ ਨੂੰ ਐਕਸੈਸ ਕਰੋ"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"ਨਿਰਧਾਰਿਤ ਸਥਾਨ"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"ਹੋਰ ਕੀ-ਬੋਰਡ"</string>
     <string name="show_ime" msgid="2506087537466597099">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ ਸਰਗਰਮ ਹੋਣ ਦੌਰਾਨ ਇਸ ਨੂੰ ਸਕ੍ਰੀਨ \'ਤੇ ਬਣਾਈ ਰੱਖੋ"</string>
     <string name="hardware" msgid="194658061510127999">"ਵਰਚੁਅਲ ਕੀ-ਬੋਰਡ ਵਿਖਾਓ"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ ਦਾ ਸੰਰੂਪਣ ਕਰੋ"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ਭਾਸ਼ਾ ਅਤੇ ਖਾਕਾ ਚੁਣਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ਉਮੀਦਵਾਰ"</u></string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 7248f4a..6be9a9d 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -237,10 +237,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Treść ukryta z powodu zasad"</string>
     <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
     <string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Włącz profil osobisty"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Włącz profil do pracy"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakty"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"dostęp do kontaktów"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Lokalizacja"</string>
@@ -1079,13 +1077,10 @@
     <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="5673193194563164021">"Inne klawiatury"</string>
     <string name="show_ime" msgid="2506087537466597099">"Pozostaw na ekranie, gdy aktywna jest klawiatura fizyczna"</string>
     <string name="hardware" msgid="194658061510127999">"Pokaż klawiaturę wirtualną"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Skonfiguruj klawiaturę fizyczną"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Kliknij, by wybrać język i układ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandydaci"</u></string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index bddb0fc..c8004bf 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Alternar para \"Trabalho\""</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatos"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"acesse seus contatos"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Local"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Outros teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Manter na tela enquanto o teclado físico estiver ativo"</string>
     <string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurar teclado físico"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 68c4bd9..c2ba8ad 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Mudar para pessoal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Mudar para trabalho"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"aceder aos contactos"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Localização"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Outros teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Manter no ecrã enquanto o teclado físico estiver ativo"</string>
     <string name="hardware" msgid="194658061510127999">"Mostrar o teclado virtual"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurar teclado físico"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o esquema"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index bddb0fc..c8004bf 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Alternar para \"Pessoal\""</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Alternar para \"Trabalho\""</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatos"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"acesse seus contatos"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Local"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Outros teclados"</string>
     <string name="show_ime" msgid="2506087537466597099">"Manter na tela enquanto o teclado físico estiver ativo"</string>
     <string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurar teclado físico"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 58c9383..7485e65 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -235,10 +235,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conținutul este ascuns conform politicii"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Comutați la Personal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Comutați la Serviciu"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Persoane de contact"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"acceseze persoanele de contact"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Locație"</string>
@@ -1071,13 +1069,10 @@
     <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="5673193194563164021">"Alte tastaturi"</string>
     <string name="show_ime" msgid="2506087537466597099">"Se păstrează pe ecran cât timp este activată tastatura fizică"</string>
     <string name="hardware" msgid="194658061510127999">"Afișați tastatura virtuală"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configurați tastatura fizică"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Atingeți pentru a selecta limba și aspectul"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidați"</u></string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 345bb49..5926bfd 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -237,10 +237,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содержимое скрыто в соответствии с заданными правилами"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Перейти в личный профиль"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Перейти в рабочий профиль"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакты"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"доступ к контактам"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Местоположение"</string>
@@ -1079,13 +1077,10 @@
     <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="5673193194563164021">"Другие клавиатуры"</string>
     <string name="show_ime" msgid="2506087537466597099">"Показывать на экране, когда физическая клавиатура включена"</string>
     <string name="hardware" msgid="194658061510127999">"Виртуальная клавиатура"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Настройка физической клавиатуры"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Нажмите, чтобы выбрать язык и раскладку"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"варианты"</u></string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index f01ab61..6c76da0 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ප්‍රතිපත්තිය විසින් අන්තර්ගතය සඟවන ලදී"</string>
     <string name="safeMode" msgid="2788228061547930246">"ආරක්‍ෂිත ආකාරය"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android පද්ධතිය"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"පුද්ගලික වෙත මාරු වන්න"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"කාර්යාලය වෙත මාරු වන්න"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"සම්බන්ධතා"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ඔබේ සම්බන්ධතාවලට පිවිසෙන්න"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"ස්ථානය"</string>
@@ -1065,13 +1063,10 @@
     <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="5673193194563164021">"වෙනත් යතුරු පුවරු"</string>
     <string name="show_ime" msgid="2506087537466597099">"භෞතික යතුරු පුවරුව සක්‍රිය අතරතුර එය තිරය මත තබා ගන්න"</string>
     <string name="hardware" msgid="194658061510127999">"අතථ්‍ය යතුරු පුවරුව පෙන්වන්න"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"භෞතික යතුරු පුවරුව වින්‍යාස කරන්න"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"භාෂාව හා පිරිසැලසුම තේරීමට තට්ටු කරන්න"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"අපේක්ෂකයන්"</u></string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 1a3ef4c..ec45070 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -237,10 +237,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Prepnúť na osobný"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Prepnúť na pracovný"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakty"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"prístup k vašim kontaktom"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Poloha"</string>
@@ -1079,13 +1077,10 @@
     <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="5673193194563164021">"Ďalšie klávesnice"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ponechať na obrazovke, keď je aktívna fyzická klávesnica"</string>
     <string name="hardware" msgid="194658061510127999">"Zobraziť virtuálnu klávesnicu"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurácia fyzickej klávesnice"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozloženie"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c102abb..b2dba7e0 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -237,10 +237,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Pravilnik je skril vsebino"</string>
     <string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Preklop na osebni profil"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Preklop na delovni profil"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Stiki"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"dostop do stikov"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string>
@@ -1079,13 +1077,10 @@
     <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="5673193194563164021">"Druge tipkovnice"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ohrani na zaslonu, dokler je aktivna fizična tipkovnica"</string>
     <string name="hardware" msgid="194658061510127999">"Pokaži navidezno tipkovnico"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguriranje fizične tipkovnice"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dotaknite se, če želite izbrati jezik in postavitev."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 9151893..1846399 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemi \"android\""</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Ndryshoje te \"Personale\""</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Ndryshoje te \"Puna\""</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktet"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"qasu te kontaktet e tua"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Vendndodhja"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Tastierat e tjera"</string>
     <string name="show_ime" msgid="2506087537466597099">"Mbaje në ekran ndërsa tastiera fizike është aktive"</string>
     <string name="hardware" msgid="194658061510127999">"Shfaq tastierën virtuale"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguro tastierën fizike"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trokit për të zgjedhur gjuhën dhe strukturën"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidatë"</u></string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 9f8c2c0..2112dbb 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -235,10 +235,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Садржај је сакривен смерницама"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Пређи на Лични профил"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Пређи на профил за Work"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакти"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"приступи контактима"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Локација"</string>
@@ -1071,13 +1069,10 @@
     <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="5673193194563164021">"Друге тастатуре"</string>
     <string name="show_ime" msgid="2506087537466597099">"Задржи га на екрану док је физичка тастатура активна"</string>
     <string name="hardware" msgid="194658061510127999">"Прикажи виртуелну тастатуру"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Конфигуришите физичку тастатуру"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Додирните да бисте изабрали језик и распоред"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index d3855f8..832d4a2 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Byt till din personliga profil"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Byt till jobbprofilen"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakter"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"få tillgång till dina kontakter"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Plats"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Andra tangentbord"</string>
     <string name="show_ime" msgid="2506087537466597099">"Ha kvar den på skärmen när det fysiska tangentbordet används"</string>
     <string name="hardware" msgid="194658061510127999">"Visa virtuellt tangentbord"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfigurera fysiskt tangentbord"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryck om du vill välja språk och layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index fd5c2c7..e0a32f6 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -235,10 +235,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Maudhui yamefichwa kulingana na sera"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Badili uweke wasifu wa Binafsi"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Badili uweke wasifu wa Kazini"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Anwani"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ifikie anwani zako"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Mahali"</string>
@@ -1065,13 +1063,10 @@
     <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="5673193194563164021">"Kibodi zingine"</string>
     <string name="show_ime" msgid="2506087537466597099">"Iweke kwenye skrini wakati kibodi inapotumika"</string>
     <string name="hardware" msgid="194658061510127999">"Onyesha kibodi pepe"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Sanidi kibodi halisi"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Gonga ili uchague lugha na muundo"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"wagombeaji"</u></string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index f92177a..773301f 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"கொள்கையின்படி உள்ளடக்கம் மறைக்கப்பட்டது"</string>
     <string name="safeMode" msgid="2788228061547930246">"பாதுகாப்பு பயன்முறை"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android அமைப்பு"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"தனிப்பட்ட சுயவிவரத்திற்கு மாறு"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"பணிச் சுயவிவரத்திற்கு மாறு"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"தொடர்புகள்"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"தொடர்புகளை அணுகும்"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"இருப்பிடம்"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"பிற விசைப்பலகைகள்"</string>
     <string name="show_ime" msgid="2506087537466597099">"கைமுறை விசைப்பலகை இயக்கத்தில் இருக்கும் போது IMEஐ திரையில் வைத்திரு"</string>
     <string name="hardware" msgid="194658061510127999">"விர்ச்சுவல் விசைப்பலகையை காட்டு"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"கைமுறை விசைப்பலகையை உள்ளமைக்கவும்"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"மொழியையும் தளவமைப்பையும் தேர்ந்தெடுக்க, தட்டவும்"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"கேன்டிடேட்ஸ்"</u></string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 9b5fc01..4809c98 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"విధానం ద్వారా కంటెంట్‌లు దాచబడ్డాయి"</string>
     <string name="safeMode" msgid="2788228061547930246">"సురక్షిత మోడ్"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android సిస్టమ్"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"వ్యక్తిగతానికి మార్చు"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"కార్యాలయానికి మార్చు"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"పరిచయాలు"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"మీ పరిచయాలను ప్రాప్యత చేయడానికి"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"స్థానం"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"ఇతర కీబోర్డ్‌లు"</string>
     <string name="show_ime" msgid="2506087537466597099">"దీన్ని భౌతిక కీబోర్డ్ సక్రియంగా ఉన్నప్పుడు స్క్రీన్‌పై ఉంచుతుంది"</string>
     <string name="hardware" msgid="194658061510127999">"వర్చువల్ కీబోర్డ్‌ను చూపు"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"భౌతిక కీబోర్డుని కాన్ఫిగర్ చేయండి"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"భాష మరియు లేఅవుట్‌ను ఎంచుకోవడానికి నొక్కండి"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"క్యాండిడేట్‌లు"</u></string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ca401bc..0ea2e52 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"มีการซ่อนเนื้อหาโดยนโยบาย"</string>
     <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"เปลี่ยนไปใช้โปรไฟล์ส่วนตัว"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"เปลี่ยนไปใช้โปรไฟล์งาน"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"รายชื่อติดต่อ"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"เข้าถึงรายชื่อติดต่อ"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"ตำแหน่ง"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"แป้นพิมพ์อื่นๆ"</string>
     <string name="show_ime" msgid="2506087537466597099">"เปิดทิ้งไว้บนหน้าจอในระหว่างใช้งานแป้นพิมพ์จริง"</string>
     <string name="hardware" msgid="194658061510127999">"แสดงแป้นพิมพ์เสมือน"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"กำหนดค่าแป้นพิมพ์จริง"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"แตะเพื่อเลือกภาษาและรูปแบบ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ตัวเลือก"</u></string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 1a63a99..00918a4 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Lumipat sa Personal"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Lumipat sa para sa Trabaho"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Mga Contact"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ina-access ang iyong mga contact"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Lokasyon"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Iba pang mga keyboard"</string>
     <string name="show_ime" msgid="2506087537466597099">"Panatilihin ito sa screen habang aktibo ang pisikal na keyboard"</string>
     <string name="hardware" msgid="194658061510127999">"Ipakita ang virtual keyboard"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"I-configure ang pisikal na keyboard"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"I-tap upang pumili ng wika at layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"mga kandidato"</u></string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e4a44d2..4db8264 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"İçerikler politika nedeniyle gizlendi"</string>
     <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Kişisel Profile Geç"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"İş Profiline Geç"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kişiler"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"kişilerinize erişme"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Konum"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Diğer klavyeler"</string>
     <string name="show_ime" msgid="2506087537466597099">"Fiziksel klavye etkin durumdayken ekranda tut"</string>
     <string name="hardware" msgid="194658061510127999">"Sanal klavyeyi göster"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Fiziksel klavyeyi yapılandırın"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dili ve düzeni seçmek için hafifçe dokunun"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"adaylar"</u></string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index a6020e8..fe7be12 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -237,10 +237,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Вміст сховано згідно з правилом"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Перейти в особистий профіль"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Перейти в робочий профіль"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Контакти"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"отримувати доступ до контактів"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Геодані"</string>
@@ -1079,13 +1077,10 @@
     <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="5673193194563164021">"Інші клавіатури"</string>
     <string name="show_ime" msgid="2506087537466597099">"Утримуйте на екрані, коли активна фізична клавіатура"</string>
     <string name="hardware" msgid="194658061510127999">"Показати віртуальну клавіатуру"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Налаштуйте фізичну клавіатуру"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Торкніться, щоб вибрати мову та розкладку"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index b515c55..5236b7f 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"مواد پالیسی کے تحت مخفی ہے"</string>
     <string name="safeMode" msgid="2788228061547930246">"حفاظتی وضع"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏Android سسٹم"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"ذاتی پر سوئچ کریں"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"کام پر سوئچ کریں"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"رابطے"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"اپنے رابطوں تک رسائی حاصل کریں"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"مقام"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"دیگر کی بورڈز"</string>
     <string name="show_ime" msgid="2506087537466597099">"‏جب فزیکل کی بورڈ فعال ہو تو IME کو اسکرین پر رکھیں"</string>
     <string name="hardware" msgid="194658061510127999">"ورچوئل کی بورڈ دکھائیں"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"فزیکل کی بورڈ کنفیگر کریں"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"زبان اور لے آؤٹ منتخب کرنے کیلئے تھپتھپائیں"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"امیدواران"</u></string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 6323f52..6cb65a3 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Qoidaga muvofiq kontent yashirilgan"</string>
     <string name="safeMode" msgid="2788228061547930246">"Xavfsiz usul"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android tizimi"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Shaxsiy profilga o‘tish"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Ishchi profilga o‘tish"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontaktlar"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"kontaktlarga kirish"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Joylashuv"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Boshqa klaviaturalar"</string>
     <string name="show_ime" msgid="2506087537466597099">"Tashqi klaviaturadan foydalanilayotganda buni ekranda saqlab turish"</string>
     <string name="hardware" msgid="194658061510127999">"Virtual klaviatura ko‘rsatilsin"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Tashqi klaviaturani sozlash"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Til va sxemani belgilash uchun bosing"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"nomzodlar"</u></string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 10516af..29eef92 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -233,10 +233,8 @@
     <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>
     <string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Chuyển sang Cá nhân"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Chuyển sang Công việc"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Danh bạ"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"truy cập vào danh bạ của bạn"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Vị trí"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Bàn phím khác"</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>
     <string name="hardware" msgid="194658061510127999">"Hiển thị bàn phím ảo"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Định cấu hình bàn phím thực"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Nhấn để chọn ngôn ngữ và bố cục"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ứng viên"</u></string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index f7bcaba..3b26e46 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"内容已隐藏(根据政策规定)"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"切换到“个人”"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"切换到“工作”"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"通讯录"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"访问您的通讯录"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"位置信息"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"其他键盘"</string>
     <string name="show_ime" msgid="2506087537466597099">"连接到实体键盘时使其在屏幕上保持显示状态"</string>
     <string name="hardware" msgid="194658061510127999">"显示虚拟键盘"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"配置实体键盘"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"点按即可选择语言和布局"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"候选"</u></string>
@@ -1478,7 +1473,7 @@
     <string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理员安装"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"由您单位的管理员更新"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"已被管理员删除"</string>
-    <string name="battery_saver_description" msgid="1960431123816253034">"为了延长电池的续航时间,节电助手会降低设备的性能,并限制振动、位置信息服务和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n节电助手会在设备充电时自动关闭。"</string>
+    <string name="battery_saver_description" msgid="1960431123816253034">"为了延长电池的续航时间,省电模式会降低设备的性能,并限制振动、位置信息服务和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n省电模式会在设备充电时自动关闭。"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
       <item quantity="other">%1$d 分钟(到<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="one">1 分钟(到<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 15e9a5e..28f2bac 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"已根據政策隱藏內容"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"切換至工作設定檔"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"通訊錄"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"存取您的通訊錄"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"位置"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"其他鍵盤"</string>
     <string name="show_ime" msgid="2506087537466597099">"在實體鍵盤處於連接狀態時保持顯示"</string>
     <string name="hardware" msgid="194658061510127999">"顯示虛擬鍵盤"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"設定實體鍵盤"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕按即可選取語言和鍵盤配置"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"待選項目"</u></string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a27f1b7..dfc7890 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"內容已依據政策隱藏"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"切換至個人設定檔"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"切換至公司設定檔"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"聯絡人"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"存取您的聯絡人"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"位置"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"其他鍵盤"</string>
     <string name="show_ime" msgid="2506087537466597099">"有連接的實體鍵盤時保持顯示"</string>
     <string name="hardware" msgid="194658061510127999">"顯示虛擬鍵盤"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"設定實體鍵盤"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕觸即可選取語言和版面配置"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"待選項目"</u></string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 60be8fd..e32f26b 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -233,10 +233,8 @@
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Okuqukethwe kufihlwe inqubomgomo"</string>
     <string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
-    <!-- no translation found for user_owner_label (1119010402169916617) -->
-    <skip />
-    <!-- no translation found for managed_profile_label (5289992269827577857) -->
-    <skip />
+    <string name="user_owner_label" msgid="1119010402169916617">"Shintshela komuntu siqu"</string>
+    <string name="managed_profile_label" msgid="5289992269827577857">"Shintshela kumsebenzi"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Oxhumana nabo"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"finyelela koxhumana nabo"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Indawo"</string>
@@ -1063,13 +1061,10 @@
     <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="5673193194563164021">"Amanye amakhibhodi"</string>
     <string name="show_ime" msgid="2506087537466597099">"Yigcine kusikrini ngenkathi kusebenza ikhibhodi ephathekayo"</string>
     <string name="hardware" msgid="194658061510127999">"Bonisa ikhibhodi ebonakalayo"</string>
-    <!-- no translation found for select_keyboard_layout_notification_title (597189518763083494) -->
-    <skip />
-    <!-- no translation found for select_keyboard_layout_notification_message (8084622969903004900) -->
-    <skip />
+    <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Lungisa ikhibhodi yoqobo"</string>
+    <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Thepha ukuze ukhethe ulimi nesakhiwo"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"abahlanganyeli"</u></string>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index d1c0895..5b4364d 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -225,6 +225,9 @@
             granted any application pre-installed on the system image (not just privileged
             apps). -->
         <flag name="preinstalled" value="0x400" />
+        <!-- Additional flag from base permission type: this permission can be automatically
+            granted to the setup wizard app -->
+        <flag name="setup" value="0x800" />
     </attr>
 
     <!-- Flags indicating more context for a permission group. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 892b3d5..b4371c1 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -578,6 +578,9 @@
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
 
+    <!-- Fast brightness animation ramp rate -->
+    <integer translatable="false" name="config_brightness_ramp_rate_fast">200</integer>
+
     <!-- Don't name config resources like this.  It should look like config_annoyDianne -->
     <bool name="config_annoy_dianne">true</bool>
 
@@ -2501,4 +2504,20 @@
     <!-- True if the device requires AppWidgetService even if it does not have
          the PackageManager.FEATURE_APP_WIDGETS feature -->
     <bool name="config_enableAppWidgetService">false</bool>
+
+    <!-- True if the device supports Sustained Performance Mode-->
+    <bool name="config_sustainedPerformanceModeSupported">false</bool>
+
+    <!-- Controls how we deal with externally connected physical keyboards.
+         0 - When using this device, it is not clear for users to recognize when the physical
+             keyboard is (should be) connected and when it is (should be) disconnected.  Most of
+             phones and tablets with Bluetooth keyboard would fall into this category because the
+             connected Bluetooth keyboard may or may not be nearby the host device.
+         1 - When using this device, it is clear for users to recognize when the physical
+             keyboard is (should be) connected and when it is (should be) disconnected.
+             Devices with wired USB keyboard is one clear example.  Some 2-in-1 convertible
+             tablets with dedicated keyboards may have the same affordance to wired USB keyboard.
+    -->
+    <integer name="config_externalHardKeyboardBehavior">0</integer>
+
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0839187..6ff7139 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2716,6 +2716,8 @@
 
     <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
     <public type="style" name="Widget.Material.SeekBar.Discrete" />
+    <public type="style" name="Widget.Material.CompoundButton.Switch" />
+    <public type="style" name="Widget.Material.Light.CompoundButton.Switch" />
 
     <public type="id" name="accessibilityActionSetProgress" />
     <public type="id" name="icon_frame" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e83e4db..2215bd4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1744,6 +1744,7 @@
   <java-symbol type="integer" name="config_defaultNotificationLedOff" />
   <java-symbol type="integer" name="config_defaultNotificationLedOn" />
   <java-symbol type="integer" name="config_deskDockKeepsScreenOn" />
+  <java-symbol type="integer" name="config_externalHardKeyboardBehavior" />
   <java-symbol type="integer" name="config_lightSensorWarmupTime" />
   <java-symbol type="integer" name="config_lowBatteryCloseWarningBump" />
   <java-symbol type="integer" name="config_lowBatteryWarningLevel" />
@@ -1766,6 +1767,7 @@
   <java-symbol type="integer" name="config_shutdownBatteryTemperature" />
   <java-symbol type="integer" name="config_undockedHdmiRotation" />
   <java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
+  <java-symbol type="integer" name="config_brightness_ramp_rate_fast" />
   <java-symbol type="layout" name="am_compat_mode_dialog" />
   <java-symbol type="layout" name="launch_warning" />
   <java-symbol type="layout" name="safe_mode" />
@@ -2418,13 +2420,11 @@
   <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="header_sub_text" />
+  <java-symbol type="id" name="header_text" />
   <java-symbol type="id" name="expand_button" />
   <java-symbol type="id" name="notification_header" />
-  <java-symbol type="id" name="header_content_info" />
   <java-symbol type="id" name="time_divider" />
-  <java-symbol type="id" name="sub_text_divider" />
-  <java-symbol type="id" name="content_info_divider" />
+  <java-symbol type="id" name="header_text_divider" />
   <java-symbol type="id" name="text_line_1" />
   <java-symbol type="drawable" name="ic_expand_notification" />
   <java-symbol type="drawable" name="ic_collapse_notification" />
@@ -2541,4 +2541,6 @@
 
   <java-symbol type="id" name="textSpacerNoTitle" />
   <java-symbol type="id" name="titleDividerNoCustom" />
+
+  <java-symbol type="bool" name="config_sustainedPerformanceModeSupported" />
 </resources>
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index 76b5fe1..2e593a3 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -94,11 +94,27 @@
   <!-- This is the battery capacity in mAh (measured at nominal voltage) -->
   <item name="battery.capacity">1000</item>
 
-  <array name="wifi.batchedscan"> <!-- mA -->
-      <value>.0002</value> <!-- 1-8/hr -->
-      <value>.002</value>  <!-- 9-64/hr -->
-      <value>.02</value>   <!-- 65-512/hr -->
-      <value>.2</value>    <!-- 513-4,096/hr -->
-      <value>2</value>    <!-- 4097-/hr -->
+  <!-- Wifi related values. -->
+  <!-- Idle Receive current for wifi radio in mA. 0 by default-->
+  <item name="wifi.controller.idle">0</item>
+  <!-- Rx current for wifi radio in mA. 0 by default-->
+  <item name="wifi.controller.rx">0</item>
+  <!-- Tx current for wifi radio in mA. 0 by default-->
+  <item name="wifi.controller.tx">0</item>
+  <!-- Current at each of the wifi Tx levels in mA. The number of tx levels varies per device
+       and is available only of wifi chipsets which support the tx level reporting. Use
+        wifi.tx for other chipsets. none by default -->
+  <array name="wifi.controller.tx_levels"> <!-- mA -->
   </array>
+  <!-- Operating volatage for wifi radio in mV. 0 by default-->
+  <item name="wifi.controller.voltage">0</item>
+
+  <array name="wifi.batchedscan"> <!-- mA -->
+    <value>.0002</value> <!-- 1-8/hr -->
+    <value>.002</value>  <!-- 9-64/hr -->
+    <value>.02</value>   <!-- 65-512/hr -->
+    <value>.2</value>    <!-- 513-4,096/hr -->
+    <value>2</value>    <!-- 4097-/hr -->
+  </array>
+
 </device>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index b7926cf..2452cfd 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1256,15 +1256,6 @@
         <service android:name="android.os.BinderThreadPriorityService"
                 android:process=":BinderThreadPriorityService" />
 
-        <!-- Used by ApplyOverrideConfigurationTest -->
-        <activity android:name="android.app.activity.ApplyOverrideConfigurationActivity"
-                  android:configChanges="orientation|screenSize">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
         <!-- Application components used for search manager tests -->
 
         <activity android:name="android.app.activity.SearchableActivity"
diff --git a/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationActivity.java b/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationActivity.java
deleted file mode 100644
index 3df522d..0000000
--- a/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationActivity.java
+++ /dev/null
@@ -1,32 +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.app.activity;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Configuration;
-
-public class ApplyOverrideConfigurationActivity extends Activity {
-
-    @Override
-    protected void attachBaseContext(Context newBase) {
-        super.attachBaseContext(newBase);
-
-        Configuration overrideConfig = new Configuration();
-        overrideConfig.smallestScreenWidthDp = ApplyOverrideConfigurationTest.OVERRIDE_WIDTH;
-        applyOverrideConfiguration(overrideConfig);
-    }
-}
diff --git a/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationTest.java b/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationTest.java
deleted file mode 100644
index 15ed77e..0000000
--- a/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationTest.java
+++ /dev/null
@@ -1,66 +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.app.activity;
-
-import android.app.UiAutomation;
-import android.content.res.Configuration;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.ActivityInstrumentationTestCase2;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class ApplyOverrideConfigurationTest extends
-        ActivityInstrumentationTestCase2<ApplyOverrideConfigurationActivity> {
-
-    public static final int OVERRIDE_WIDTH = 9999;
-
-    public ApplyOverrideConfigurationTest() {
-        super(ApplyOverrideConfigurationActivity.class);
-    }
-
-    @Before
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        injectInstrumentation(InstrumentationRegistry.getInstrumentation());
-        getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0);
-    }
-
-    @Test
-    public void testConfigurationIsOverriden() throws Exception {
-        Configuration config = getActivity().getResources().getConfiguration();
-        assertEquals(OVERRIDE_WIDTH, config.smallestScreenWidthDp);
-
-        getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_90);
-
-        config = getActivity().getResources().getConfiguration();
-        assertEquals(OVERRIDE_WIDTH, config.smallestScreenWidthDp);
-    }
-
-    @After
-    @Override
-    public void tearDown() throws Exception {
-        getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE);
-        super.tearDown();
-    }
-}
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index 9ab62cc..e7aca78 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -23,10 +23,10 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.net.NetworkScorerAppManager.NetworkScorerAppData;
 import android.os.UserHandle;
 import android.test.InstrumentationTestCase;
-import android.util.Pair;
 
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
@@ -58,25 +58,26 @@
 
     public void testGetAllValidScorers() throws Exception {
         // Package 1 - Valid scorer.
-        Pair<ResolveInfo, ResolveInfo> package1 = buildResolveInfo("package1", 1, true, true,
-                false);
+        ResolveInfoHolder package1 = buildResolveInfo("package1", 1, true, true, false, false);
 
         // Package 2 - Receiver does not have BROADCAST_NETWORK_PRIVILEGED permission.
-        Pair<ResolveInfo, ResolveInfo> package2 = buildResolveInfo("package2", 2, false, true,
-                false);
+        ResolveInfoHolder package2 = buildResolveInfo("package2", 2, false, true, false, false);
 
         // Package 3 - App does not have SCORE_NETWORKS permission.
-        Pair<ResolveInfo, ResolveInfo> package3 = buildResolveInfo("package3", 3, true, false,
-                false);
+        ResolveInfoHolder package3 = buildResolveInfo("package3", 3, true, false, false, false);
 
         // Package 4 - Valid scorer w/ optional config activity.
-        Pair<ResolveInfo, ResolveInfo> package4 = buildResolveInfo("package4", 4, true, true, true);
+        ResolveInfoHolder package4 = buildResolveInfo("package4", 4, true, true, true, false);
 
-        List<Pair<ResolveInfo, ResolveInfo>> scorers = new ArrayList<>();
+        // Package 5 - Valid scorer w/ optional service to bind to.
+        ResolveInfoHolder package5 = buildResolveInfo("package5", 5, true, true, false, true);
+
+        List<ResolveInfoHolder> scorers = new ArrayList<>();
         scorers.add(package1);
         scorers.add(package2);
         scorers.add(package3);
         scorers.add(package4);
+        scorers.add(package5);
         setScorers(scorers);
 
         Iterator<NetworkScorerAppData> result =
@@ -94,14 +95,20 @@
         assertEquals(4, next.mPackageUid);
         assertEquals(".ConfigActivity", next.mConfigurationActivityClassName);
 
+        assertTrue(result.hasNext());
+        next = result.next();
+        assertEquals("package5", next.mPackageName);
+        assertEquals(5, next.mPackageUid);
+        assertEquals(".ScoringService", next.mScoringServiceClassName);
+
         assertFalse(result.hasNext());
     }
 
-    private void setScorers(List<Pair<ResolveInfo, ResolveInfo>> scorers) {
+    private void setScorers(List<ResolveInfoHolder> scorers) {
         List<ResolveInfo> receivers = new ArrayList<>();
-        for (final Pair<ResolveInfo, ResolveInfo> scorer : scorers) {
-            receivers.add(scorer.first);
-            if (scorer.second != null) {
+        for (final ResolveInfoHolder scorer : scorers) {
+            receivers.add(scorer.scorerResolveInfo);
+            if (scorer.configActivityResolveInfo != null) {
                 // This scorer has a config activity.
                 Mockito.when(mMockPm.queryIntentActivities(
                         Mockito.argThat(new ArgumentMatcher<Intent>() {
@@ -110,10 +117,26 @@
                                 Intent intent = (Intent) object;
                                 return NetworkScoreManager.ACTION_CUSTOM_ENABLE.equals(
                                         intent.getAction())
-                                        && scorer.first.activityInfo.packageName.equals(
+                                        && scorer.scorerResolveInfo.activityInfo.packageName.equals(
                                                 intent.getPackage());
                             }
-                        }), Mockito.eq(0))).thenReturn(Collections.singletonList(scorer.second));
+                        }), Mockito.eq(0))).thenReturn(
+                                Collections.singletonList(scorer.configActivityResolveInfo));
+            }
+
+            if (scorer.serviceResolveInfo != null) {
+                // This scorer has a service to bind to
+                Mockito.when(mMockPm.resolveService(
+                        Mockito.argThat(new ArgumentMatcher<Intent>() {
+                            @Override
+                            public boolean matches(Object object) {
+                                Intent intent = (Intent) object;
+                                return NetworkScoreManager.ACTION_SCORE_NETWORKS.equals(
+                                        intent.getAction())
+                                        && scorer.scorerResolveInfo.activityInfo.packageName.equals(
+                                        intent.getPackage());
+                            }
+                        }), Mockito.eq(0))).thenReturn(scorer.serviceResolveInfo);
             }
         }
 
@@ -128,9 +151,9 @@
                 .thenReturn(receivers);
     }
 
-    private Pair<ResolveInfo, ResolveInfo> buildResolveInfo(String packageName, int packageUid,
-            boolean hasReceiverPermission, boolean hasScorePermission, boolean hasConfigActivity)
-            throws Exception {
+    private ResolveInfoHolder buildResolveInfo(String packageName, int packageUid,
+            boolean hasReceiverPermission, boolean hasScorePermission, boolean hasConfigActivity,
+            boolean hasServiceInfo) throws Exception {
         Mockito.when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
                 .thenReturn(hasScorePermission ?
                         PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
@@ -150,6 +173,27 @@
             configActivityInfo.activityInfo = new ActivityInfo();
             configActivityInfo.activityInfo.name = ".ConfigActivity";
         }
-        return Pair.create(resolveInfo, configActivityInfo);
+
+        ResolveInfo serviceInfo = null;
+        if (hasServiceInfo) {
+            serviceInfo = new ResolveInfo();
+            serviceInfo.serviceInfo = new ServiceInfo();
+            serviceInfo.serviceInfo.name = ".ScoringService";
+        }
+
+        return new ResolveInfoHolder(resolveInfo, configActivityInfo, serviceInfo);
+    }
+
+    private static class ResolveInfoHolder {
+        final ResolveInfo scorerResolveInfo;
+        final ResolveInfo configActivityResolveInfo;
+        final ResolveInfo serviceResolveInfo;
+
+        public ResolveInfoHolder(ResolveInfo scorerResolveInfo,
+                ResolveInfo configActivityResolveInfo, ResolveInfo serviceResolveInfo) {
+            this.scorerResolveInfo = scorerResolveInfo;
+            this.configActivityResolveInfo = configActivityResolveInfo;
+            this.serviceResolveInfo = serviceResolveInfo;
+        }
     }
 }
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index 43a61e3..d491ec4 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -515,7 +515,7 @@
     public void testGetPrintServices() throws Exception {
         List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
                 PrintManager.ALL_SERVICES, mUserId);
-        assertTrue(printServices.size() >= 2);
+        assertTrue(printServices.size() >= 1);
 
         printServices = mIPrintManager.getPrintServices(0, mUserId);
         assertEquals(printServices, null);
diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
index 59ffd56..eafe427 100644
--- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
+++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
@@ -16,13 +16,35 @@
 
 package android.widget;
 
-import android.app.Activity;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.Espresso.pressBack;
+import static android.support.test.espresso.action.ViewActions.clearText;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.action.ViewActions.replaceText;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static android.widget.espresso.DragHandleUtils.onHandleView;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupContainsItem;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupIsDisplayed;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupIsNotDisplayed;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.clickSuggestionsPopupItem;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.onSuggestionsPopup;
+import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
+import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
+import static org.hamcrest.Matchers.is;
 import android.content.res.TypedArray;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.ViewAssertion;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.test.suitebuilder.annotation.Suppress;
 import android.text.Selection;
-import android.text.SpannableStringBuilder;
+import android.text.Spannable;
 import android.text.Spanned;
 import android.text.TextPaint;
 import android.text.style.SuggestionSpan;
@@ -42,55 +64,215 @@
         super(TextViewActivity.class);
     }
 
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        getActivity();
+    }
+
+    private void setSuggestionSpan(SuggestionSpan span, int start, int end) {
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+        textView.post(
+                () -> {
+                    final Spannable text = (Spannable) textView.getText();
+                    text.setSpan(span, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+                    Selection.setSelection(text, (start + end) / 2);
+                });
+        getInstrumentation().waitForIdleSync();
+    }
+
     @SmallTest
-    @Suppress
+    public void testOnTextContextMenuItem() {
+        final String text = "abc def ghi";
+
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(replaceText(text));
+
+        final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+                new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+        setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+        textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE));
+        getInstrumentation().waitForIdleSync();
+
+        assertSuggestionsPopupIsDisplayed();
+    }
+
+    @SmallTest
+    public void testSelectionActionMode() {
+        final String text = "abc def ghi";
+
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(replaceText(text));
+
+        final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+                new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+        setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('e')));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarContainsItem(
+                getActivity().getString(com.android.internal.R.string.replace));
+        sleepForFloatingToolbarPopup();
+        clickFloatingToolbarItem(
+                getActivity().getString(com.android.internal.R.string.replace));
+
+        assertSuggestionsPopupIsDisplayed();
+    }
+
+    @SmallTest
+    public void testInsertionActionMode() {
+        final String text = "abc def ghi";
+
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(replaceText(text));
+
+        final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+                new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+        setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e')));
+        onHandleView(com.android.internal.R.id.insertion_handle).perform(click());
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarContainsItem(
+                getActivity().getString(com.android.internal.R.string.replace));
+        clickFloatingToolbarItem(
+                getActivity().getString(com.android.internal.R.string.replace));
+
+        assertSuggestionsPopupIsDisplayed();
+    }
+
+    private void showSuggestionsPopup() {
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+        textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE));
+        getInstrumentation().waitForIdleSync();
+        assertSuggestionsPopupIsDisplayed();
+    }
+
+    @SmallTest
+    public void testSuggestionItems() {
+        final String text = "abc def ghi";
+
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(replaceText(text));
+
+        final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+                new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+        setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+        showSuggestionsPopup();
+
+        assertSuggestionsPopupIsDisplayed();
+        assertSuggestionsPopupContainsItem("DEF");
+        assertSuggestionsPopupContainsItem("Def");
+        assertSuggestionsPopupContainsItem(
+                getActivity().getString(com.android.internal.R.string.delete));
+
+        // Select an item.
+        clickSuggestionsPopupItem("DEF");
+        assertSuggestionsPopupIsNotDisplayed();
+        onView(withId(R.id.textview)).check(matches(withText("abc DEF ghi")));
+
+        showSuggestionsPopup();
+        assertSuggestionsPopupIsDisplayed();
+        assertSuggestionsPopupContainsItem("def");
+        assertSuggestionsPopupContainsItem("Def");
+        assertSuggestionsPopupContainsItem(
+                getActivity().getString(com.android.internal.R.string.delete));
+
+        // Delete
+        clickSuggestionsPopupItem(
+                getActivity().getString(com.android.internal.R.string.delete));
+        assertSuggestionsPopupIsNotDisplayed();
+        onView(withId(R.id.textview)).check(matches(withText("abc ghi")));
+    }
+
+    @SmallTest
+    public void testMisspelled() {
+        final String text = "abc def ghi";
+
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(replaceText(text));
+
+        final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+                new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_MISSPELLED);
+        setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+        showSuggestionsPopup();
+
+        assertSuggestionsPopupIsDisplayed();
+        assertSuggestionsPopupContainsItem("DEF");
+        assertSuggestionsPopupContainsItem("Def");
+        assertSuggestionsPopupContainsItem(
+                getActivity().getString(com.android.internal.R.string.addToDictionary));
+        assertSuggestionsPopupContainsItem(
+                getActivity().getString(com.android.internal.R.string.delete));
+
+        // Click "Add to dictionary".
+        clickSuggestionsPopupItem(
+                getActivity().getString(com.android.internal.R.string.addToDictionary));
+        // TODO: Check if add to dictionary dialog is displayed.
+    }
+
+    @SmallTest
+    public void testEasyCorrect() {
+        final String text = "abc def ghi";
+
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(replaceText(text));
+
+        final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+                new String[]{"DEF", "Def"},
+                SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED);
+        setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e')));
+
+        assertSuggestionsPopupIsDisplayed();
+        assertSuggestionsPopupContainsItem("DEF");
+        assertSuggestionsPopupContainsItem("Def");
+        assertSuggestionsPopupContainsItem(
+                getActivity().getString(com.android.internal.R.string.delete));
+
+        // Select an item.
+        clickSuggestionsPopupItem("DEF");
+        assertSuggestionsPopupIsNotDisplayed();
+        onView(withId(R.id.textview)).check(matches(withText("abc DEF ghi")));
+
+        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e')));
+        assertSuggestionsPopupIsNotDisplayed();
+
+        showSuggestionsPopup();
+        assertSuggestionsPopupIsDisplayed();
+        assertSuggestionsPopupContainsItem("def");
+        assertSuggestionsPopupContainsItem("Def");
+        assertSuggestionsPopupContainsItem(
+                getActivity().getString(com.android.internal.R.string.delete));
+    }
+
+    @SmallTest
     public void testTextAppearanceInSuggestionsPopup() {
-        final Activity activity = getActivity();
+        final String text = "abc def ghi";
 
-        final String sampleText = "abc def ghi";
         final String[] singleWordCandidates = {"DEF", "Def"};
-        final SuggestionSpan singleWordSuggestionSpan = new SuggestionSpan(activity,
-                singleWordCandidates, SuggestionSpan.FLAG_AUTO_CORRECTION);
-        final int singleWordSpanStart = 4;
-        final int singleWordSpanEnd = 7;
-
+        final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+                singleWordCandidates, SuggestionSpan.FLAG_MISSPELLED);
         final String[] multiWordCandidates = {"ABC DEF GHI", "Abc Def Ghi"};
-        final SuggestionSpan multiWordSuggestionSpan = new SuggestionSpan(activity,
-                multiWordCandidates, SuggestionSpan.FLAG_AUTO_CORRECTION);
-        final int multiWordSpanStart = 0;
-        final int multiWordSpanEnd = 11;
+        final SuggestionSpan multiWordSuggestionSpan = new SuggestionSpan(getActivity(),
+                multiWordCandidates, SuggestionSpan.FLAG_MISSPELLED);
 
-        TypedArray array = activity.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
-        int id = array.getResourceId(
+        final TypedArray array =
+                getActivity().obtainStyledAttributes(com.android.internal.R.styleable.Theme);
+        final int id = array.getResourceId(
                 com.android.internal.R.styleable.Theme_textEditSuggestionHighlightStyle, 0);
         array.recycle();
-
-        TextAppearanceSpan expectedSpan = new TextAppearanceSpan(activity, id);
-        TextPaint tmpTp = new TextPaint();
+        final TextAppearanceSpan expectedSpan = new TextAppearanceSpan(getActivity(), id);
+        final TextPaint tmpTp = new TextPaint();
         expectedSpan.updateDrawState(tmpTp);
         final int expectedHighlightTextColor = tmpTp.getColor();
         final float expectedHighlightTextSize = tmpTp.getTextSize();
-
-        final EditText editText = (EditText) activity.findViewById(R.id.textview);
-        final Editor editor = editText.getEditorForTesting();
-        assertNotNull(editor);
-
-        // Request to show SuggestionsPopupWindow.
-        Runnable showSuggestionWindowRunner = new Runnable() {
-            @Override
-            public void run() {
-                SpannableStringBuilder ssb = new SpannableStringBuilder();
-                ssb.append(sampleText);
-                ssb.setSpan(singleWordSuggestionSpan, singleWordSpanStart, singleWordSpanEnd,
-                        Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-                ssb.setSpan(multiWordSuggestionSpan, multiWordSpanStart, multiWordSpanEnd,
-                        Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-                editText.setText(ssb);
-
-                Selection.setSelection(editText.getText(), singleWordSpanStart, singleWordSpanEnd);
-                editText.onTextContextMenuItem(TextView.ID_REPLACE);
-            }
-        };
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
 
         // In this test, the SuggestionsPopupWindow looks like
         //   abc def ghi
@@ -103,96 +285,74 @@
         // | DELETE        |
         // -----------------
         // *XX* means that XX is highlighted.
-        Runnable popupVaridator = new Runnable() {
-            @Override
-            public void run() {
-                Editor.SuggestionsPopupWindow popupWindow =
-                        editor.getSuggestionsPopupWindowForTesting();
-                assertNotNull(popupWindow);
+        for (int i = 0; i < 2; i++) {
+            onView(withId(R.id.textview)).perform(click());
+            onView(withId(R.id.textview)).perform(replaceText(text));
+            setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+            setSuggestionSpan(multiWordSuggestionSpan, 0, text.length());
 
-                LinearLayout linearLayout = (LinearLayout) popupWindow.getContentViewForTesting();
-                assertNotNull(linearLayout);
+            showSuggestionsPopup();
+            assertSuggestionsPopupIsDisplayed();
+            assertSuggestionsPopupContainsItem("abc DEF ghi");
+            assertSuggestionsPopupContainsItem("abc Def ghi");
+            assertSuggestionsPopupContainsItem("ABC DEF GHI");
+            assertSuggestionsPopupContainsItem("Abc Def Ghi");
+            assertSuggestionsPopupContainsItem(
+                    getActivity().getString(com.android.internal.R.string.delete));
 
-                ListView listView = (ListView)linearLayout.findViewById(
-                        com.android.internal.R.id.suggestionContainer);
-                assertNotNull(listView);
+            onSuggestionsPopup().check(new ViewAssertion() {
+                @Override
+                public void check(View view, NoMatchingViewException e) {
+                    final ListView listView = (ListView) view.findViewById(
+                            com.android.internal.R.id.suggestionContainer);
+                    assertNotNull(listView);
+                    final int childNum = listView.getChildCount();
+                    assertEquals(singleWordCandidates.length + multiWordCandidates.length,
+                            childNum);
 
-                int childNum = listView.getChildCount();
-                assertEquals(singleWordCandidates.length + multiWordCandidates.length, childNum);
+                    for (int j = 0; j < childNum; j++) {
+                        final TextView suggestion = (TextView) listView.getChildAt(j);
+                        assertNotNull(suggestion);
+                        final Spanned spanned = (Spanned) suggestion.getText();
+                        assertNotNull(spanned);
 
-                for (int i = 0; i < singleWordCandidates.length; ++i) {
-                    TextView textView = (TextView) listView.getChildAt(i);
-                    assertNotNull(textView);
+                        // Check that the suggestion item order is kept.
+                        final String expectedText;
+                        if (j < singleWordCandidates.length) {
+                            expectedText = "abc " + singleWordCandidates[j] + " ghi";
+                        } else {
+                            expectedText = multiWordCandidates[j - singleWordCandidates.length];
+                        }
+                        assertEquals(expectedText, spanned.toString());
 
-                    Spanned spanned = (Spanned) textView.getText();
-                    assertNotNull(spanned);
+                        // Check that the text is highlighted with correct color and text size.
+                        final TextAppearanceSpan[] taSpan = spanned.getSpans(
+                                text.indexOf('d'), text.indexOf('f') + 1, TextAppearanceSpan.class);
+                        assertEquals(1, taSpan.length);
+                        TextPaint tp = new TextPaint();
+                        taSpan[0].updateDrawState(tp);
+                        assertEquals(expectedHighlightTextColor, tp.getColor());
+                        assertEquals(expectedHighlightTextSize, tp.getTextSize());
 
-                    // Check that the suggestion item order is kept.
-                    String expectedText = "abc " + singleWordCandidates[i] + " ghi";
-                    assertEquals(expectedText, spanned.toString());
-
-                    // Check that the text is highlighted with correct color and text size.
-                    TextAppearanceSpan[] taSpan = spanned.getSpans(singleWordSpanStart,
-                            singleWordSpanEnd, TextAppearanceSpan.class);
-                    assertEquals(1, taSpan.length);
-                    TextPaint tp = new TextPaint();
-                    taSpan[0].updateDrawState(tp);
-                    assertEquals(expectedHighlightTextColor, tp.getColor());
-                    assertEquals(expectedHighlightTextSize, tp.getTextSize());
-
-                    // Check only center word is highlighted.
-                    assertEquals(singleWordSpanStart, spanned.getSpanStart(taSpan[0]));
-                    assertEquals(singleWordSpanEnd, spanned.getSpanEnd(taSpan[0]));
+                        // Check the correct part of the text is highlighted.
+                        final int expectedStart;
+                        final int expectedEnd;
+                        if (j < singleWordCandidates.length) {
+                            expectedStart = text.indexOf('d');
+                            expectedEnd = text.indexOf('f') + 1;
+                        } else {
+                            expectedStart = 0;
+                            expectedEnd = text.length();
+                        }
+                        assertEquals(expectedStart, spanned.getSpanStart(taSpan[0]));
+                        assertEquals(expectedEnd, spanned.getSpanEnd(taSpan[0]));
+                    }
                 }
-
-                for (int i = 0; i < multiWordCandidates.length; ++i) {
-                    int indexInListView = singleWordCandidates.length + i;
-                    TextView textView = (TextView) listView.getChildAt(indexInListView);
-                    assertNotNull(textView);
-
-                    Spanned spanned = (Spanned) textView.getText();
-                    assertNotNull(spanned);
-
-                    // Check that the suggestion item order is kept.
-                    assertEquals(multiWordCandidates[i], spanned.toString());
-
-                    // Check that the text is highlighted with correct color and text size.
-                    TextAppearanceSpan[] taSpan = spanned.getSpans(
-                            0, multiWordCandidates[i].length(), TextAppearanceSpan.class);
-                    assertEquals(1, taSpan.length);
-                    TextPaint tp = new TextPaint();
-                    taSpan[0].updateDrawState(tp);
-                    assertEquals(expectedHighlightTextColor, tp.getColor());
-                    assertEquals(expectedHighlightTextSize, tp.getTextSize());
-
-                    // Check the whole text is highlighted.
-                    assertEquals(multiWordSpanStart, spanned.getSpanStart(taSpan[0]));
-                    assertEquals(multiWordSpanEnd, spanned.getSpanEnd(taSpan[0]));
-                }
-
-                TextView deleteButton = (TextView)linearLayout.findViewById(
-                        com.android.internal.R.id.deleteButton);
-                assertEquals(View.VISIBLE, deleteButton.getWindowVisibility());
-            }
-        };
-
-        // Show the SuggestionWindow and verify the contents.
-        activity.runOnUiThread(showSuggestionWindowRunner);
-        getInstrumentation().waitForIdleSync();
-        activity.runOnUiThread(popupVaridator);
-
-        // Request to hide the SuggestionPopupWindow and wait until it is hidden.
-        activity.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                editText.setText("");
-            }
-        });
-        getInstrumentation().waitForIdleSync();
-
-        // Show and verify the contents again.
-        activity.runOnUiThread(showSuggestionWindowRunner);
-        getInstrumentation().waitForIdleSync();
-        activity.runOnUiThread(popupVaridator);
+            });
+            pressBack();
+            onView(withId(R.id.textview))
+                    .inRoot(withDecorView(is(getActivity().getWindow().getDecorView())))
+                    .perform(clearText());
+        }
     }
 }
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
index 923b829..edb749b95 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -16,6 +16,10 @@
 
 package android.widget;
 
+
+import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemDisabled;
+import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemEnabled;
+import static android.widget.espresso.ContextMenuUtils.assertContextMenuIsNotDisplayed;
 import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
 import static android.widget.espresso.DragHandleUtils.onHandleView;
 import static android.widget.espresso.TextViewActions.mouseClickOnTextAtIndex;
@@ -41,11 +45,9 @@
 
 import com.android.frameworks.coretests.R;
 
-import android.support.test.espresso.Espresso;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.MotionEvent;
-import android.widget.espresso.ContextMenuUtils;
 
 /**
  * Tests mouse interaction of the TextView widget from an Activity
@@ -57,7 +59,8 @@
     }
 
     @Override
-    public void setUp() {
+    public void setUp() throws Exception {
+        super.setUp();
         getActivity();
     }
 
@@ -102,28 +105,28 @@
         onView(withId(R.id.textview)).perform(click());
         onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text));
 
-        ContextMenuUtils.assertContextMenuIsNotDisplayed();
+        assertContextMenuIsNotDisplayed();
 
         onView(withId(R.id.textview)).perform(
                 mouseClickOnTextAtIndex(text.indexOf("d"), MotionEvent.BUTTON_SECONDARY));
 
-        ContextMenuUtils.assertContextMenuContainsItemDisabled(
+        assertContextMenuContainsItemDisabled(
                 getActivity().getString(com.android.internal.R.string.copy));
-        ContextMenuUtils.assertContextMenuContainsItemEnabled(
+        assertContextMenuContainsItemEnabled(
                 getActivity().getString(com.android.internal.R.string.undo));
 
         // Hide context menu.
         pressBack();
-        ContextMenuUtils.assertContextMenuIsNotDisplayed();
+        assertContextMenuIsNotDisplayed();
 
         onView(withId(R.id.textview)).perform(
                 mouseDragOnText(text.indexOf("c"), text.indexOf("h")));
         onView(withId(R.id.textview)).perform(
                 mouseClickOnTextAtIndex(text.indexOf("d"), MotionEvent.BUTTON_SECONDARY));
 
-        ContextMenuUtils.assertContextMenuContainsItemEnabled(
+        assertContextMenuContainsItemEnabled(
                 getActivity().getString(com.android.internal.R.string.copy));
-        ContextMenuUtils.assertContextMenuContainsItemEnabled(
+        assertContextMenuContainsItemEnabled(
                 getActivity().getString(com.android.internal.R.string.undo));
 
         // Hide context menu.
@@ -133,9 +136,9 @@
 
         onView(withId(R.id.textview)).perform(
                 mouseClickOnTextAtIndex(text.indexOf("i"), MotionEvent.BUTTON_SECONDARY));
-        ContextMenuUtils.assertContextMenuContainsItemDisabled(
+        assertContextMenuContainsItemDisabled(
                 getActivity().getString(com.android.internal.R.string.copy));
-        ContextMenuUtils.assertContextMenuContainsItemEnabled(
+        assertContextMenuContainsItemEnabled(
                 getActivity().getString(com.android.internal.R.string.undo));
 
         // Hide context menu.
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index f779d6c..67ffd2b 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -19,7 +19,6 @@
 import static android.support.test.espresso.action.ViewActions.longClick;
 import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
 import static android.widget.espresso.DragHandleUtils.onHandleView;
-import static android.widget.espresso.FloatingToolbarEspressoUtils.onFloatingToolBarItem;
 import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
 import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText;
 import static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex;
@@ -31,9 +30,10 @@
 import static android.widget.espresso.TextViewAssertions.hasSelection;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed;
-import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup;
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.action.ViewActions.click;
 import static android.support.test.espresso.action.ViewActions.pressKey;
@@ -67,7 +67,8 @@
     }
 
     @Override
-    public void setUp() {
+    public void setUp() throws Exception {
+        super.setUp();
         getActivity();
     }
 
@@ -256,7 +257,8 @@
 
         onView(withId(R.id.textview)).perform(typeTextIntoFocusedView("test"));
         onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(1));
-        onFloatingToolBarItem(withText(com.android.internal.R.string.cut)).perform(click());
+        clickFloatingToolbarItem(
+                getActivity().getString(com.android.internal.R.string.cut));
         onView(withId(R.id.textview)).perform(longClick());
         sleepForFloatingToolbarPopup();
 
@@ -675,4 +677,26 @@
         assertFloatingToolbarContainsItem(
                 getActivity().getString(com.android.internal.R.string.copy));
     }
+
+    @SmallTest
+    public void testTransientState() throws Exception {
+        final String text = "abc def";
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(replaceText(text));
+
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+        assertFalse(textView.hasTransientState());
+
+        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('b')));
+        // hasTransientState should return true when user generated selection is active.
+        assertTrue(textView.hasTransientState());
+        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('d')));
+        // hasTransientState should return false as the selection has been cleared.
+        assertFalse(textView.hasTransientState());
+        textView.post(
+                () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length()));
+        getInstrumentation().waitForIdleSync();
+        // hasTransientState should return false when selection is created by API.
+        assertFalse(textView.hasTransientState());
+    }
 }
diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
index 0f7f359..838f4db 100644
--- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
+++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
@@ -17,6 +17,7 @@
 package android.widget.espresso;
 
 import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
 import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
 import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
@@ -24,6 +25,7 @@
 import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
 import static android.support.test.espresso.matcher.ViewMatchers.withTagValue;
 import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
 import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.is;
 
@@ -34,8 +36,6 @@
 import android.support.test.espresso.UiController;
 import android.support.test.espresso.ViewAction;
 import android.support.test.espresso.ViewInteraction;
-import android.support.test.espresso.action.ViewActions;
-import android.support.test.espresso.matcher.ViewMatchers;
 import android.view.View;
 
 import com.android.internal.widget.FloatingToolbar;
@@ -90,7 +90,7 @@
         final int id = com.android.internal.R.id.overflow;
         onView(allOf(withId(id), isDisplayed()))
                 .inRoot(withDecorView(hasDescendant(withId(id))))
-                .perform(ViewActions.click());
+                .perform(click());
         onView(isRoot()).perform(SLEEP);
     }
 
@@ -106,7 +106,7 @@
      */
     public static void assertFloatingToolbarContainsItem(String itemLabel) {
         try{
-            onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel))));
+            onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel))));
         } catch (AssertionError e) {
             try{
                 toggleOverflow();
@@ -115,7 +115,7 @@
                 throw e;
             }
             try{
-                onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel))));
+                onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel))));
             } finally {
                 toggleOverflow();
             }
@@ -138,6 +138,21 @@
     }
 
     /**
+     * Click specified item on the floating tool bar.
+     *
+     * @param itemLabel label of the item.
+     */
+    public static void clickFloatingToolbarItem(String itemLabel) {
+        try{
+            onFloatingToolBarItem(withText(itemLabel)).check(matches(isDisplayed()));
+        } catch (AssertionError e) {
+            // Try to find the item in the overflow menu.
+            toggleOverflow();
+        }
+        onFloatingToolBarItem(withText(itemLabel)).perform(click());
+    }
+
+    /**
      * ViewAction to sleep to wait floating toolbar's animation.
      */
     private static final ViewAction SLEEP = new ViewAction() {
diff --git a/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java b/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java
index b8ea2de..bec4180 100644
--- a/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java
+++ b/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java
@@ -21,7 +21,6 @@
 import android.support.test.espresso.UiController;
 import android.support.test.espresso.ViewAction;
 import android.support.test.espresso.action.CoordinatesProvider;
-import android.support.test.espresso.action.GeneralClickAction;
 import android.support.test.espresso.action.MotionEvents;
 import android.support.test.espresso.action.MotionEvents.DownResultHolder;
 import android.support.test.espresso.action.Press;
@@ -34,7 +33,7 @@
  * ViewAction for performing an click on View by a mouse.
  */
 public final class MouseClickAction implements ViewAction {
-    private final GeneralClickAction mGeneralClickAction;
+    private final ViewClickAction mViewClickAction;
     @MouseUiController.MouseButton
     private final int mButton;
 
@@ -100,30 +99,22 @@
      */
     public MouseClickAction(Tapper tapper, CoordinatesProvider coordinatesProvider,
             @MouseUiController.MouseButton int button) {
-        mGeneralClickAction = new GeneralClickAction(tapper, coordinatesProvider, Press.PINPOINT);
+        mViewClickAction = new ViewClickAction(tapper, coordinatesProvider, Press.PINPOINT);
         mButton = button;
     }
 
     @Override
     public Matcher<View> getConstraints() {
-        return mGeneralClickAction.getConstraints();
+        return mViewClickAction.getConstraints();
     }
 
     @Override
     public String getDescription() {
-        return mGeneralClickAction.getDescription();
+        return mViewClickAction.getDescription();
     }
 
     @Override
     public void perform(UiController uiController, View view) {
-        mGeneralClickAction.perform(new MouseUiController(uiController, mButton), view);
-        long doubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
-        if (0 < doubleTapTimeout) {
-            // Wait to avoid false gesture detection. Without this wait, consecutive clicks can be
-            // detected as a triple click. e.g. 2 double clicks are detected as a triple click and
-            // a single click because espresso isn't aware of triple click detection logic, which
-            // is TextView specific gesture.
-            uiController.loopMainThreadForAtLeast(doubleTapTimeout);
-        }
+        mViewClickAction.perform(new MouseUiController(uiController, mButton), view);
     }
 }
diff --git a/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java
new file mode 100644
index 0000000..b5a96ae
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.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.widget.espresso;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
+import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import org.hamcrest.Matcher;
+
+import android.support.test.espresso.NoMatchingRootException;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.ViewInteraction;
+import android.support.test.espresso.action.GeneralLocation;
+import android.support.test.espresso.action.Press;
+import android.support.test.espresso.action.Tap;
+import android.view.View;
+
+public final class SuggestionsPopupwindowUtils {
+    private static final int id = com.android.internal.R.id.suggestionWindowContainer;
+
+    private SuggestionsPopupwindowUtils() {};
+
+    public static ViewInteraction onSuggestionsPopup() {
+        return onView(withId(id)).inRoot(withDecorView(hasDescendant(withId(id))));
+    }
+
+    private static ViewInteraction onSuggestionsPopupItem(Matcher<View> matcher) {
+        return onView(matcher).inRoot(withDecorView(hasDescendant(withId(id))));
+    }
+
+    /**
+     * Asserts that the suggestions popup is displayed on screen.
+     *
+     * @throws AssertionError if the assertion fails
+     */
+    public static void assertSuggestionsPopupIsDisplayed() {
+        onSuggestionsPopup().check(matches(isDisplayed()));
+    }
+
+    /**
+     * Asserts that the suggestions popup is not displayed on screen.
+     *
+     * @throws AssertionError if the assertion fails
+     */
+    public static void assertSuggestionsPopupIsNotDisplayed() {
+        try {
+            onSuggestionsPopup().check(matches(isDisplayed()));
+        } catch (NoMatchingRootException | NoMatchingViewException | AssertionError e) {
+            return;
+        }
+        throw new AssertionError("Suggestions popup is displayed");
+    }
+
+    /**
+     * Asserts that the suggestions popup contains the specified item.
+     *
+     * @param itemLabel label of the item.
+     * @throws AssertionError if the assertion fails
+     */
+    public static void assertSuggestionsPopupContainsItem(String itemLabel) {
+        onSuggestionsPopupItem(withText(itemLabel)).check(matches(isDisplayed()));
+    }
+
+    /**
+     * Click on the specified item in the suggestions popup.
+     *
+     * @param itemLabel label of the item.
+     */
+    public static void clickSuggestionsPopupItem(String itemLabel) {
+        onSuggestionsPopupItem(withText(itemLabel)).perform(new SuggestionItemClickAction());
+    }
+
+    /**
+     * Click action to avoid checking ViewClickAction#getConstraints().
+     * TODO: Use Espresso.onData instead of this.
+     */
+    private static final class SuggestionItemClickAction implements ViewAction {
+        private final ViewClickAction mViewClickAction;
+
+        public SuggestionItemClickAction() {
+            mViewClickAction =
+                    new ViewClickAction(Tap.SINGLE, GeneralLocation.VISIBLE_CENTER, Press.FINGER);
+        }
+
+        @Override
+        public Matcher<View> getConstraints() {
+            return isDisplayed();
+        }
+
+        @Override
+        public String getDescription() {
+            return mViewClickAction.getDescription();
+        }
+
+        @Override
+        public void perform(UiController uiController, View view) {
+            mViewClickAction.perform(uiController, view);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
index 4cecb65..335d021 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
@@ -17,15 +17,10 @@
 package android.widget.espresso;
 
 import static android.support.test.espresso.action.ViewActions.actionWithAssertions;
-
-import org.hamcrest.core.Is;
-import org.hamcrest.core.IsInstanceOf;
-
 import android.graphics.Rect;
 import android.support.test.espresso.PerformException;
 import android.support.test.espresso.ViewAction;
 import android.support.test.espresso.action.CoordinatesProvider;
-import android.support.test.espresso.action.GeneralClickAction;
 import android.support.test.espresso.action.Press;
 import android.support.test.espresso.action.Tap;
 import android.support.test.espresso.util.HumanReadables;
@@ -55,7 +50,7 @@
      */
     public static ViewAction clickOnTextAtIndex(int index) {
         return actionWithAssertions(
-                new GeneralClickAction(Tap.SINGLE, new TextCoordinates(index), Press.FINGER));
+                new ViewClickAction(Tap.SINGLE, new TextCoordinates(index), Press.FINGER));
     }
 
     /**
@@ -101,7 +96,7 @@
      */
     public static ViewAction doubleClickOnTextAtIndex(int index) {
         return actionWithAssertions(
-                new GeneralClickAction(Tap.DOUBLE, new TextCoordinates(index), Press.FINGER));
+                new ViewClickAction(Tap.DOUBLE, new TextCoordinates(index), Press.FINGER));
     }
 
     /**
@@ -131,7 +126,7 @@
      */
     public static ViewAction longPressOnTextAtIndex(int index) {
         return actionWithAssertions(
-                new GeneralClickAction(Tap.LONG, new TextCoordinates(index), Press.FINGER));
+                new ViewClickAction(Tap.LONG, new TextCoordinates(index), Press.FINGER));
     }
 
     /**
diff --git a/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java b/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java
new file mode 100644
index 0000000..8bce1b0
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/espresso/ViewClickAction.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.espresso;
+
+import org.hamcrest.Matcher;
+
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.action.CoordinatesProvider;
+import android.support.test.espresso.action.GeneralClickAction;
+import android.support.test.espresso.action.PrecisionDescriber;
+import android.support.test.espresso.action.Tapper;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+public final class ViewClickAction implements ViewAction {
+    private final GeneralClickAction mGeneralClickAction;
+
+    public ViewClickAction(Tapper tapper, CoordinatesProvider coordinatesProvider,
+            PrecisionDescriber precisionDescriber) {
+        mGeneralClickAction = new GeneralClickAction(tapper, coordinatesProvider,
+                precisionDescriber);
+    }
+
+    @Override
+    public Matcher<View> getConstraints() {
+        return mGeneralClickAction.getConstraints();
+    }
+
+    @Override
+    public String getDescription() {
+        return mGeneralClickAction.getDescription();
+    }
+
+    @Override
+    public void perform(UiController uiController, View view) {
+        mGeneralClickAction.perform(uiController, view);
+        long doubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
+        if (0 < doubleTapTimeout) {
+            // Wait to avoid false gesture detection. Without this wait, consecutive clicks can be
+            // detected as a double click or triple click. e.g. 2 double clicks on TextView are
+            // detected as a triple click and a single click because espresso isn't aware of
+            // TextView specific gestures.
+            uiController.loopMainThreadForAtLeast(doubleTapTimeout);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
index 7519627..2a24881 100644
--- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
@@ -22,7 +22,6 @@
 import android.view.ActionMode;
 import android.view.ActionMode.Callback;
 import android.view.KeyEvent;
-import android.view.KeyboardShortcutGroup;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
diff --git a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
index 5f36c2d..3cef336 100644
--- a/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/FastXmlSerializerTest.java
@@ -16,16 +16,32 @@
 
 package com.android.internal.util;
 
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import android.util.Xml;
+
 import junit.framework.TestCase;
 
+import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
 
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
 
 /**
  * Tests for {@link FastXmlSerializer}
  */
+@SmallTest
 public class FastXmlSerializerTest extends TestCase {
+    private static final String TAG = "FastXmlSerializerTest";
+
+    private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH TRUE.
+
+    private static final String ROOT_TAG = "root";
+    private static final String ATTR = "attr";
+
     public void testEmptyText() throws Exception {
         final ByteArrayOutputStream stream = new ByteArrayOutputStream();
 
@@ -44,4 +60,93 @@
         assertEquals("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
                 + "<string name=\"meow\"></string>\n", stream.toString());
     }
+
+    private boolean checkPreserved(String description, String str) {
+        boolean ok = true;
+        byte[] data;
+        try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            final XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(baos, StandardCharsets.UTF_16.name());
+            out.startDocument(null, true);
+
+            out.startTag(null, ROOT_TAG);
+            out.attribute(null, ATTR, str);
+            out.text(str);
+            out.endTag(null, ROOT_TAG);
+
+            out.endDocument();
+            baos.flush();
+            data = baos.toByteArray();
+        } catch (Exception e) {
+            Log.e(TAG, "Unable to serialize: " + description, e);
+            return false;
+        }
+
+        if (ENABLE_DUMP) {
+            Log.d(TAG, "Dump:");
+            Log.d(TAG, new String(data));
+        }
+
+        try (final ByteArrayInputStream baos = new ByteArrayInputStream(data)) {
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(baos, StandardCharsets.UTF_16.name());
+
+            int type;
+            String tag = null;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                if (type == XmlPullParser.START_TAG) {
+                    tag = parser.getName();
+                    if (ROOT_TAG.equals(tag)) {
+                        String read = parser.getAttributeValue(null, ATTR);
+                        if (!str.equals(read)) {
+                            Log.e(TAG, "Attribute not preserved: " + description
+                                    + " input=\"" + str + "\", but read=\"" + read + "\"");
+                            ok = false;
+                        }
+                    }
+                }
+                if (type == XmlPullParser.TEXT && ROOT_TAG.equals(tag)) {
+                    String read = parser.getText();
+                    if (!str.equals(parser.getText())) {
+                        Log.e(TAG, "Text not preserved: " + description
+                                + " input=\"" + str + "\", but read=\"" + read + "\"");
+                        ok = false;
+                    }
+                }
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Unable to parse: " + description, e);
+            return false;
+        }
+        return ok;
+    }
+
+    private boolean check(String description, String str) throws Exception {
+        boolean ok = false;
+        ok |= checkPreserved(description, str);
+        ok |= checkPreserved(description + " wrapped with spaces" ,"  " + str + "  ");
+        return ok;
+    }
+
+    @LargeTest
+    public void testAllCharacters() throws Exception {
+        boolean ok = true;
+        for (int i = 0; i < 0xffff; i++) {
+            if (0xd800 <= i && i <= 0xdfff) {
+                // Surrogate pair characters.
+                continue;
+            }
+            ok &= check("char: " + i, String.valueOf((char) i));
+        }
+        // Dangling surrogate pairs. We can't preserve them.
+        assertFalse(check("+ud800", "\ud800"));
+        assertFalse(check("+udc00", "\udc00"));
+
+        for (int i = 0xd800; i < 0xdc00; i ++) {
+            for (int j = 0xdc00; j < 0xe000; j++) {
+                ok &= check("char: " + i, String.valueOf((char) i) + String.valueOf((char) j));
+            }
+        }
+        assertTrue("Some tests failed.  See logcat for details.", ok);
+    }
 }
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index e3639ec..f4c5b53 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -108,6 +108,6 @@
 endif
 
 .PHONY: fontchain_lint
-fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml
+fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml $(PRODUCT_OUT)/system.img
 	PYTHONPATH=$$PYTHONPATH:external/fonttools/Lib \
 	python $(FONTCHAIN_LINTER) $(TARGET_OUT) $(CHECK_EMOJI) external/unicode
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 3973f2f..aa81b91 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -37,22 +37,26 @@
 public final class Outline {
     private static final float RADIUS_UNDEFINED = Float.NEGATIVE_INFINITY;
 
-    private static final int MODE_EMPTY = 0;
-    private static final int MODE_RECT = 1;
-    private static final int MODE_CONVEX_PATH = 2;
+    /** @hide */
+    public static final int MODE_EMPTY = 0;
+    /** @hide */
+    public static final int MODE_ROUND_RECT = 1;
+    /** @hide */
+    public static final int MODE_CONVEX_PATH = 2;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = false,
             value = {
                     MODE_EMPTY,
-                    MODE_RECT,
+                    MODE_ROUND_RECT,
                     MODE_CONVEX_PATH,
             })
     public @interface Mode {}
 
+    /** @hide */
     @Mode
-    private int mMode = MODE_EMPTY;
+    public int mMode = MODE_EMPTY;
 
     /** @hide */
     public final Path mPath = new Path();
@@ -176,7 +180,7 @@
             return;
         }
 
-        mMode = MODE_RECT;
+        mMode = MODE_ROUND_RECT;
         mRect.set(left, top, right, bottom);
         mRadius = radius;
         mPath.rewind();
@@ -199,7 +203,7 @@
      *         bounds, or {@code false} if no outline bounds are set
      */
     public boolean getRect(@NonNull Rect outRect) {
-        if (mMode != MODE_RECT) {
+        if (mMode != MODE_ROUND_RECT) {
             return false;
         }
         outRect.set(mRect);
@@ -270,7 +274,7 @@
      * Offsets the Outline by (dx,dy)
      */
     public void offset(int dx, int dy) {
-        if (mMode == MODE_RECT) {
+        if (mMode == MODE_ROUND_RECT) {
             mRect.offset(dx, dy);
         } else if (mMode == MODE_CONVEX_PATH) {
             mPath.offset(dx, dy);
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 46a0f43..35385eb 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -1416,6 +1416,9 @@
                 Log.d(LOGTAG, "on finished called from native");
             }
             mStarted = false;
+            // Invalidate in the end of the animation to make sure the data in
+            // RT thread is synced back to UI thread.
+            invalidateOwningView();
             if (mListener != null) {
                 mListener.onAnimationEnd(null);
             }
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index f43bf86..5fb8425 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -809,10 +809,6 @@
                         Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
                 .build();
         renderer.renderGlop(state, glop);
-
-        if (op.destroy) {
-            renderer.renderState().layerPool().putOrDelete(buffer);
-        }
     }
 }
 
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 20f102b..3c302b3 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -37,6 +37,10 @@
     return buffer;
 }
 
+void BakedOpRenderer::recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) {
+    mRenderState.layerPool().putOrDelete(offscreenBuffer);
+}
+
 void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) {
     LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
 
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 1b4065a..62bc564 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -69,6 +69,7 @@
     void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect);
     void endFrame(const Rect& repaintRect);
     WARN_UNUSED_RESULT OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height);
+    void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer);
     void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect);
     void endLayer();
     WARN_UNUSED_RESULT OffscreenBuffer* copyToLayer(const Rect& area);
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 59f0d7c..181b343 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -45,6 +45,7 @@
         , regions(stdAllocator)
         , referenceHolders(stdAllocator)
         , functors(stdAllocator)
+        , pushStagingFunctors(stdAllocator)
         , hasDrawOps(false) {
 }
 
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 60cc7ba..e209e2a 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -110,6 +110,16 @@
 };
 
 /**
+ * Functor that can be used for objects with data in both UI thread and RT to keep the data
+ * in sync. This functor, when added to DisplayList, will be call during DisplayList sync.
+ */
+struct PushStagingFunctor {
+    PushStagingFunctor() {}
+    virtual ~PushStagingFunctor() {}
+    virtual void operator ()() {}
+};
+
+/**
  * Data structure that holds the list of commands used in display list stream
  */
 class DisplayList {
@@ -142,6 +152,7 @@
 
     const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
     const LsaVector<Functor*>& getFunctors() const { return functors; }
+    const LsaVector<PushStagingFunctor*>& getPushStagingFunctors() { return pushStagingFunctors; }
 
     size_t addChild(NodeOpType* childOp);
 
@@ -183,6 +194,11 @@
     // List of functors
     LsaVector<Functor*> functors;
 
+    // List of functors that need to be notified of pushStaging. Note that this list gets nothing
+    // but a callback during sync DisplayList, unlike the list of functors defined above, which
+    // gets special treatment exclusive for webview.
+    LsaVector<PushStagingFunctor*> pushStagingFunctors;
+
     bool hasDrawOps; // only used if !HWUI_NEW_OPS
 
     void cleanupResources();
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 2dccf32..c6e92ab 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -415,7 +415,8 @@
 
 void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
     mDisplayList->ref(tree);
-    addDrawOp(new (alloc()) DrawVectorDrawableOp(tree));
+    mDisplayList->pushStagingFunctors.push_back(tree->getFunctor());
+    addDrawOp(new (alloc()) DrawVectorDrawableOp(tree, tree->stagingProperties()->getBounds()));
 }
 
 void DisplayListCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int count,
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 516e619..59f073f 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1110,15 +1110,14 @@
 
 class DrawVectorDrawableOp : public DrawOp {
 public:
-    DrawVectorDrawableOp(VectorDrawableRoot* tree)
-            : DrawOp(nullptr), mTree(tree) {}
+    DrawVectorDrawableOp(VectorDrawableRoot* tree, const SkRect& bounds)
+            : DrawOp(nullptr), mTree(tree), mDst(bounds) {}
 
     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);
+                mDst, paint);
     }
 
     virtual void output(int level, uint32_t logFlags) const override {
@@ -1129,6 +1128,7 @@
 
 private:
     VectorDrawableRoot* mTree;
+    SkRect mDst;
 
 };
 
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 9c46c00..0401f2d 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -522,7 +522,10 @@
 void FrameBuilder::deferBitmapOp(const BitmapOp& op) {
     BakedOpState* bakedState = tryBakeOpState(op);
     if (!bakedState) return; // quick rejected
-    bakedState->setupOpacity(op.paint);
+
+    if (op.bitmap->isOpaque()) {
+        bakedState->setupOpacity(op.paint);
+    }
 
     // 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
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index e418227..039ab6b 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -86,6 +86,7 @@
      */
     template <typename StaticDispatcher, typename Renderer>
     void replayBakedOps(Renderer& renderer) {
+        std::vector<OffscreenBuffer*> temporaryLayers;
         finishDefer();
         /**
          * Defines a LUT of lambdas which allow a recorded BakedOpState to use state->op->opId to
@@ -129,6 +130,7 @@
             } else if (!layer.empty()) {
                 // save layer - skip entire layer if empty (in which case, LayerOp has null layer).
                 layer.offscreenBuffer = renderer.startTemporaryLayer(layer.width, layer.height);
+                temporaryLayers.push_back(layer.offscreenBuffer);
                 GL_CHECKPOINT(MODERATE);
                 layer.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
                 GL_CHECKPOINT(MODERATE);
@@ -145,6 +147,10 @@
             GL_CHECKPOINT(MODERATE);
             renderer.endFrame(fbo0.repaintRect);
         }
+
+        for (auto& temporaryLayer : temporaryLayers) {
+            renderer.recycleTemporaryLayer(temporaryLayer);
+        }
     }
 
     void dump() const {
diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp
index 8f837f6..0932d65 100644
--- a/libs/hwui/PropertyValuesHolder.cpp
+++ b/libs/hwui/PropertyValuesHolder.cpp
@@ -53,7 +53,7 @@
     } else {
         animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
     }
-    mGroup->setPropertyValue(mPropertyId, animatedValue);
+    mGroup->mutateProperties()->setPropertyValue(mPropertyId, animatedValue);
 }
 
 inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) {
@@ -72,7 +72,7 @@
 
 void FullPathColorPropertyValuesHolder::setFraction(float fraction) {
     SkColor animatedValue = interpolateColors(mStartValue, mEndValue, fraction);
-    mFullPath->setColorPropertyValue(mPropertyId, animatedValue);
+    mFullPath->mutateProperties()->setColorPropertyValue(mPropertyId, animatedValue);
 }
 
 void FullPathPropertyValuesHolder::setFraction(float fraction) {
@@ -82,17 +82,17 @@
     } else {
         animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
     }
-    mFullPath->setPropertyValue(mPropertyId, animatedValue);
+    mFullPath->mutateProperties()->setPropertyValue(mPropertyId, animatedValue);
 }
 
 void PathDataPropertyValuesHolder::setFraction(float fraction) {
     VectorDrawableUtils::interpolatePaths(&mPathData, mStartValue, mEndValue, fraction);
-    mPath->setPathData(mPathData);
+    mPath->mutateProperties()->setData(mPathData);
 }
 
 void RootAlphaPropertyValuesHolder::setFraction(float fraction) {
     float animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
-    mTree->setRootAlpha(animatedValue);
+    mTree->mutateProperties()->setRootAlpha(animatedValue);
 }
 
 } // namepace uirenderer
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index 0271a80..aee9d63 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -501,22 +501,20 @@
  * when creating/tracking a SkPaint* during defer isn't worth the bother.
  */
 struct LayerOp : RecordedOp {
-    // Records a one-use (saveLayer) layer for drawing. Once drawn, the layer will be destroyed.
+    // Records a one-use (saveLayer) layer for drawing.
     LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle)
             : SUPER_PAINTLESS(LayerOp)
             , layerHandle(layerHandle)
             , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f)
             , mode(PaintUtils::getXfermodeDirect(paint))
-            , colorFilter(paint ? paint->getColorFilter() : nullptr)
-            , destroy(true) {}
+            , colorFilter(paint ? paint->getColorFilter() : nullptr) {}
 
     LayerOp(RenderNode& node)
             : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), nullptr, nullptr)
             , layerHandle(node.getLayerHandle())
             , alpha(node.properties().layerProperties().alpha() / 255.0f)
             , mode(node.properties().layerProperties().xferMode())
-            , colorFilter(node.properties().layerProperties().colorFilter())
-            , destroy(false) {}
+            , colorFilter(node.properties().layerProperties().colorFilter()) {}
 
     // Records a handle to the Layer object, since the Layer itself won't be
     // constructed until after this operation is constructed.
@@ -527,9 +525,6 @@
     // pointer to object owned by either LayerProperties, or a recorded Paint object in a
     // BeginLayerOp. Lives longer than LayerOp in either case, so no skia ref counting is used.
     SkColorFilter* colorFilter;
-
-    // whether to destroy the layer, once rendered
-    const bool destroy;
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 4f9cd68..b78497d 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -430,10 +430,11 @@
 }
 
 void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
+    mDisplayList->pushStagingFunctors.push_back(tree->getFunctor());
     mDisplayList->ref(tree);
     addOp(alloc().create_trivial<VectorDrawableOp>(
             tree,
-            Rect(tree->getBounds()),
+            Rect(tree->stagingProperties()->getBounds()),
             *(mState.currentSnapshot()->transform),
             getRecordedClip()));
 }
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index f6f92f7..9578486 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -477,6 +477,9 @@
         for (size_t i = 0; i < mDisplayList->getFunctors().size(); i++) {
             (*mDisplayList->getFunctors()[i])(DrawGlInfo::kModeSync, nullptr);
         }
+        for (size_t i = 0; i < mDisplayList->getPushStagingFunctors().size(); i++) {
+            (*mDisplayList->getPushStagingFunctors()[i])();
+        }
     }
 }
 
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index f577785..5ebf545 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -155,6 +155,23 @@
         ALOGD("%*s(ClipRect %d, %d, %d, %d)", level * 2, "",
                 (int)clipRect.left, (int)clipRect.top, (int)clipRect.right, (int)clipRect.bottom);
     }
+
+    if (getRevealClip().willClip()) {
+        Rect bounds;
+        getRevealClip().getBounds(&bounds);
+        ALOGD("%*s(Clip to reveal clip with bounds %.2f %.2f %.2f %.2f)", level * 2, "",
+                RECT_ARGS(bounds));
+    }
+
+    auto& outline = mPrimitiveFields.mOutline;
+    if (outline.getShouldClip()) {
+        if (outline.isEmpty()) {
+            ALOGD("%*s(Clip to empty outline)", level * 2, "");
+        } else if (outline.willClip()) {
+            ALOGD("%*s(Clip to outline with bounds %.2f %.2f %.2f %.2f)", level * 2, "",
+                    RECT_ARGS(outline.getBounds()));
+        }
+    }
 }
 
 void RenderProperties::updateMatrix() {
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 5d24fa0..1b459c1 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -747,11 +747,7 @@
 }
 
 void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
-    const SkBitmap& bitmap = vectorDrawable->getBitmapUpdateIfDirty();
-    SkRect bounds = vectorDrawable->getBounds();
-    drawBitmap(bitmap, 0, 0, bitmap.width(), bitmap.height(),
-            bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
-            vectorDrawable->getPaint());
+    vectorDrawable->drawStaging(this);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index d35f764..adfe45c 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -17,6 +17,7 @@
 #include "VectorDrawable.h"
 
 #include "PathParser.h"
+#include "SkColorFilter.h"
 #include "SkImageInfo.h"
 #include "SkShader.h"
 #include <utils/Log.h>
@@ -32,41 +33,36 @@
 
 const int Tree::MAX_CACHED_BITMAP_SIZE = 2048;
 
-void Path::draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix, float scaleX, float scaleY) {
+void Path::draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix, float scaleX, float scaleY,
+        bool useStagingData) {
     float matrixScale = getMatrixScale(groupStackedMatrix);
     if (matrixScale == 0) {
         // When either x or y is scaled to 0, we don't need to draw anything.
         return;
     }
 
-    const SkPath updatedPath = getUpdatedPath();
     SkMatrix pathMatrix(groupStackedMatrix);
     pathMatrix.postScale(scaleX, scaleY);
 
     //TODO: try apply the path matrix to the canvas instead of creating a new path.
     SkPath renderPath;
     renderPath.reset();
-    renderPath.addPath(updatedPath, pathMatrix);
+
+    if (useStagingData) {
+        SkPath tmpPath;
+        getStagingPath(&tmpPath);
+        renderPath.addPath(tmpPath, pathMatrix);
+    } else {
+        renderPath.addPath(getUpdatedPath(), pathMatrix);
+    }
 
     float minScale = fmin(scaleX, scaleY);
     float strokeScale = minScale * matrixScale;
-    drawPath(outCanvas, renderPath, strokeScale, pathMatrix);
-}
-
-void Path::setPathData(const Data& data) {
-    if (mData == data) {
-        return;
-    }
-    // Updates the path data. Note that we don't generate a new Skia path right away
-    // because there are cases where the animation is changing the path data, but the view
-    // that hosts the VD has gone off screen, in which case we won't even draw. So we
-    // postpone the Skia path generation to the draw time.
-    mData = data;
-    mSkPathDirty = true;
+    drawPath(outCanvas, renderPath, strokeScale, pathMatrix, useStagingData);
 }
 
 void Path::dump() {
-    ALOGD("Path: %s has %zu points", mName.c_str(), mData.points.size());
+    ALOGD("Path: %s has %zu points", mName.c_str(), mProperties.getData().points.size());
 }
 
 float Path::getMatrixScale(const SkMatrix& groupStackedMatrix) {
@@ -95,213 +91,215 @@
     }
     return matrixScale;
 }
+
+// Called from UI thread during the initial setup/theme change.
 Path::Path(const char* pathStr, size_t strLength) {
     PathParser::ParseResult result;
-    PathParser::getPathDataFromString(&mData, &result, pathStr, strLength);
-    if (!result.failureOccurred) {
-        VectorDrawableUtils::verbsToPath(&mSkPath, mData);
-    }
-}
-
-Path::Path(const Data& data) {
-    mData = data;
-    // Now we need to construct a path
-    VectorDrawableUtils::verbsToPath(&mSkPath, data);
+    Data data;
+    PathParser::getPathDataFromString(&data, &result, pathStr, strLength);
+    mStagingProperties.setData(data);
 }
 
 Path::Path(const Path& path) : Node(path) {
-    mData = path.mData;
-    VectorDrawableUtils::verbsToPath(&mSkPath, mData);
-}
-
-bool Path::canMorph(const Data& morphTo) {
-    return VectorDrawableUtils::canMorph(mData, morphTo);
-}
-
-bool Path::canMorph(const Path& path) {
-    return canMorph(path.mData);
+    mStagingProperties.syncProperties(path.mStagingProperties);
 }
 
 const SkPath& Path::getUpdatedPath() {
     if (mSkPathDirty) {
         mSkPath.reset();
-        VectorDrawableUtils::verbsToPath(&mSkPath, mData);
+        VectorDrawableUtils::verbsToPath(&mSkPath, mProperties.getData());
         mSkPathDirty = false;
     }
     return mSkPath;
 }
 
-void Path::setPath(const char* pathStr, size_t strLength) {
-    PathParser::ParseResult result;
-    mSkPathDirty = true;
-    PathParser::getPathDataFromString(&mData, &result, pathStr, strLength);
+void Path::getStagingPath(SkPath* outPath) {
+    outPath->reset();
+    VectorDrawableUtils::verbsToPath(outPath, mStagingProperties.getData());
+}
+
+void Path::syncProperties() {
+    if (mStagingPropertiesDirty) {
+        mProperties.syncProperties(mStagingProperties);
+    } else {
+        mStagingProperties.syncProperties(mProperties);
+    }
+    mStagingPropertiesDirty = false;
 }
 
 FullPath::FullPath(const FullPath& path) : Path(path) {
-    mProperties = path.mProperties;
-    SkRefCnt_SafeAssign(mStrokeGradient, path.mStrokeGradient);
-    SkRefCnt_SafeAssign(mFillGradient, path.mFillGradient);
+    mStagingProperties.syncProperties(path.mStagingProperties);
+}
+
+static void applyTrim(SkPath* outPath, const SkPath& inPath, float trimPathStart, float trimPathEnd,
+        float trimPathOffset) {
+    if (trimPathStart == 0.0f && trimPathEnd == 1.0f) {
+        *outPath = inPath;
+        return;
+    }
+    outPath->reset();
+    if (trimPathStart == trimPathEnd) {
+        // Trimmed path should be empty.
+        return;
+    }
+    SkPathMeasure measure(inPath, false);
+    float len = SkScalarToFloat(measure.getLength());
+    float start = len * fmod((trimPathStart + trimPathOffset), 1.0f);
+    float end = len * fmod((trimPathEnd + trimPathOffset), 1.0f);
+
+    if (start > end) {
+        measure.getSegment(start, len, outPath, true);
+        if (end > 0) {
+            measure.getSegment(0, end, outPath, true);
+        }
+    } else {
+        measure.getSegment(start, end, outPath, true);
+    }
 }
 
 const SkPath& FullPath::getUpdatedPath() {
-    if (!mSkPathDirty && !mTrimDirty) {
+    if (!mSkPathDirty && !mProperties.mTrimDirty) {
         return mTrimmedSkPath;
     }
     Path::getUpdatedPath();
-    if (mProperties.trimPathStart != 0.0f || mProperties.trimPathEnd != 1.0f) {
-        applyTrim();
+    if (mProperties.getTrimPathStart() != 0.0f || mProperties.getTrimPathEnd() != 1.0f) {
+        mProperties.mTrimDirty = false;
+        applyTrim(&mTrimmedSkPath, mSkPath, mProperties.getTrimPathStart(),
+                mProperties.getTrimPathEnd(), mProperties.getTrimPathOffset());
         return mTrimmedSkPath;
     } else {
         return mSkPath;
     }
 }
 
-void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
-        SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
-        float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
-        int fillType) {
-    mProperties.strokeWidth = strokeWidth;
-    mProperties.strokeColor = strokeColor;
-    mProperties.strokeAlpha = strokeAlpha;
-    mProperties.fillColor = fillColor;
-    mProperties.fillAlpha = fillAlpha;
-    mProperties.strokeMiterLimit = strokeMiterLimit;
-    mProperties.strokeLineCap = strokeLineCap;
-    mProperties.strokeLineJoin = strokeLineJoin;
-    mProperties.fillType = fillType;
-
-    // If any trim property changes, mark trim dirty and update the trim path
-    setTrimPathStart(trimPathStart);
-    setTrimPathEnd(trimPathEnd);
-    setTrimPathOffset(trimPathOffset);
+void FullPath::getStagingPath(SkPath* outPath) {
+    Path::getStagingPath(outPath);
+    SkPath inPath = *outPath;
+    applyTrim(outPath, inPath, mStagingProperties.getTrimPathStart(),
+            mStagingProperties.getTrimPathEnd(), mStagingProperties.getTrimPathOffset());
 }
 
+void FullPath::dump() {
+    Path::dump();
+    ALOGD("stroke width, color, alpha: %f, %d, %f, fill color, alpha: %d, %f",
+            mProperties.getStrokeWidth(), mProperties.getStrokeColor(), mProperties.getStrokeAlpha(),
+            mProperties.getFillColor(), mProperties.getFillAlpha());
+}
+
+
 inline SkColor applyAlpha(SkColor color, float alpha) {
     int alphaBytes = SkColorGetA(color);
     return SkColorSetA(color, alphaBytes * alpha);
 }
 
 void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale,
-                        const SkMatrix& matrix){
+                        const SkMatrix& matrix, bool useStagingData){
+    const FullPathProperties& properties = useStagingData ? mStagingProperties : mProperties;
+
     // Draw path's fill, if fill color or gradient is valid
     bool needsFill = false;
-    if (mFillGradient != nullptr) {
-        mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.fillAlpha));
-        SkShader* newShader = mFillGradient->newWithLocalMatrix(matrix);
-        mPaint.setShader(newShader);
+    SkPaint paint;
+    if (properties.getFillGradient() != nullptr) {
+        paint.setColor(applyAlpha(SK_ColorBLACK, properties.getFillAlpha()));
+        SkShader* newShader = properties.getFillGradient()->newWithLocalMatrix(matrix);
+        paint.setShader(newShader);
         needsFill = true;
-    } else if (mProperties.fillColor != SK_ColorTRANSPARENT) {
-        mPaint.setColor(applyAlpha(mProperties.fillColor, mProperties.fillAlpha));
+    } else if (properties.getFillColor() != SK_ColorTRANSPARENT) {
+        paint.setColor(applyAlpha(properties.getFillColor(), properties.getFillAlpha()));
         needsFill = true;
     }
 
     if (needsFill) {
-        mPaint.setStyle(SkPaint::Style::kFill_Style);
-        mPaint.setAntiAlias(true);
-        SkPath::FillType ft = static_cast<SkPath::FillType>(mProperties.fillType);
+        paint.setStyle(SkPaint::Style::kFill_Style);
+        paint.setAntiAlias(true);
+        SkPath::FillType ft = static_cast<SkPath::FillType>(properties.getFillType());
         renderPath.setFillType(ft);
-        outCanvas->drawPath(renderPath, mPaint);
+        outCanvas->drawPath(renderPath, paint);
     }
 
-    // Draw path's stroke, if stroke color or gradient is valid
+    // Draw path's stroke, if stroke color or Gradient is valid
     bool needsStroke = false;
-    if (mStrokeGradient != nullptr) {
-        mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.strokeAlpha));
-        SkShader* newShader = mStrokeGradient->newWithLocalMatrix(matrix);
-        mPaint.setShader(newShader);
+    if (properties.getStrokeGradient() != nullptr) {
+        paint.setColor(applyAlpha(SK_ColorBLACK, properties.getStrokeAlpha()));
+        SkShader* newShader = properties.getStrokeGradient()->newWithLocalMatrix(matrix);
+        paint.setShader(newShader);
         needsStroke = true;
-    } else if (mProperties.strokeColor != SK_ColorTRANSPARENT) {
-        mPaint.setColor(applyAlpha(mProperties.strokeColor, mProperties.strokeAlpha));
+    } else if (properties.getStrokeColor() != SK_ColorTRANSPARENT) {
+        paint.setColor(applyAlpha(properties.getStrokeColor(), properties.getStrokeAlpha()));
         needsStroke = true;
     }
     if (needsStroke) {
-        mPaint.setStyle(SkPaint::Style::kStroke_Style);
-        mPaint.setAntiAlias(true);
-        mPaint.setStrokeJoin(SkPaint::Join(mProperties.strokeLineJoin));
-        mPaint.setStrokeCap(SkPaint::Cap(mProperties.strokeLineCap));
-        mPaint.setStrokeMiter(mProperties.strokeMiterLimit);
-        mPaint.setStrokeWidth(mProperties.strokeWidth * strokeScale);
-        outCanvas->drawPath(renderPath, mPaint);
+        paint.setStyle(SkPaint::Style::kStroke_Style);
+        paint.setAntiAlias(true);
+        paint.setStrokeJoin(SkPaint::Join(properties.getStrokeLineJoin()));
+        paint.setStrokeCap(SkPaint::Cap(properties.getStrokeLineCap()));
+        paint.setStrokeMiter(properties.getStrokeMiterLimit());
+        paint.setStrokeWidth(properties.getStrokeWidth() * strokeScale);
+        outCanvas->drawPath(renderPath, paint);
     }
 }
 
-/**
- * Applies trimming to the specified path.
- */
-void FullPath::applyTrim() {
-    if (mProperties.trimPathStart == 0.0f && mProperties.trimPathEnd == 1.0f) {
-        // No trimming necessary.
-        return;
-    }
-    mTrimDirty = false;
-    mTrimmedSkPath.reset();
-    if (mProperties.trimPathStart == mProperties.trimPathEnd) {
-        // Trimmed path should be empty.
-        return;
-    }
-    SkPathMeasure measure(mSkPath, false);
-    float len = SkScalarToFloat(measure.getLength());
-    float start = len * fmod((mProperties.trimPathStart + mProperties.trimPathOffset), 1.0f);
-    float end = len * fmod((mProperties.trimPathEnd + mProperties.trimPathOffset), 1.0f);
+void FullPath::syncProperties() {
+    Path::syncProperties();
 
-    if (start > end) {
-        measure.getSegment(start, len, &mTrimmedSkPath, true);
-        if (end > 0) {
-            measure.getSegment(0, end, &mTrimmedSkPath, true);
-        }
+    if (mStagingPropertiesDirty) {
+        mProperties.syncProperties(mStagingProperties);
     } else {
-        measure.getSegment(start, end, &mTrimmedSkPath, true);
+        // Update staging property with property values from animation.
+        mStagingProperties.syncProperties(mProperties);
     }
+    mStagingPropertiesDirty = false;
 }
 
-REQUIRE_COMPATIBLE_LAYOUT(FullPath::Properties);
+REQUIRE_COMPATIBLE_LAYOUT(FullPath::FullPathProperties::PrimitiveFields);
 
 static_assert(sizeof(float) == sizeof(int32_t), "float is not the same size as int32_t");
 static_assert(sizeof(SkColor) == sizeof(int32_t), "SkColor is not the same size as int32_t");
 
-bool FullPath::getProperties(int8_t* outProperties, int length) {
-    int propertyDataSize = sizeof(Properties);
+bool FullPath::FullPathProperties::copyProperties(int8_t* outProperties, int length) const {
+    int propertyDataSize = sizeof(FullPathProperties::PrimitiveFields);
     if (length != propertyDataSize) {
         LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
                 propertyDataSize, length);
         return false;
     }
-    Properties* out = reinterpret_cast<Properties*>(outProperties);
-    *out = mProperties;
+
+    PrimitiveFields* out = reinterpret_cast<PrimitiveFields*>(outProperties);
+    *out = mPrimitiveFields;
     return true;
 }
 
-void FullPath::setColorPropertyValue(int propertyId, int32_t value) {
+void FullPath::FullPathProperties::setColorPropertyValue(int propertyId, int32_t value) {
     Property currentProperty = static_cast<Property>(propertyId);
-    if (currentProperty == Property::StrokeColor) {
-        mProperties.strokeColor = value;
-    } else if (currentProperty == Property::FillColor) {
-        mProperties.fillColor = value;
+    if (currentProperty == Property::strokeColor) {
+        setStrokeColor(value);
+    } else if (currentProperty == Property::fillColor) {
+        setFillColor(value);
     } else {
-        LOG_ALWAYS_FATAL("Error setting color property on FullPath: No valid property with id: %d",
-                propertyId);
+        LOG_ALWAYS_FATAL("Error setting color property on FullPath: No valid property"
+                " with id: %d", propertyId);
     }
 }
 
-void FullPath::setPropertyValue(int propertyId, float value) {
+void FullPath::FullPathProperties::setPropertyValue(int propertyId, float value) {
     Property property = static_cast<Property>(propertyId);
     switch (property) {
-    case Property::StrokeWidth:
+    case Property::strokeWidth:
         setStrokeWidth(value);
         break;
-    case Property::StrokeAlpha:
+    case Property::strokeAlpha:
         setStrokeAlpha(value);
         break;
-    case Property::FillAlpha:
+    case Property::fillAlpha:
         setFillAlpha(value);
         break;
-    case Property::TrimPathStart:
+    case Property::trimPathStart:
         setTrimPathStart(value);
         break;
-    case Property::TrimPathEnd:
+    case Property::trimPathEnd:
         setTrimPathEnd(value);
         break;
-    case Property::TrimPathOffset:
+    case Property::trimPathOffset:
         setTrimPathOffset(value);
         break;
     default:
@@ -311,16 +309,16 @@
 }
 
 void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath,
-        float strokeScale, const SkMatrix& matrix){
+        float strokeScale, const SkMatrix& matrix, bool useStagingData){
     outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
 }
 
 Group::Group(const Group& group) : Node(group) {
-    mProperties = group.mProperties;
+    mStagingProperties.syncProperties(group.mStagingProperties);
 }
 
 void Group::draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scaleX,
-        float scaleY) {
+        float scaleY, bool useStagingData) {
     // TODO: Try apply the matrix to the canvas instead of passing it down the tree
 
     // Calculate current group's matrix by preConcat the parent's and
@@ -328,14 +326,15 @@
     // Basically the Mfinal = Mviewport * M0 * M1 * M2;
     // Mi the local matrix at level i of the group tree.
     SkMatrix stackedMatrix;
-    getLocalMatrix(&stackedMatrix);
+    const GroupProperties& prop = useStagingData ? mStagingProperties : mProperties;
+    getLocalMatrix(&stackedMatrix, prop);
     stackedMatrix.postConcat(currentMatrix);
 
     // Save the current clip information, which is local to this group.
     outCanvas->save();
     // Draw the group tree in the same order as the XML file.
     for (auto& child : mChildren) {
-        child->draw(outCanvas, stackedMatrix, scaleX, scaleY);
+        child->draw(outCanvas, stackedMatrix, scaleX, scaleY, useStagingData);
     }
     // Restore the previous clip information.
     outCanvas->restore();
@@ -343,96 +342,106 @@
 
 void Group::dump() {
     ALOGD("Group %s has %zu children: ", mName.c_str(), mChildren.size());
+    ALOGD("Group translateX, Y : %f, %f, scaleX, Y: %f, %f", mProperties.getTranslateX(),
+            mProperties.getTranslateY(), mProperties.getScaleX(), mProperties.getScaleY());
     for (size_t i = 0; i < mChildren.size(); i++) {
         mChildren[i]->dump();
     }
 }
 
-void Group::updateLocalMatrix(float rotate, float pivotX, float pivotY,
-        float scaleX, float scaleY, float translateX, float translateY) {
-    setRotation(rotate);
-    setPivotX(pivotX);
-    setPivotY(pivotY);
-    setScaleX(scaleX);
-    setScaleY(scaleY);
-    setTranslateX(translateX);
-    setTranslateY(translateY);
+void Group::syncProperties() {
+    // Copy over the dirty staging properties
+    if (mStagingPropertiesDirty) {
+        mProperties.syncProperties(mStagingProperties);
+    } else {
+        mStagingProperties.syncProperties(mProperties);
+    }
+    mStagingPropertiesDirty = false;
+    for (auto& child : mChildren) {
+        child->syncProperties();
+    }
 }
 
-void Group::getLocalMatrix(SkMatrix* outMatrix) {
+void Group::getLocalMatrix(SkMatrix* outMatrix, const GroupProperties& properties) {
     outMatrix->reset();
     // TODO: use rotate(mRotate, mPivotX, mPivotY) and scale with pivot point, instead of
     // translating to pivot for rotating and scaling, then translating back.
-    outMatrix->postTranslate(-mProperties.pivotX, -mProperties.pivotY);
-    outMatrix->postScale(mProperties.scaleX, mProperties.scaleY);
-    outMatrix->postRotate(mProperties.rotate, 0, 0);
-    outMatrix->postTranslate(mProperties.translateX + mProperties.pivotX,
-            mProperties.translateY + mProperties.pivotY);
+    outMatrix->postTranslate(-properties.getPivotX(), -properties.getPivotY());
+    outMatrix->postScale(properties.getScaleX(), properties.getScaleY());
+    outMatrix->postRotate(properties.getRotation(), 0, 0);
+    outMatrix->postTranslate(properties.getTranslateX() + properties.getPivotX(),
+            properties.getTranslateY() + properties.getPivotY());
 }
 
 void Group::addChild(Node* child) {
     mChildren.emplace_back(child);
+    if (mPropertyChangedListener != nullptr) {
+        child->setPropertyChangedListener(mPropertyChangedListener);
+    }
 }
 
-bool Group::getProperties(float* outProperties, int length) {
-    int propertyCount = static_cast<int>(Property::Count);
+bool Group::GroupProperties::copyProperties(float* outProperties, int length) const {
+    int propertyCount = static_cast<int>(Property::count);
     if (length != propertyCount) {
         LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
                 propertyCount, length);
         return false;
     }
-    Properties* out = reinterpret_cast<Properties*>(outProperties);
-    *out = mProperties;
+
+    PrimitiveFields* out = reinterpret_cast<PrimitiveFields*>(outProperties);
+    *out = mPrimitiveFields;
     return true;
 }
 
 // TODO: Consider animating the properties as float pointers
-float Group::getPropertyValue(int propertyId) const {
+// Called on render thread
+float Group::GroupProperties::getPropertyValue(int propertyId) const {
     Property currentProperty = static_cast<Property>(propertyId);
     switch (currentProperty) {
-    case Property::Rotate:
-        return mProperties.rotate;
-    case Property::PivotX:
-        return mProperties.pivotX;
-    case Property::PivotY:
-        return mProperties.pivotY;
-    case Property::ScaleX:
-        return mProperties.scaleX;
-    case Property::ScaleY:
-        return mProperties.scaleY;
-    case Property::TranslateX:
-        return mProperties.translateX;
-    case Property::TranslateY:
-        return mProperties.translateY;
+    case Property::rotate:
+        return getRotation();
+    case Property::pivotX:
+        return getPivotX();
+    case Property::pivotY:
+        return getPivotY();
+    case Property::scaleX:
+        return getScaleX();
+    case Property::scaleY:
+        return getScaleY();
+    case Property::translateX:
+        return getTranslateX();
+    case Property::translateY:
+        return getTranslateY();
     default:
         LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
         return 0;
     }
 }
 
-void Group::setPropertyValue(int propertyId, float value) {
+// Called on render thread
+void Group::GroupProperties::setPropertyValue(int propertyId, float value) {
     Property currentProperty = static_cast<Property>(propertyId);
     switch (currentProperty) {
-    case Property::Rotate:
-        mProperties.rotate = value;
+    case Property::rotate:
+        setRotation(value);
         break;
-    case Property::PivotX:
-        mProperties.pivotX = value;
+    case Property::pivotX:
+        setPivotX(value);
         break;
-    case Property::PivotY:
-        mProperties.pivotY = value;
+    case Property::pivotY:
+        setPivotY(value);
         break;
-    case Property::ScaleX:
-        mProperties.scaleX = value;
+    case Property::scaleX:
+        setScaleX(value);
         break;
-    case Property::ScaleY:
-        mProperties.scaleY = value;
+    case Property::scaleY:
+        setScaleY(value);
         break;
-    case Property::TranslateX:
-        mProperties.translateX = value;
+    case Property::translateX:
+        setTranslateX(value);
         break;
-    case Property::TranslateY:
-        mProperties.translateY = value;
+    case Property::translateY:
+        setTranslateY(value);
         break;
     default:
         LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
@@ -440,7 +449,11 @@
 }
 
 bool Group::isValidProperty(int propertyId) {
-    return propertyId >= 0 && propertyId < static_cast<int>(Property::Count);
+    return GroupProperties::isValidProperty(propertyId);
+}
+
+bool Group::GroupProperties::isValidProperty(int propertyId) {
+    return propertyId >= 0 && propertyId < static_cast<int>(Property::count);
 }
 
 void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
@@ -449,18 +462,18 @@
     // avoid blurry scaling, we have to draw into a bitmap with exact pixel
     // size first. This bitmap size is determined by the bounds and the
     // canvas scale.
-    outCanvas->getMatrix(&mCanvasMatrix);
-    mBounds = bounds;
+    SkMatrix canvasMatrix;
+    outCanvas->getMatrix(&canvasMatrix);
     float canvasScaleX = 1.0f;
     float canvasScaleY = 1.0f;
-    if (mCanvasMatrix.getSkewX() == 0 && mCanvasMatrix.getSkewY() == 0) {
+    if (canvasMatrix.getSkewX() == 0 && canvasMatrix.getSkewY() == 0) {
         // Only use the scale value when there's no skew or rotation in the canvas matrix.
         // TODO: Add a cts test for drawing VD on a canvas with negative scaling factors.
-        canvasScaleX = fabs(mCanvasMatrix.getScaleX());
-        canvasScaleY = fabs(mCanvasMatrix.getScaleY());
+        canvasScaleX = fabs(canvasMatrix.getScaleX());
+        canvasScaleY = fabs(canvasMatrix.getScaleY());
     }
-    int scaledWidth = (int) (mBounds.width() * canvasScaleX);
-    int scaledHeight = (int) (mBounds.height() * canvasScaleY);
+    int scaledWidth = (int) (bounds.width() * canvasScaleX);
+    int scaledHeight = (int) (bounds.height() * canvasScaleY);
     scaledWidth = std::min(Tree::MAX_CACHED_BITMAP_SIZE, scaledWidth);
     scaledHeight = std::min(Tree::MAX_CACHED_BITMAP_SIZE, scaledHeight);
 
@@ -468,63 +481,105 @@
         return;
     }
 
-    mPaint.setColorFilter(colorFilter);
-
+    mStagingProperties.setScaledSize(scaledWidth, scaledHeight);
     int saveCount = outCanvas->save(SaveFlags::MatrixClip);
-    outCanvas->translate(mBounds.fLeft, mBounds.fTop);
+    outCanvas->translate(bounds.fLeft, bounds.fTop);
 
     // Handle RTL mirroring.
     if (needsMirroring) {
-        outCanvas->translate(mBounds.width(), 0);
+        outCanvas->translate(bounds.width(), 0);
         outCanvas->scale(-1.0f, 1.0f);
     }
+    mStagingProperties.setColorFilter(colorFilter);
 
     // 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);
-    mBounds.offsetTo(0, 0);
-    createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
-
+    SkRect tmpBounds = bounds;
+    tmpBounds.offsetTo(0, 0);
+    mStagingProperties.setBounds(tmpBounds);
     outCanvas->drawVectorDrawable(this);
-
     outCanvas->restoreToCount(saveCount);
 }
 
-SkPaint* Tree::getPaint() {
-    SkPaint* paint;
-    if (mRootAlpha == 1.0f && mPaint.getColorFilter() == NULL) {
-        paint = NULL;
-    } else {
-        mPaint.setFilterQuality(kLow_SkFilterQuality);
-        mPaint.setAlpha(mRootAlpha * 255);
-        paint = &mPaint;
+void Tree::drawStaging(Canvas* outCanvas) {
+    bool redrawNeeded = allocateBitmapIfNeeded(&mStagingCache.bitmap,
+            mStagingProperties.getScaledWidth(), mStagingProperties.getScaledHeight());
+    // draw bitmap cache
+    if (redrawNeeded || mStagingCache.dirty) {
+        updateBitmapCache(&mStagingCache.bitmap, true);
+        mStagingCache.dirty = false;
     }
-    return paint;
+
+    SkPaint tmpPaint;
+    SkPaint* paint = updatePaint(&tmpPaint, &mStagingProperties);
+    outCanvas->drawBitmap(mStagingCache.bitmap, 0, 0,
+            mStagingCache.bitmap.width(), mStagingCache.bitmap.height(),
+            mStagingProperties.getBounds().left(), mStagingProperties.getBounds().top(),
+            mStagingProperties.getBounds().right(), mStagingProperties.getBounds().bottom(), paint);
+}
+
+SkPaint* Tree::getPaint() {
+    return updatePaint(&mPaint, &mProperties);
+}
+
+// Update the given paint with alpha and color filter. Return nullptr if no color filter is
+// specified and root alpha is 1. Otherwise, return updated paint.
+SkPaint* Tree::updatePaint(SkPaint* outPaint, TreeProperties* prop) {
+    if (prop->getRootAlpha() == 1.0f && prop->getColorFilter() == nullptr) {
+        return nullptr;
+    } else {
+        outPaint->setColorFilter(mStagingProperties.getColorFilter());
+        outPaint->setFilterQuality(kLow_SkFilterQuality);
+        outPaint->setAlpha(prop->getRootAlpha() * 255);
+        return outPaint;
+    }
 }
 
 const SkBitmap& Tree::getBitmapUpdateIfDirty() {
-    mCachedBitmap.eraseColor(SK_ColorTRANSPARENT);
-    SkCanvas outCanvas(mCachedBitmap);
-    float scaleX = (float) mCachedBitmap.width() / mViewportWidth;
-    float scaleY = (float) mCachedBitmap.height() / mViewportHeight;
-    mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY);
-    mCacheDirty = false;
-    return mCachedBitmap;
+    bool redrawNeeded = allocateBitmapIfNeeded(&mCache.bitmap, mProperties.getScaledWidth(),
+            mProperties.getScaledHeight());
+    if (redrawNeeded || mCache.dirty) {
+        updateBitmapCache(&mCache.bitmap, false);
+        mCache.dirty = false;
+    }
+    return mCache.bitmap;
 }
 
-void Tree::createCachedBitmapIfNeeded(int width, int height) {
-    if (!canReuseBitmap(width, height)) {
+void Tree::updateBitmapCache(SkBitmap* outCache, bool useStagingData) {
+    outCache->eraseColor(SK_ColorTRANSPARENT);
+    SkCanvas outCanvas(*outCache);
+    float viewportWidth = useStagingData ?
+            mStagingProperties.getViewportWidth() : mProperties.getViewportWidth();
+    float viewportHeight = useStagingData ?
+            mStagingProperties.getViewportHeight() : mProperties.getViewportHeight();
+    float scaleX = outCache->width() / viewportWidth;
+    float scaleY = outCache->height() / viewportHeight;
+    mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY, useStagingData);
+}
+
+bool Tree::allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height) {
+    if (!canReuseBitmap(*outCache, width, height)) {
         SkImageInfo info = SkImageInfo::Make(width, height,
                 kN32_SkColorType, kPremul_SkAlphaType);
-        mCachedBitmap.setInfo(info);
+        outCache->setInfo(info);
         // TODO: Count the bitmap cache against app's java heap
-        mCachedBitmap.allocPixels(info);
-        mCacheDirty = true;
+        outCache->allocPixels(info);
+        return true;
     }
+    return false;
 }
 
-bool Tree::canReuseBitmap(int width, int height) {
-    return width == mCachedBitmap.width() && height == mCachedBitmap.height();
+bool Tree::canReuseBitmap(const SkBitmap& bitmap, int width, int height) {
+    return width == bitmap.width() && height == bitmap.height();
+}
+
+void Tree::onPropertyChanged(TreeProperties* prop) {
+    if (prop == &mStagingProperties) {
+        mStagingCache.dirty = true;
+    } else {
+        mCache.dirty = true;
+    }
 }
 
 }; // namespace VectorDrawable
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 7a45bf5..e4c7ed7 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -18,9 +18,11 @@
 #define ANDROID_HWUI_VPATH_H
 
 #include "hwui/Canvas.h"
+#include "DisplayList.h"
 
 #include <SkBitmap.h>
 #include <SkColor.h>
+#include <SkColorFilter.h>
 #include <SkCanvas.h>
 #include <SkMatrix.h>
 #include <SkPaint.h>
@@ -38,8 +40,11 @@
 namespace uirenderer {
 
 namespace VectorDrawable {
-#define VD_SET_PROP_WITH_FLAG(field, value, flag) (VD_SET_PROP(field, value) ? (flag = true, true): false);
+#define VD_SET_PROP_WITH_FLAG(field, value, flag) (VD_SET_PROP_AND_NOTIFY(field, value) ? (flag = true, true) : false)
 #define VD_SET_PROP(field, value) (value != field ? (field = value, true) : false)
+#define VD_SET_PROP_AND_NOTIFY(field, value) ({ bool retVal = VD_SET_PROP(field, value);\
+    onPropertyChanged(); retVal;})
+#define UPDATE_SKPROP(field, value) ({bool retVal = (field != value); if (field != value) SkRefCnt_SafeAssign(field, value); retVal;})
 
 /* A VectorDrawable is composed of a tree of nodes.
  * Each node can be a group node, or a path.
@@ -52,22 +57,65 @@
  *          /     \             |
  *         Path   Path         Path
  *
+ * VectorDrawables are drawn into bitmap caches first, then the caches are drawn to the given
+ * canvas with root alpha applied. Two caches are maintained for VD, one in UI thread, the other in
+ * Render Thread. A generation id is used to keep track of changes in the vector drawable tree.
+ * Each cache has their own generation id to track whether they are up to date with the latest
+ * change in the tree.
+ *
+ * Any property change to the vector drawable coming from UI thread (such as bulk setters to update
+ * all the properties, and viewport change, etc.) are only modifying the staging properties. The
+ * staging properties will then be marked dirty and will be pushed over to render thread properties
+ * at sync point. If staging properties are not dirty at sync point, we sync backwards by updating
+ * staging properties with render thread properties to reflect the latest animation value.
+ *
  */
+
+class PropertyChangedListener {
+public:
+    PropertyChangedListener(bool* dirty, bool* stagingDirty)
+            : mDirty(dirty), mStagingDirty(stagingDirty) {}
+    void onPropertyChanged() {
+            *mDirty = true;
+    }
+    void onStagingPropertyChanged() {
+            *mStagingDirty = true;
+    }
+private:
+    bool* mDirty;
+    bool* mStagingDirty;
+};
+
 class ANDROID_API Node {
 public:
+    class Properties {
+    public:
+        Properties(Node* node) : mNode(node) {}
+        inline void onPropertyChanged() {
+            mNode->onPropertyChanged(this);
+        }
+    private:
+        Node* mNode;
+    };
     Node(const Node& node) {
         mName = node.mName;
     }
     Node() {}
     virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
-            float scaleX, float scaleY) = 0;
+            float scaleX, float scaleY, bool useStagingData) = 0;
     virtual void dump() = 0;
     void setName(const char* name) {
         mName = name;
     }
+    virtual void setPropertyChangedListener(PropertyChangedListener* listener) {
+        mPropertyChangedListener = listener;
+    }
+    virtual void onPropertyChanged(Properties* properties) = 0;
     virtual ~Node(){}
+    virtual void syncProperties() = 0;
 protected:
     std::string mName;
+    PropertyChangedListener* mPropertyChangedListener = nullptr;
 };
 
 class ANDROID_API Path : public Node {
@@ -81,150 +129,267 @@
                     && points == data.points;
         }
     };
-    Path(const Data& nodes);
+
+    class PathProperties : public Properties {
+    public:
+        PathProperties(Node* node) : Properties(node) {}
+        void syncProperties(const PathProperties& prop) {
+            mData = prop.mData;
+            onPropertyChanged();
+        }
+        void setData(const Data& data) {
+            // Updates the path data. Note that we don't generate a new Skia path right away
+            // because there are cases where the animation is changing the path data, but the view
+            // that hosts the VD has gone off screen, in which case we won't even draw. So we
+            // postpone the Skia path generation to the draw time.
+            if (data == mData) {
+                return;
+            }
+            mData = data;
+            onPropertyChanged();
+
+        }
+        const Data& getData() const {
+            return mData;
+        }
+    private:
+        Data mData;
+    };
+
     Path(const Path& path);
     Path(const char* path, size_t strLength);
     Path() {}
+
     void dump() override;
-    bool canMorph(const Data& path);
-    bool canMorph(const Path& path);
     void draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix,
-            float scaleX, float scaleY) override;
-    void setPath(const char* path, size_t strLength);
-    void setPathData(const Data& data);
+            float scaleX, float scaleY, bool useStagingData) override;
     static float getMatrixScale(const SkMatrix& groupStackedMatrix);
+    virtual void syncProperties() override;
+    virtual void onPropertyChanged(Properties* prop) override {
+        if (prop == &mStagingProperties) {
+            mStagingPropertiesDirty = true;
+            if (mPropertyChangedListener) {
+                mPropertyChangedListener->onStagingPropertyChanged();
+            }
+        } else if (prop == &mProperties){
+            mSkPathDirty = true;
+            if (mPropertyChangedListener) {
+                mPropertyChangedListener->onPropertyChanged();
+            }
+        }
+    }
+    PathProperties* mutateStagingProperties() { return &mStagingProperties; }
+    const PathProperties* stagingProperties() { return &mStagingProperties; }
+
+    // This should only be called from animations on RT
+    PathProperties* mutateProperties() { return &mProperties; }
 
 protected:
     virtual const SkPath& getUpdatedPath();
+    virtual void getStagingPath(SkPath* outPath);
     virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath,
-            float strokeScale, const SkMatrix& matrix) = 0;
-    Data mData;
-    SkPath mSkPath;
+            float strokeScale, const SkMatrix& matrix, bool useStagingData) = 0;
+
+    // Internal data, render thread only.
     bool mSkPathDirty = true;
+    SkPath mSkPath;
+
+private:
+    PathProperties mProperties = PathProperties(this);
+    PathProperties mStagingProperties = PathProperties(this);
+    bool mStagingPropertiesDirty = true;
 };
 
 class ANDROID_API FullPath: public Path {
 public:
+    class FullPathProperties : public Properties {
+    public:
+        struct PrimitiveFields {
+            float strokeWidth = 0;
+            SkColor strokeColor = SK_ColorTRANSPARENT;
+            float strokeAlpha = 1;
+            SkColor fillColor = SK_ColorTRANSPARENT;
+            float fillAlpha = 1;
+            float trimPathStart = 0;
+            float trimPathEnd = 1;
+            float trimPathOffset = 0;
+            int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
+            int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
+            float strokeMiterLimit = 4;
+            int fillType = 0; /* non-zero or kWinding_FillType in Skia */
+        };
+        FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
+        void syncProperties(const FullPathProperties& prop) {
+            mPrimitiveFields = prop.mPrimitiveFields;
+            mTrimDirty = true;
+            fillGradient.reset(prop.fillGradient);
+            strokeGradient.reset(prop.strokeGradient);
+            onPropertyChanged();
+        }
+        void setFillGradient(SkShader* gradient) {
+            if(fillGradient != gradient){
+                fillGradient.reset(gradient);
+                onPropertyChanged();
+            }
+        }
+        void setStrokeGradient(SkShader* gradient) {
+            if(strokeGradient != gradient){
+                strokeGradient.reset(gradient);
+                onPropertyChanged();
+            }
+        }
+        SkShader* getFillGradient() const {
+            return fillGradient;
+        }
+        SkShader* getStrokeGradient() const {
+            return strokeGradient;
+        }
+        float getStrokeWidth() const{
+            return mPrimitiveFields.strokeWidth;
+        }
+        void setStrokeWidth(float strokeWidth) {
+            VD_SET_PROP_AND_NOTIFY(strokeWidth, strokeWidth);
+        }
+        SkColor getStrokeColor() const{
+            return mPrimitiveFields.strokeColor;
+        }
+        void setStrokeColor(SkColor strokeColor) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.strokeColor, strokeColor);
+        }
+        float getStrokeAlpha() const{
+            return mPrimitiveFields.strokeAlpha;
+        }
+        void setStrokeAlpha(float strokeAlpha) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.strokeAlpha, strokeAlpha);
+        }
+        SkColor getFillColor() const {
+            return mPrimitiveFields.fillColor;
+        }
+        void setFillColor(SkColor fillColor) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.fillColor, fillColor);
+        }
+        float getFillAlpha() const{
+            return mPrimitiveFields.fillAlpha;
+        }
+        void setFillAlpha(float fillAlpha) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.fillAlpha, fillAlpha);
+        }
+        float getTrimPathStart() const{
+            return mPrimitiveFields.trimPathStart;
+        }
+        void setTrimPathStart(float trimPathStart) {
+            VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathStart, trimPathStart, mTrimDirty);
+        }
+        float getTrimPathEnd() const{
+            return mPrimitiveFields.trimPathEnd;
+        }
+        void setTrimPathEnd(float trimPathEnd) {
+            VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathEnd, trimPathEnd, mTrimDirty);
+        }
+        float getTrimPathOffset() const{
+            return mPrimitiveFields.trimPathOffset;
+        }
+        void setTrimPathOffset(float trimPathOffset) {
+            VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathOffset, trimPathOffset, mTrimDirty);
+        }
 
-struct Properties {
-    float strokeWidth = 0;
-    SkColor strokeColor = SK_ColorTRANSPARENT;
-    float strokeAlpha = 1;
-    SkColor fillColor = SK_ColorTRANSPARENT;
-    float fillAlpha = 1;
-    float trimPathStart = 0;
-    float trimPathEnd = 1;
-    float trimPathOffset = 0;
-    int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
-    int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
-    float strokeMiterLimit = 4;
-    int fillType = 0; /* non-zero or kWinding_FillType in Skia */
-};
+        float getStrokeMiterLimit() const {
+            return mPrimitiveFields.strokeMiterLimit;
+        }
+        float getStrokeLineCap() const {
+            return mPrimitiveFields.strokeLineCap;
+        }
+        float getStrokeLineJoin() const {
+            return mPrimitiveFields.strokeLineJoin;
+        }
+        float getFillType() const {
+            return mPrimitiveFields.fillType;
+        }
+        bool copyProperties(int8_t* outProperties, int length) const;
+        void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
+                SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
+                float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
+                int fillType) {
+            mPrimitiveFields.strokeWidth = strokeWidth;
+            mPrimitiveFields.strokeColor = strokeColor;
+            mPrimitiveFields.strokeAlpha = strokeAlpha;
+            mPrimitiveFields.fillColor = fillColor;
+            mPrimitiveFields.fillAlpha = fillAlpha;
+            mPrimitiveFields.trimPathStart = trimPathStart;
+            mPrimitiveFields.trimPathEnd = trimPathEnd;
+            mPrimitiveFields.trimPathOffset = trimPathOffset;
+            mPrimitiveFields.strokeMiterLimit = strokeMiterLimit;
+            mPrimitiveFields.strokeLineCap = strokeLineCap;
+            mPrimitiveFields.strokeLineJoin = strokeLineJoin;
+            mPrimitiveFields.fillType = fillType;
+            mTrimDirty = true;
+            onPropertyChanged();
+        }
+        // Set property values during animation
+        void setColorPropertyValue(int propertyId, int32_t value);
+        void setPropertyValue(int propertyId, float value);
+        bool mTrimDirty;
+    private:
+        enum class Property {
+            strokeWidth = 0,
+            strokeColor,
+            strokeAlpha,
+            fillColor,
+            fillAlpha,
+            trimPathStart,
+            trimPathEnd,
+            trimPathOffset,
+            strokeLineCap,
+            strokeLineJoin,
+            strokeMiterLimit,
+            fillType,
+            count,
+        };
+        PrimitiveFields mPrimitiveFields;
+        SkAutoTUnref<SkShader> fillGradient;
+        SkAutoTUnref<SkShader> strokeGradient;
+    };
 
+    // Called from UI thread
     FullPath(const FullPath& path); // for cloning
     FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
     FullPath() : Path() {}
-    FullPath(const Data& nodes) : Path(nodes) {}
+    void dump() override;
+    FullPathProperties* mutateStagingProperties() { return &mStagingProperties; }
+    const FullPathProperties* stagingProperties() { return &mStagingProperties; }
 
-    ~FullPath() {
-        SkSafeUnref(mFillGradient);
-        SkSafeUnref(mStrokeGradient);
-    }
+    // This should only be called from animations on RT
+    FullPathProperties* mutateProperties() { return &mProperties; }
 
-    void updateProperties(float strokeWidth, SkColor strokeColor,
-            float strokeAlpha, SkColor fillColor, float fillAlpha,
-            float trimPathStart, float trimPathEnd, float trimPathOffset,
-            float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType);
-    // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
-    float getStrokeWidth() {
-        return mProperties.strokeWidth;
+    virtual void syncProperties() override;
+    virtual void onPropertyChanged(Properties* properties) override {
+        Path::onPropertyChanged(properties);
+        if (properties == &mStagingProperties) {
+            mStagingPropertiesDirty = true;
+            if (mPropertyChangedListener) {
+                mPropertyChangedListener->onStagingPropertyChanged();
+            }
+        } else if (properties == &mProperties) {
+            if (mPropertyChangedListener) {
+                mPropertyChangedListener->onPropertyChanged();
+            }
+        }
     }
-    void setStrokeWidth(float strokeWidth) {
-        mProperties.strokeWidth = strokeWidth;
-    }
-    SkColor getStrokeColor() {
-        return mProperties.strokeColor;
-    }
-    void setStrokeColor(SkColor strokeColor) {
-        mProperties.strokeColor = strokeColor;
-    }
-    float getStrokeAlpha() {
-        return mProperties.strokeAlpha;
-    }
-    void setStrokeAlpha(float strokeAlpha) {
-        mProperties.strokeAlpha = strokeAlpha;
-    }
-    SkColor getFillColor() {
-        return mProperties.fillColor;
-    }
-    void setFillColor(SkColor fillColor) {
-        mProperties.fillColor = fillColor;
-    }
-    float getFillAlpha() {
-        return mProperties.fillAlpha;
-    }
-    void setFillAlpha(float fillAlpha) {
-        mProperties.fillAlpha = fillAlpha;
-    }
-    float getTrimPathStart() {
-        return mProperties.trimPathStart;
-    }
-    void setTrimPathStart(float trimPathStart) {
-        VD_SET_PROP_WITH_FLAG(mProperties.trimPathStart, trimPathStart, mTrimDirty);
-    }
-    float getTrimPathEnd() {
-        return mProperties.trimPathEnd;
-    }
-    void setTrimPathEnd(float trimPathEnd) {
-        VD_SET_PROP_WITH_FLAG(mProperties.trimPathEnd, trimPathEnd, mTrimDirty);
-    }
-    float getTrimPathOffset() {
-        return mProperties.trimPathOffset;
-    }
-    void setTrimPathOffset(float trimPathOffset) {
-        VD_SET_PROP_WITH_FLAG(mProperties.trimPathOffset, trimPathOffset, mTrimDirty);
-    }
-    bool getProperties(int8_t* outProperties, int length);
-    void setColorPropertyValue(int propertyId, int32_t value);
-    void setPropertyValue(int propertyId, float value);
-
-    void setFillGradient(SkShader* fillGradient) {
-        SkRefCnt_SafeAssign(mFillGradient, fillGradient);
-    };
-    void setStrokeGradient(SkShader* strokeGradient) {
-        SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient);
-    };
-
 
 protected:
     const SkPath& getUpdatedPath() override;
+    void getStagingPath(SkPath* outPath) override;
     void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
-            float strokeScale, const SkMatrix& matrix) override;
-
+            float strokeScale, const SkMatrix& matrix, bool useStagingData) override;
 private:
-    enum class Property {
-        StrokeWidth = 0,
-        StrokeColor,
-        StrokeAlpha,
-        FillColor,
-        FillAlpha,
-        TrimPathStart,
-        TrimPathEnd,
-        TrimPathOffset,
-        StrokeLineCap,
-        StrokeLineJoin,
-        StrokeMiterLimit,
-        FillType,
-        Count,
-    };
-    // Applies trimming to the specified path.
-    void applyTrim();
-    Properties mProperties;
-    bool mTrimDirty = true;
+
+    FullPathProperties mProperties = FullPathProperties(this);
+    FullPathProperties mStagingProperties = FullPathProperties(this);
+    bool mStagingPropertiesDirty = true;
+
+    // Intermediate data for drawing, render thread only
     SkPath mTrimmedSkPath;
-    SkPaint mPaint;
-    SkShader* mStrokeGradient = nullptr;
-    SkShader* mFillGradient = nullptr;
+
 };
 
 class ANDROID_API ClipPath: public Path {
@@ -232,143 +397,316 @@
     ClipPath(const ClipPath& path) : Path(path) {}
     ClipPath(const char* path, size_t strLength) : Path(path, strLength) {}
     ClipPath() : Path() {}
-    ClipPath(const Data& nodes) : Path(nodes) {}
 
 protected:
     void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
-            float strokeScale, const SkMatrix& matrix) override;
+            float strokeScale, const SkMatrix& matrix, bool useStagingData) override;
 };
 
 class ANDROID_API Group: public Node {
 public:
-    struct Properties {
-        float rotate = 0;
-        float pivotX = 0;
-        float pivotY = 0;
-        float scaleX = 1;
-        float scaleY = 1;
-        float translateX = 0;
-        float translateY = 0;
+    class GroupProperties : public Properties {
+    public:
+        GroupProperties(Node* mNode) : Properties(mNode) {}
+        struct PrimitiveFields {
+            float rotate = 0;
+            float pivotX = 0;
+            float pivotY = 0;
+            float scaleX = 1;
+            float scaleY = 1;
+            float translateX = 0;
+            float translateY = 0;
+        } mPrimitiveFields;
+        void syncProperties(const GroupProperties& prop) {
+            mPrimitiveFields = prop.mPrimitiveFields;
+            onPropertyChanged();
+        }
+        float getRotation() const {
+            return mPrimitiveFields.rotate;
+        }
+        void setRotation(float rotation) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.rotate, rotation);
+        }
+        float getPivotX() const {
+            return mPrimitiveFields.pivotX;
+        }
+        void setPivotX(float pivotX) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.pivotX, pivotX);
+        }
+        float getPivotY() const {
+            return mPrimitiveFields.pivotY;
+        }
+        void setPivotY(float pivotY) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.pivotY, pivotY);
+        }
+        float getScaleX() const {
+            return mPrimitiveFields.scaleX;
+        }
+        void setScaleX(float scaleX) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.scaleX, scaleX);
+        }
+        float getScaleY() const {
+            return mPrimitiveFields.scaleY;
+        }
+        void setScaleY(float scaleY) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.scaleY, scaleY);
+        }
+        float getTranslateX() const {
+            return mPrimitiveFields.translateX;
+        }
+        void setTranslateX(float translateX) {
+            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.translateX, translateX);
+        }
+        float getTranslateY() const {
+            return mPrimitiveFields.translateY;
+        }
+        void setTranslateY(float translateY) {
+            VD_SET_PROP_AND_NOTIFY(translateY, translateY);
+        }
+        void updateProperties(float rotate, float pivotX, float pivotY,
+                float scaleX, float scaleY, float translateX, float translateY) {
+            mPrimitiveFields.rotate = rotate;
+            mPrimitiveFields.pivotX = pivotX;
+            mPrimitiveFields.pivotY = pivotY;
+            mPrimitiveFields.scaleX = scaleX;
+            mPrimitiveFields.scaleY = scaleY;
+            mPrimitiveFields.translateX = translateX;
+            mPrimitiveFields.translateY = translateY;
+            onPropertyChanged();
+        }
+        void setPropertyValue(int propertyId, float value);
+        float getPropertyValue(int propertyId) const;
+        bool copyProperties(float* outProperties, int length) const;
+        static bool isValidProperty(int propertyId);
+    private:
+        enum class Property {
+            rotate = 0,
+            pivotX,
+            pivotY,
+            scaleX,
+            scaleY,
+            translateX,
+            translateY,
+            // Count of the properties, must be at the end.
+            count,
+        };
     };
+
     Group(const Group& group);
     Group() {}
-    float getRotation() {
-        return mProperties.rotate;
-    }
-    void setRotation(float rotation) {
-        mProperties.rotate = rotation;
-    }
-    float getPivotX() {
-        return mProperties.pivotX;
-    }
-    void setPivotX(float pivotX) {
-        mProperties.pivotX = pivotX;
-    }
-    float getPivotY() {
-        return mProperties.pivotY;
-    }
-    void setPivotY(float pivotY) {
-        mProperties.pivotY = pivotY;
-    }
-    float getScaleX() {
-        return mProperties.scaleX;
-    }
-    void setScaleX(float scaleX) {
-        mProperties.scaleX = scaleX;
-    }
-    float getScaleY() {
-        return mProperties.scaleY;
-    }
-    void setScaleY(float scaleY) {
-        mProperties.scaleY = scaleY;
-    }
-    float getTranslateX() {
-        return mProperties.translateX;
-    }
-    void setTranslateX(float translateX) {
-        mProperties.translateX = translateX;
-    }
-    float getTranslateY() {
-        return mProperties.translateY;
-    }
-    void setTranslateY(float translateY) {
-        mProperties.translateY = translateY;
-    }
-    virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
-            float scaleX, float scaleY) override;
-    void updateLocalMatrix(float rotate, float pivotX, float pivotY,
-            float scaleX, float scaleY, float translateX, float translateY);
-    void getLocalMatrix(SkMatrix* outMatrix);
     void addChild(Node* child);
+    virtual void setPropertyChangedListener(PropertyChangedListener* listener) override {
+        Node::setPropertyChangedListener(listener);
+        for (auto& child : mChildren) {
+             child->setPropertyChangedListener(listener);
+        }
+    }
+    virtual void syncProperties() override;
+    GroupProperties* mutateStagingProperties() { return &mStagingProperties; }
+    const GroupProperties* stagingProperties() { return &mStagingProperties; }
+
+    // This should only be called from animations on RT
+    GroupProperties* mutateProperties() { return &mProperties; }
+
+    // Methods below could be called from either UI thread or Render Thread.
+    virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
+            float scaleX, float scaleY, bool useStagingData) override;
+    void getLocalMatrix(SkMatrix* outMatrix, const GroupProperties& properties);
     void dump() override;
-    bool getProperties(float* outProperties, int length);
-    float getPropertyValue(int propertyId) const;
-    void setPropertyValue(int propertyId, float value);
     static bool isValidProperty(int propertyId);
 
+    virtual void onPropertyChanged(Properties* properties) override {
+        if (properties == &mStagingProperties) {
+            mStagingPropertiesDirty = true;
+            if (mPropertyChangedListener) {
+                mPropertyChangedListener->onStagingPropertyChanged();
+            }
+        } else {
+            if (mPropertyChangedListener) {
+                mPropertyChangedListener->onPropertyChanged();
+            }
+        }
+    }
+
 private:
-    enum class Property {
-        Rotate = 0,
-        PivotX,
-        PivotY,
-        ScaleX,
-        ScaleY,
-        TranslateX,
-        TranslateY,
-        // Count of the properties, must be at the end.
-        Count,
-    };
+    GroupProperties mProperties = GroupProperties(this);
+    GroupProperties mStagingProperties = GroupProperties(this);
+    bool mStagingPropertiesDirty = true;
     std::vector< std::unique_ptr<Node> > mChildren;
-    Properties mProperties;
 };
 
 class ANDROID_API Tree : public VirtualLightRefBase {
 public:
-    Tree(Group* rootNode) : mRootNode(rootNode) {}
+    Tree(Group* rootNode) : mRootNode(rootNode) {
+        mRootNode->setPropertyChangedListener(&mPropertyChangedListener);
+    }
     void draw(Canvas* outCanvas, SkColorFilter* colorFilter,
             const SkRect& bounds, bool needsMirroring, bool canReuseCache);
+    void drawStaging(Canvas* canvas);
 
     const SkBitmap& getBitmapUpdateIfDirty();
-    void createCachedBitmapIfNeeded(int width, int height);
-    bool canReuseBitmap(int width, int height);
     void setAllowCaching(bool allowCaching) {
         mAllowCaching = allowCaching;
     }
-    bool setRootAlpha(float rootAlpha) {
-        return VD_SET_PROP(mRootAlpha, rootAlpha);
+    SkPaint* getPaint();
+    void syncProperties() {
+        if (mStagingProperties.mNonAnimatablePropertiesDirty) {
+            mProperties.syncNonAnimatableProperties(mStagingProperties);
+            mStagingProperties.mNonAnimatablePropertiesDirty = false;
+        }
+
+        if (mStagingProperties.mAnimatablePropertiesDirty) {
+            mProperties.syncAnimatableProperties(mStagingProperties);
+        } else {
+            mStagingProperties.syncAnimatableProperties(mProperties);
+        }
+        mStagingProperties.mAnimatablePropertiesDirty = false;
+        mRootNode->syncProperties();
     }
 
-    float getRootAlpha() {
-        return mRootAlpha;
-    }
-    void setViewportSize(float viewportWidth, float viewportHeight) {
-        mViewportWidth = viewportWidth;
-        mViewportHeight = viewportHeight;
-    }
-    SkPaint* getPaint();
-    const SkRect& getBounds() const {
-        return mBounds;
-    }
+    class TreeProperties {
+    public:
+        TreeProperties(Tree* tree) : mTree(tree) {}
+        // Properties that can only be modified by UI thread, therefore sync should
+        // only go from UI to RT
+        struct NonAnimatableProperties {
+            float viewportWidth = 0;
+            float viewportHeight = 0;
+            SkRect bounds;
+            int scaledWidth = 0;
+            int scaledHeight = 0;
+            SkColorFilter* colorFilter = nullptr;
+            ~NonAnimatableProperties() {
+                SkSafeUnref(colorFilter);
+            }
+        } mNonAnimatableProperties;
+        bool mNonAnimatablePropertiesDirty = true;
+
+        float mRootAlpha = 1.0f;
+        bool mAnimatablePropertiesDirty = true;
+
+        void syncNonAnimatableProperties(const TreeProperties& prop) {
+            // Copy over the data that can only be changed in UI thread
+            if (mNonAnimatableProperties.colorFilter != prop.mNonAnimatableProperties.colorFilter) {
+                SkRefCnt_SafeAssign(mNonAnimatableProperties.colorFilter,
+                        prop.mNonAnimatableProperties.colorFilter);
+            }
+            mNonAnimatableProperties = prop.mNonAnimatableProperties;
+        }
+
+        void setViewportSize(float width, float height) {
+            if (mNonAnimatableProperties.viewportWidth != width
+                    || mNonAnimatableProperties.viewportHeight != height) {
+                mNonAnimatablePropertiesDirty = true;
+                mNonAnimatableProperties.viewportWidth = width;
+                mNonAnimatableProperties.viewportHeight = height;
+                mTree->onPropertyChanged(this);
+            }
+        }
+        void setBounds(const SkRect& bounds) {
+            if (mNonAnimatableProperties.bounds != bounds) {
+                mNonAnimatableProperties.bounds = bounds;
+                mNonAnimatablePropertiesDirty = true;
+                mTree->onPropertyChanged(this);
+            }
+        }
+
+        void setScaledSize(int width, int height) {
+            if (mNonAnimatableProperties.scaledWidth != width
+                    || mNonAnimatableProperties.scaledHeight != height) {
+                mNonAnimatableProperties.scaledWidth = width;
+                mNonAnimatableProperties.scaledHeight = height;
+                mNonAnimatablePropertiesDirty = true;
+                mTree->onPropertyChanged(this);
+            }
+        }
+        void setColorFilter(SkColorFilter* filter) {
+            if (UPDATE_SKPROP(mNonAnimatableProperties.colorFilter, filter)) {
+                mNonAnimatablePropertiesDirty = true;
+                mTree->onPropertyChanged(this);
+            }
+        }
+        SkColorFilter* getColorFilter() const{
+            return mNonAnimatableProperties.colorFilter;
+        }
+
+        float getViewportWidth() const {
+            return mNonAnimatableProperties.viewportWidth;
+        }
+        float getViewportHeight() const {
+            return mNonAnimatableProperties.viewportHeight;
+        }
+        float getScaledWidth() const {
+            return mNonAnimatableProperties.scaledWidth;
+        }
+        float getScaledHeight() const {
+            return mNonAnimatableProperties.scaledHeight;
+        }
+        void syncAnimatableProperties(const TreeProperties& prop) {
+            mRootAlpha = prop.mRootAlpha;
+        }
+        bool setRootAlpha(float rootAlpha) {
+            if (rootAlpha != mRootAlpha) {
+                mAnimatablePropertiesDirty = true;
+                mRootAlpha = rootAlpha;
+                mTree->onPropertyChanged(this);
+                return true;
+            }
+            return false;
+        }
+        float getRootAlpha() const { return mRootAlpha;}
+        const SkRect& getBounds() const {
+            return mNonAnimatableProperties.bounds;
+        }
+        Tree* mTree;
+    };
+    void onPropertyChanged(TreeProperties* prop);
+    TreeProperties* mutateStagingProperties() { return &mStagingProperties; }
+    const TreeProperties* stagingProperties() { return &mStagingProperties; }
+    PushStagingFunctor* getFunctor() { return &mFunctor;}
+
+    // This should only be called from animations on RT
+    TreeProperties* mutateProperties() { return &mProperties; }
 
 private:
+    class VectorDrawableFunctor : public PushStagingFunctor {
+    public:
+        VectorDrawableFunctor(Tree* tree) : mTree(tree) {}
+        virtual void operator ()() {
+            mTree->syncProperties();
+        }
+    private:
+        Tree* mTree;
+    };
+
+    SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop);
+    bool allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height);
+    bool canReuseBitmap(const SkBitmap&, int width, int height);
+    void updateBitmapCache(SkBitmap* outCache, bool useStagingData);
     // Cap the bitmap size, such that it won't hurt the performance too much
     // and it won't crash due to a very large scale.
     // The drawable will look blurry above this size.
     const static int MAX_CACHED_BITMAP_SIZE;
 
-    bool mCacheDirty = true;
     bool mAllowCaching = true;
-    float mViewportWidth = 0;
-    float mViewportHeight = 0;
-    float mRootAlpha = 1.0f;
-
     std::unique_ptr<Group> mRootNode;
-    SkRect mBounds;
-    SkMatrix mCanvasMatrix;
-    SkPaint mPaint;
-    SkPathMeasure mPathMeasure;
-    SkBitmap mCachedBitmap;
 
+    TreeProperties mProperties = TreeProperties(this);
+    TreeProperties mStagingProperties = TreeProperties(this);
+
+    VectorDrawableFunctor mFunctor = VectorDrawableFunctor(this);
+
+    SkPaint mPaint;
+    struct Cache {
+        SkBitmap bitmap;
+        bool dirty = true;
+    };
+
+    Cache mStagingCache;
+    Cache mCache;
+
+    PropertyChangedListener mPropertyChangedListener
+            = PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty);
 };
 
 } // namespace VectorDrawable
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index bb1a044..73b6c02 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -127,7 +127,7 @@
 }
 
 void OffscreenBufferPool::clear() {
-    for (auto entry : mPool) {
+    for (auto& entry : mPool) {
         delete entry.layer;
     }
     mPool.clear();
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 7dfafb9..0ea246f 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -49,9 +49,12 @@
 public:
     virtual ~TestRendererBase() {}
     virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) {
-        ADD_FAILURE() << "Layer creation not expected in this test";
+        ADD_FAILURE() << "Temporary layers not expected in this test";
         return nullptr;
     }
+    virtual void recycleTemporaryLayer(OffscreenBuffer*) {
+        ADD_FAILURE() << "Temporary layers not expected in this test";
+    }
     virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) {
         ADD_FAILURE() << "Layer repaint not expected in this test";
     }
@@ -298,7 +301,6 @@
     class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase {
     public:
         void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
-            EXPECT_LT(mIndex++, 2) << "Should be two bitmaps";
             switch(mIndex++) {
             case 0:
                 EXPECT_EQ(opaqueBitmap.pixelRef(), op.bitmap->pixelRef());
@@ -331,7 +333,7 @@
 
     AvoidOverdrawBitmapsTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
-    EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly one op";
+    EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly two ops";
 }
 
 RENDERTHREAD_TEST(FrameBuilder, clippedMerging) {
@@ -711,6 +713,10 @@
             EXPECT_EQ(Rect(200, 200), state.computedState.clipRect());
             EXPECT_TRUE(state.computedState.transform.isIdentity());
         }
+        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+            EXPECT_EQ(4, mIndex++);
+            EXPECT_EQ(nullptr, offscreenBuffer);
+        }
     };
 
     auto node = TestUtils::createNode(0, 0, 200, 200,
@@ -723,7 +729,7 @@
             TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
     SaveLayerSimpleTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
-    EXPECT_EQ(4, renderer.getIndex());
+    EXPECT_EQ(5, renderer.getIndex());
 }
 
 RENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) {
@@ -775,6 +781,15 @@
                 EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer
             } else { ADD_FAILURE(); }
         }
+        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+            const int index = mIndex++;
+            // order isn't important, but we need to see both
+            if (index == 10) {
+                EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer);
+            } else if (index == 11) {
+                EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer);
+            } else { ADD_FAILURE(); }
+        }
     };
 
     auto node = TestUtils::createNode(0, 0, 800, 800,
@@ -795,7 +810,7 @@
             TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
     SaveLayerNestedTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
-    EXPECT_EQ(10, renderer.getIndex());
+    EXPECT_EQ(12, renderer.getIndex());
 }
 
 RENDERTHREAD_TEST(FrameBuilder, saveLayer_contentRejection) {
@@ -1010,10 +1025,15 @@
         }
         void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
             EXPECT_EQ(9, mIndex++);
+            EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle);
         }
         void endFrame(const Rect& repaintRect) override {
             EXPECT_EQ(11, mIndex++);
         }
+        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+            EXPECT_EQ(12, mIndex++);
+            EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer);
+        }
     };
 
     auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping
@@ -1030,7 +1050,7 @@
             TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
     SaveLayerUnclippedComplexTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
-    EXPECT_EQ(12, renderer.getIndex());
+    EXPECT_EQ(13, renderer.getIndex());
 }
 
 RENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) {
@@ -1152,6 +1172,9 @@
         void endFrame(const Rect& repaintRect) override {
             EXPECT_EQ(12, mIndex++);
         }
+        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+            EXPECT_EQ(13, mIndex++);
+        }
     };
 
     auto child = TestUtils::createNode(50, 50, 150, 150,
@@ -1189,7 +1212,7 @@
             syncedList, sLightGeometry, Caches::getInstance());
     HwLayerComplexTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
-    EXPECT_EQ(13, renderer.getIndex());
+    EXPECT_EQ(14, renderer.getIndex());
 
     // clean up layer pointers, so we can safely destruct RenderNodes
     *(child->getLayerHandle()) = nullptr;
@@ -1593,6 +1616,9 @@
         void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
             EXPECT_EQ(4, mIndex++);
         }
+        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+            EXPECT_EQ(5, mIndex++);
+        }
     };
 
     auto parent = TestUtils::createNode(0, 0, 200, 200,
@@ -1611,7 +1637,7 @@
             (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
     ShadowSaveLayerTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
-    EXPECT_EQ(5, renderer.getIndex());
+    EXPECT_EQ(6, renderer.getIndex());
 }
 
 RENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) {
@@ -1840,6 +1866,9 @@
         void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
             EXPECT_EQ(3, mIndex++);
         }
+        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
+            EXPECT_EQ(4, mIndex++);
+        }
     private:
         SaveLayerAlphaData* mOutData;
     };
@@ -1865,7 +1894,7 @@
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
 
     // assert, since output won't be valid if we haven't seen a save layer triggered
-    ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
+    ASSERT_EQ(5, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
 }
 
 RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
diff --git a/libs/hwui/tests/unit/LeakCheckTests.cpp b/libs/hwui/tests/unit/LeakCheckTests.cpp
index 9161f90..e2fc376 100644
--- a/libs/hwui/tests/unit/LeakCheckTests.cpp
+++ b/libs/hwui/tests/unit/LeakCheckTests.cpp
@@ -30,6 +30,25 @@
 const FrameBuilder::LightGeometry sLightGeometery = { {100, 100, 100}, 50};
 const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
 
+RENDERTHREAD_TEST(LeakCheck, saveLayer_overdrawRejection) {
+    auto node = TestUtils::createNode(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        canvas.saveLayerAlpha(0, 0, 100, 100, 128, SaveFlags::ClipToLayer);
+        canvas.drawRect(0, 0, 100, 100, SkPaint());
+        canvas.restore();
+
+        // opaque draw, rejects saveLayer beneath
+        canvas.drawRect(0, 0, 100, 100, SkPaint());
+    });
+    RenderState& renderState = renderThread.renderState();
+    Caches& caches = Caches::getInstance();
+
+    FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
+            TestUtils::createSyncedNodeList(node), sLightGeometery, Caches::getInstance());
+    BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
+    frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
+}
+
 RENDERTHREAD_TEST(LeakCheck, saveLayerUnclipped_simple) {
     auto node = TestUtils::createNode(0, 0, 200, 200,
             [](RenderProperties& props, RecordingCanvas& canvas) {
diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index 37a485e..b7950aa 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -30,119 +30,126 @@
     EXPECT_EQ(1024u, OffscreenBuffer::computeIdealDimension(1000));
 }
 
-TEST(OffscreenBuffer, construct) {
-    TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
-        OffscreenBuffer layer(thread.renderState(), Caches::getInstance(), 49u, 149u);
-        EXPECT_EQ(49u, layer.viewportWidth);
-        EXPECT_EQ(149u, layer.viewportHeight);
+RENDERTHREAD_TEST(OffscreenBuffer, construct) {
+    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 49u, 149u);
+    EXPECT_EQ(49u, layer.viewportWidth);
+    EXPECT_EQ(149u, layer.viewportHeight);
 
-        EXPECT_EQ(64u, layer.texture.width());
-        EXPECT_EQ(192u, layer.texture.height());
+    EXPECT_EQ(64u, layer.texture.width());
+    EXPECT_EQ(192u, layer.texture.height());
 
-        EXPECT_EQ(64u * 192u * 4u, layer.getSizeInBytes());
-    });
+    EXPECT_EQ(64u * 192u * 4u, layer.getSizeInBytes());
 }
 
-TEST(OffscreenBuffer, getTextureCoordinates) {
-    TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
-        OffscreenBuffer layerAligned(thread.renderState(), Caches::getInstance(), 256u, 256u);
-        EXPECT_EQ(Rect(0, 1, 1, 0),
-                layerAligned.getTextureCoordinates());
+RENDERTHREAD_TEST(OffscreenBuffer, getTextureCoordinates) {
+    OffscreenBuffer layerAligned(renderThread.renderState(), Caches::getInstance(), 256u, 256u);
+    EXPECT_EQ(Rect(0, 1, 1, 0),
+            layerAligned.getTextureCoordinates());
 
-        OffscreenBuffer layerUnaligned(thread.renderState(), Caches::getInstance(), 200u, 225u);
-        EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0),
-                layerUnaligned.getTextureCoordinates());
-    });
+    OffscreenBuffer layerUnaligned(renderThread.renderState(), Caches::getInstance(), 200u, 225u);
+    EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0),
+            layerUnaligned.getTextureCoordinates());
 }
 
-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());
-    });
+RENDERTHREAD_TEST(OffscreenBuffer, dirty) {
+    OffscreenBuffer buffer(renderThread.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;
-        EXPECT_EQ(0u, pool.getCount()) << "pool must be created empty";
-        EXPECT_EQ(0u, pool.getSize()) << "pool must be created empty";
-        EXPECT_EQ((uint32_t) Properties::layerPoolSize, pool.getMaxSize())
-                << "pool must read size from Properties";
-    });
+RENDERTHREAD_TEST(OffscreenBufferPool, construct) {
+    OffscreenBufferPool pool;
+    EXPECT_EQ(0u, pool.getCount()) << "pool must be created empty";
+    EXPECT_EQ(0u, pool.getSize()) << "pool must be created empty";
+    EXPECT_EQ((uint32_t) Properties::layerPoolSize, pool.getMaxSize())
+            << "pool must read size from Properties";
 }
 
-TEST(OffscreenBufferPool, getPutClear) {
-    TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
-        OffscreenBufferPool pool;
+RENDERTHREAD_TEST(OffscreenBufferPool, getPutClear) {
+    OffscreenBufferPool pool;
 
-        auto layer = pool.get(thread.renderState(), 100u, 200u);
-        EXPECT_EQ(100u, layer->viewportWidth);
-        EXPECT_EQ(200u, layer->viewportHeight);
+    auto layer = pool.get(renderThread.renderState(), 100u, 200u);
+    EXPECT_EQ(100u, layer->viewportWidth);
+    EXPECT_EQ(200u, layer->viewportHeight);
 
-        ASSERT_LT(layer->getSizeInBytes(), pool.getMaxSize());
+    ASSERT_LT(layer->getSizeInBytes(), pool.getMaxSize());
 
-        pool.putOrDelete(layer);
-        ASSERT_EQ(layer->getSizeInBytes(), pool.getSize());
+    pool.putOrDelete(layer);
+    ASSERT_EQ(layer->getSizeInBytes(), pool.getSize());
 
-        auto layer2 = pool.get(thread.renderState(), 102u, 202u);
-        EXPECT_EQ(layer, layer2) << "layer should be recycled";
-        ASSERT_EQ(0u, pool.getSize()) << "pool should have been emptied by removing only layer";
+    auto layer2 = pool.get(renderThread.renderState(), 102u, 202u);
+    EXPECT_EQ(layer, layer2) << "layer should be recycled";
+    ASSERT_EQ(0u, pool.getSize()) << "pool should have been emptied by removing only layer";
 
-        pool.putOrDelete(layer);
-        EXPECT_EQ(1u, pool.getCount());
-        pool.clear();
-        EXPECT_EQ(0u, pool.getSize());
-        EXPECT_EQ(0u, pool.getCount());
-    });
+    pool.putOrDelete(layer);
+    EXPECT_EQ(1u, pool.getCount());
+    pool.clear();
+    EXPECT_EQ(0u, pool.getSize());
+    EXPECT_EQ(0u, pool.getCount());
 }
 
-TEST(OffscreenBufferPool, resize) {
-    TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
-        OffscreenBufferPool pool;
+RENDERTHREAD_TEST(OffscreenBufferPool, resize) {
+    OffscreenBufferPool pool;
 
-        auto layer = pool.get(thread.renderState(), 64u, 64u);
-        layer->dirty(Rect(64, 64));
+    auto layer = pool.get(renderThread.renderState(), 64u, 64u);
+    layer->dirty(Rect(64, 64));
 
-        // resize in place
-        ASSERT_EQ(layer, pool.resize(layer, 60u, 55u));
-        EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region";
-        EXPECT_EQ(60u, layer->viewportWidth);
-        EXPECT_EQ(55u, layer->viewportHeight);
-        EXPECT_EQ(64u, layer->texture.width());
-        EXPECT_EQ(64u, layer->texture.height());
+    // resize in place
+    ASSERT_EQ(layer, pool.resize(layer, 60u, 55u));
+    EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region";
+    EXPECT_EQ(60u, layer->viewportWidth);
+    EXPECT_EQ(55u, layer->viewportHeight);
+    EXPECT_EQ(64u, layer->texture.width());
+    EXPECT_EQ(64u, layer->texture.height());
 
-        // resized to use different object in pool
-        auto layer2 = pool.get(thread.renderState(), 128u, 128u);
-        layer2->dirty(Rect(128, 128));
-        EXPECT_FALSE(layer2->region.isEmpty());
-        pool.putOrDelete(layer2);
-        ASSERT_EQ(1u, pool.getCount());
+    // resized to use different object in pool
+    auto layer2 = pool.get(renderThread.renderState(), 128u, 128u);
+    layer2->dirty(Rect(128, 128));
+    EXPECT_FALSE(layer2->region.isEmpty());
+    pool.putOrDelete(layer2);
+    ASSERT_EQ(1u, pool.getCount());
 
-        ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u));
-        EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region";
-        EXPECT_EQ(120u, layer2->viewportWidth);
-        EXPECT_EQ(125u, layer2->viewportHeight);
-        EXPECT_EQ(128u, layer2->texture.width());
-        EXPECT_EQ(128u, layer2->texture.height());
+    ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u));
+    EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region";
+    EXPECT_EQ(120u, layer2->viewportWidth);
+    EXPECT_EQ(125u, layer2->viewportHeight);
+    EXPECT_EQ(128u, layer2->texture.width());
+    EXPECT_EQ(128u, layer2->texture.height());
 
-        // original allocation now only thing in pool
-        EXPECT_EQ(1u, pool.getCount());
-        EXPECT_EQ(layer->getSizeInBytes(), pool.getSize());
+    // original allocation now only thing in pool
+    EXPECT_EQ(1u, pool.getCount());
+    EXPECT_EQ(layer->getSizeInBytes(), pool.getSize());
 
-        pool.putOrDelete(layer2);
-    });
+    pool.putOrDelete(layer2);
 }
 
-TEST(OffscreenBufferPool, putAndDestroy) {
-    TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
-        OffscreenBufferPool pool;
-        // layer too big to return to the pool
-        // Note: this relies on the fact that the pool won't reject based on max texture size
-        auto hugeLayer = pool.get(thread.renderState(), pool.getMaxSize() / 64, 64);
-        EXPECT_GT(hugeLayer->getSizeInBytes(), pool.getMaxSize());
-        pool.putOrDelete(hugeLayer);
-        EXPECT_EQ(0u, pool.getCount()); // failed to put (so was destroyed instead)
-    });
+RENDERTHREAD_TEST(OffscreenBufferPool, putAndDestroy) {
+    OffscreenBufferPool pool;
+    // layer too big to return to the pool
+    // Note: this relies on the fact that the pool won't reject based on max texture size
+    auto hugeLayer = pool.get(renderThread.renderState(), pool.getMaxSize() / 64, 64);
+    EXPECT_GT(hugeLayer->getSizeInBytes(), pool.getMaxSize());
+    pool.putOrDelete(hugeLayer);
+    EXPECT_EQ(0u, pool.getCount()); // failed to put (so was destroyed instead)
+}
+
+RENDERTHREAD_TEST(OffscreenBufferPool, clear) {
+    EXPECT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
+    OffscreenBufferPool pool;
+
+    // Create many buffers, with several at each size
+    std::vector<OffscreenBuffer*> buffers;
+    for (int size = 32; size <= 128; size += 32) {
+        for (int i = 0; i < 10; i++) {
+            buffers.push_back(pool.get(renderThread.renderState(), size, size));
+        }
+    }
+    EXPECT_EQ(0u, pool.getCount()) << "Expect nothing inside";
+    for (auto& buffer : buffers) pool.putOrDelete(buffer);
+    EXPECT_EQ(40u, pool.getCount()) << "Expect all items added";
+    EXPECT_EQ(40, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
+    pool.clear();
+    EXPECT_EQ(0u, pool.getCount()) << "Expect all items cleared";
+
+    EXPECT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::OffscreenBuffer));
 }
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index df42a73..d1b1be9 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -22,7 +22,8 @@
 
 /**
  * A class containing a GPS clock timestamp.
- * It represents a measurement of the GPS receiver's clock.
+ *
+ * <p>It represents a measurement of the GPS receiver's clock.
  */
 public final class GnssClock implements Parcelable {
     // The following enumerations must be in sync with the values declared in gps.h
@@ -85,7 +86,7 @@
     }
 
     /**
-     * Returns true if {@link #getLeapSecond()} is available, false otherwise.
+     * Returns {@code true} if {@link #getLeapSecond()} is available, {@code false} otherwise.
      */
     public boolean hasLeapSecond() {
         return isFlagSet(HAS_LEAP_SECOND);
@@ -93,10 +94,12 @@
 
     /**
      * Gets the leap second associated with the clock's time.
-     * The sign of the value is defined by the following equation:
-     *      utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
      *
-     * The value is only available if {@link #hasLeapSecond()} is true.
+     * <p>The sign of the value is defined by the following equation:
+     * <pre>
+     *     UtcTimeNanos = TimeNanos + (FullBiasNanos + BiasNanos) - LeapSecond * 1,000,000,000</pre>
+     *
+     * <p>The value is only available if {@link #hasLeapSecond()} is {@code true}.
      */
     public int getLeapSecond() {
         return mLeapSecond;
@@ -123,18 +126,15 @@
     }
 
     /**
-     * Gets the GNSS receiver internal clock value in nanoseconds.
+     * Gets the GNSS receiver internal hardware clock value in nanoseconds.
      *
-     * 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 #getFullBiasNanos()} (when it is available) from this value.
+     * <p>This value is expected to be monotonically increasing while the hardware clock remains
+     * powered on. For the case of a hardware clock that is not continuously on, see the
+     * {@link #getHardwareClockDiscontinuityCount} field. The GPS time can be derived by adding
+     * {@link #getFullBiasNanos()} and {@link #getBiasNanos()} (when they are available) to this
+     * value. Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
      *
-     * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
-     * receiver can achieve. {@link #getTimeUncertaintyNanos()} should be available when GPS time is
-     * specified.
-     *
-     * Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
-     * The reported time includes {@link #getTimeUncertaintyNanos()}.
+     * <p>The error estimate for this value (if applicable) is {@link #getTimeUncertaintyNanos()}.
      */
     public long getTimeNanos() {
         return mTimeNanos;
@@ -150,7 +150,8 @@
     }
 
     /**
-     * Returns true if {@link #getTimeUncertaintyNanos()} is available, false otherwise.
+     * Returns {@code true} if {@link #getTimeUncertaintyNanos()} is available, {@code false}
+     * otherwise.
      */
     public boolean hasTimeUncertaintyNanos() {
         return isFlagSet(HAS_TIME_UNCERTAINTY);
@@ -158,9 +159,13 @@
 
     /**
      * 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 #hasTimeUncertaintyNanos()} is true.
+     * <p>The uncertainty is represented as an absolute (single sided) value.
+     *
+     * <p>The value is only available if {@link #hasTimeUncertaintyNanos()} is {@code true}.
+     *
+     * <p>This value is often effectively zero (it is the reference clock by which all other times
+     * and time uncertainties are measured), and thus this field may often be 0, or not provided.
      */
     public double getTimeUncertaintyNanos() {
         return mTimeUncertaintyNanos;
@@ -187,7 +192,7 @@
     }
 
     /**
-     * Returns true if {@link #getFullBiasNanos()} is available, false otherwise.
+     * Returns {@code true} if {@link #getFullBiasNanos()} is available, {@code false} otherwise.
      */
     public boolean hasFullBiasNanos() {
         return isFlagSet(HAS_FULL_BIAS);
@@ -197,14 +202,18 @@
      * 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 #getBiasUncertaintyNanos()} in
-     * it, and it should be used for quality check. The value is only available if
-     * {@link #hasFullBiasNanos()} is true.
+     * <p>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 is only available if {@link #hasFullBiasNanos()} is
+     * {@code true}.
      *
-     * The sign of the value is defined by the following equation:
-     *      local estimate of GPS time = time_ns + (full_bias_ns + bias_ns)
+     * <p>The error estimate for the sum of this field and {@link #getBiasNanos} is
+     * {@link #getBiasUncertaintyNanos()}.
+     *
+     * <p>The sign of the value is defined by the following equation:
+     *
+     * <pre>
+     *     local estimate of GPS time = TimeNanos + (FullBiasNanos + BiasNanos)</pre>
      */
     public long getFullBiasNanos() {
         return mFullBiasNanos;
@@ -231,7 +240,7 @@
     }
 
     /**
-     * Returns true if {@link #getBiasNanos()} is available, false otherwise.
+     * Returns {@code true} if {@link #getBiasNanos()} is available, {@code false} otherwise.
      */
     public boolean hasBiasNanos() {
         return isFlagSet(HAS_BIAS);
@@ -239,9 +248,14 @@
 
     /**
      * Gets the clock's sub-nanosecond bias.
-     * The reported bias includes {@link #getBiasUncertaintyNanos()}.
      *
-     * The value is only available if {@link #hasBiasNanos()} is true.
+     * <p>See the description of how this field is part of converting from hardware clock time, to
+     * GPS time, in {@link #getFullBiasNanos()}.
+     *
+     * <p>The error estimate for the sum of this field and {@link #getFullBiasNanos} is
+     * {@link #getBiasUncertaintyNanos()}.
+     *
+     * <p>The value is only available if {@link #hasBiasNanos()} is {@code true}.
      */
     public double getBiasNanos() {
         return mBiasNanos;
@@ -268,7 +282,8 @@
     }
 
     /**
-     * Returns true if {@link #getBiasUncertaintyNanos()} is available, false otherwise.
+     * Returns {@code true} if {@link #getBiasUncertaintyNanos()} is available, {@code false}
+     * otherwise.
      */
     public boolean hasBiasUncertaintyNanos() {
         return isFlagSet(HAS_BIAS_UNCERTAINTY);
@@ -277,7 +292,10 @@
     /**
      * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
      *
-     * The value is only available if {@link #hasBiasUncertaintyNanos()} is true.
+     * <p>See the description of how this field provides the error estimate in the conversion from
+     * hardware clock time, to GPS time, in {@link #getFullBiasNanos()}.
+     *
+     * <p>The value is only available if {@link #hasBiasUncertaintyNanos()} is {@code true}.
      */
     public double getBiasUncertaintyNanos() {
         return mBiasUncertaintyNanos;
@@ -304,7 +322,8 @@
     }
 
     /**
-     * Returns true if {@link #getDriftNanosPerSecond()} is available, false otherwise.
+     * Returns {@code true} if {@link #getDriftNanosPerSecond()} is available, {@code false}
+     * otherwise.
      */
     public boolean hasDriftNanosPerSecond() {
         return isFlagSet(HAS_DRIFT);
@@ -312,10 +331,12 @@
 
     /**
      * 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 #getDriftUncertaintyNanosPerSecond()}.
      *
-     * The value is only available if {@link #hasDriftNanosPerSecond()} is true.
+     * <p>A positive value indicates that the frequency is higher than the nominal (e.g. GPS master
+     * clock) frequency. The error estimate for this reported drift is
+     * {@link #getDriftUncertaintyNanosPerSecond()}.
+     *
+     * <p>The value is only available if {@link #hasDriftNanosPerSecond()} is {@code true}.
      */
     public double getDriftNanosPerSecond() {
         return mDriftNanosPerSecond;
@@ -342,7 +363,8 @@
     }
 
     /**
-     * Returns true if {@link #getDriftUncertaintyNanosPerSecond()} is available, false otherwise.
+     * Returns {@code true} if {@link #getDriftUncertaintyNanosPerSecond()} is available,
+     * {@code false} otherwise.
      */
     public boolean hasDriftUncertaintyNanosPerSecond() {
         return isFlagSet(HAS_DRIFT_UNCERTAINTY);
@@ -351,7 +373,8 @@
     /**
      * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
      *
-     * The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is true.
+     * <p>The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is
+     * {@code true}.
      */
     public double getDriftUncertaintyNanosPerSecond() {
         return mDriftUncertaintyNanosPerSecond;
@@ -368,7 +391,29 @@
     }
 
     /**
-     * Gets count of last hardware clock discontinuity.
+     * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
+     * @hide
+     */
+    @TestApi
+    public void resetDriftUncertaintyNanosPerSecond() {
+        resetFlag(HAS_DRIFT_UNCERTAINTY);
+        mDriftUncertaintyNanosPerSecond = Double.NaN;
+    }
+
+    /**
+     * Gets count of hardware clock discontinuities.
+     *
+     * <p>When this value stays the same, vs. a value in a previously reported {@link GnssClock}, it
+     * can be safely assumed that the {@code TimeNanos} value has been derived from a clock that has
+     * been running continuously - e.g. a single continuously powered crystal oscillator, and thus
+     * the {@code (FullBiasNanos + BiasNanos)} offset can be modelled with traditional clock bias
+     * &amp; drift models.
+     *
+     * <p>Each time this value changes, vs. the value in a previously reported {@link GnssClock},
+     * that suggests the hardware clock may have experienced a discontinuity (e.g. a power cycle or
+     * other anomaly), so that any assumptions about modelling a smoothly changing
+     * {@code (FullBiasNanos + BiasNanos)} offset, and a smoothly growing {@code (TimeNanos)}
+     * between this and the previously reported {@code GnssClock}, should be reset.
      */
     public int getHardwareClockDiscontinuityCount() {
         return mHardwareClockDiscontinuityCount;
@@ -383,16 +428,6 @@
         mHardwareClockDiscontinuityCount = value;
     }
 
-    /**
-     * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
-     * @hide
-     */
-    @TestApi
-    public void resetDriftUncertaintyNanosPerSecond() {
-        resetFlag(HAS_DRIFT_UNCERTAINTY);
-        mDriftUncertaintyNanosPerSecond = Double.NaN;
-    }
-
     public static final Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
         @Override
         public GnssClock createFromParcel(Parcel parcel) {
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index d78ccee..761ee22 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -67,18 +67,21 @@
     public @interface MultipathIndicator {}
 
     /**
-     * The indicator is not available or it is unknown.
+     * The indicator is not available or the presence or absence of multipath is unknown.
      */
     public static final int MULTIPATH_INDICATOR_UNKNOWN = 0;
 
     /**
-     * The measurement has been indicated to use multi-path.
+     * The measurement shows signs of multi-path.
      */
     public static final int MULTIPATH_INDICATOR_DETECTED = 1;
 
     /**
-     * The measurement has been indicated not tu use multi-path.
+     * The measurement shows no signs of multi-path.
      */
+    public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2;
+
+    /** @removed */
     public static final int MULTIPATH_INDICATOR_NOT_USED = 2;
 
     /** This GNSS measurement's tracking state is invalid or unknown. */
@@ -192,15 +195,17 @@
     }
 
     /**
-     * Gets the Pseudo-random number (PRN).
-     * Range: [1, 32]
+     * Gets the satellite ID.
+     *
+     * <p>Interpretation depends on {@link #getConstellationType()}.
+     * See {@link GnssStatus#getSvid(int)}.
      */
     public int getSvid() {
         return mSvid;
     }
 
     /**
-     * Sets the Pseud-random number (PRN).
+     * Sets the Satellite ID.
      * @hide
      */
     @TestApi
@@ -209,7 +214,10 @@
     }
 
     /**
-     * Getst the constellation type.
+     * Gets the constellation type.
+     *
+     * <p>The return value is one of those constants with {@code CONSTELLATION_} prefix in
+     * {@link GnssStatus}.
      */
     @GnssStatus.ConstellationType
     public int getConstellationType() {
@@ -228,13 +236,14 @@
     /**
      * 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
+     * <p>The reference receiver's time from which this is offset is specified by
      * {@link GnssClock#getTimeNanos()}.
      *
-     * The sign of this value is given by the following equation:
-     *      measurement time = time_ns + time_offset_ns
+     * <p>The sign of this value is given by the following equation:
+     * <pre>
+     *      measurement time = TimeNanos + TimeOffsetNanos</pre>
      *
-     * The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
+     * <p>The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
      * accuracy.
      */
     public double getTimeOffsetNanos() {
@@ -252,9 +261,10 @@
 
     /**
      * Gets per-satellite sync state.
-     * It represents the current sync state for the associated satellite.
      *
-     * This value helps interpret {@link #getReceivedSvTimeNanos()}.
+     * <p>It represents the current sync state for the associated satellite.
+     *
+     * <p>This value helps interpret {@link #getReceivedSvTimeNanos()}.
      */
     public int getState() {
         return mState;
@@ -271,7 +281,8 @@
 
     /**
      * Gets a string representation of the 'sync state'.
-     * For internal and logging use only.
+     *
+     * <p>For internal and logging use only.
      */
     private String getStateString() {
         if (mState == STATE_UNKNOWN) {
@@ -335,66 +346,79 @@
     /**
      * Gets the received GNSS satellite time, at the measurement time, in nanoseconds.
      *
-     * For GPS &amp; QZSS, this is:
-     *   Received GPS Time-of-Week at the measurement time, in nanoseconds.
-     *   The value is relative to the beginning of the current GPS week.
+     * <p>For GPS &amp; QZSS, this is:
+     * <ul>
+     * <li>Received GPS Time-of-Week at the measurement time, in nanoseconds.</li>
+     * <li>The value is relative to the beginning of the current GPS week.</li>
+     * </ul>
      *
-     *   Given the highest sync state that can be achieved, per each satellite, valid range
-     *   for this field can be:
+     * <p>Given the highest sync state that can be achieved, per each satellite, valid range
+     * for this field can be:
+     * <pre>
      *     Searching       : [ 0       ]   : STATE_UNKNOWN
      *     C/A code lock   : [ 0   1ms ]   : STATE_CODE_LOCK is set
      *     Bit sync        : [ 0  20ms ]   : STATE_BIT_SYNC is set
      *     Subframe sync   : [ 0    6s ]   : STATE_SUBFRAME_SYNC is set
-     *     TOW decoded     : [ 0 1week ]   : STATE_TOW_DECODED is set
+     *     TOW decoded     : [ 0 1week ]   : STATE_TOW_DECODED is set</pre>
      *
-     *   Note well: if there is any ambiguity in integer millisecond,
-     *   STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+     * <p>Note well: if there is any ambiguity in integer millisecond, {@code STATE_MSEC_AMBIGUOUS}
+     * should be set accordingly, in the 'state' field.
      *
-     *   This value must be populated if 'state' != STATE_UNKNOWN.
+     * <p>This value must be populated if 'state' != {@code STATE_UNKNOWN}.
      *
-     * For Glonass, this is:
-     *   Received Glonass time of day, at the measurement time in nanoseconds.
+     * <p>For Glonass, this is:
+     * <ul>
+     * <li>Received Glonass time of day, at the measurement time in nanoseconds.</li>
+     * </ul>
      *
-     *   Given the highest sync state that can be achieved, per each satellite, valid range for
-     *   this field can be:
+     * <p>Given the highest sync state that can be achieved, per each satellite, valid range for
+     * this field can be:
+     * <pre>
      *     Searching       : [ 0       ]   : STATE_UNKNOWN
      *     C/A code lock   : [ 0   1ms ]   : STATE_CODE_LOCK is set
-     *    Symbol sync    : [ 0  10ms ]   : STATE_SYMBOL_SYNC is set
-     *    Bit sync       : [ 0  20ms ]   : STATE_BIT_SYNC is set
-     *     String sync     : [ 0    2s ]   :  STATE_GLO_STRING_SYNC is set
-     *    Time of day      : [ 0  1day ]   : STATE_GLO_TOD_DECODED is set
+     *     Symbol sync     : [ 0  10ms ]   : STATE_SYMBOL_SYNC is set
+     *     Bit sync        : [ 0  20ms ]   : STATE_BIT_SYNC is set
+     *     String sync     : [ 0    2s ]   : STATE_GLO_STRING_SYNC is set
+     *     Time of day     : [ 0  1day ]   : STATE_GLO_TOD_DECODED is set</pre>
      *
-     * For Beidou, this is:
-     *   Received Beidou time of week, at the measurement time in nanoseconds.
+     * <p>For Beidou, this is:
+     * <ul>
+     * <li>Received Beidou time of week, at the measurement time in nanoseconds.</li>
+     * </ul>
      *
-     *   Given the highest sync state that can be achieved, per each satellite, valid range for
-     *   this field can be:
+     * <p>Given the highest sync state that can be achieved, per each satellite, valid range for
+     * this field can be:
+     * <pre>
      *     Searching       : [ 0       ]   : STATE_UNKNOWN
      *     C/A code lock   : [ 0   1ms ]   : STATE_CODE_LOCK is set
      *     Bit sync (D2)   : [ 0   2ms ]   : STATE_BDS_D2_BIT_SYNC is set
      *     Bit sync (D1)   : [ 0  20ms ]   : STATE_BIT_SYNC is set
      *     Subframe (D2)   : [ 0  0.6s ]   : STATE_BDS_D2_SUBFRAME_SYNC is set
      *     Subframe (D1)   : [ 0    6s ]   : STATE_SUBFRAME_SYNC is set
-     *     Time of week    : [ 0 1week ]   : STATE_TOW_DECODED is set
+     *     Time of week    : [ 0 1week ]   : STATE_TOW_DECODED is set</pre>
      *
-     * For Galileo, this is:
-     *   Received Galileo time of week, at the measurement time in nanoseconds.
+     * <p>For Galileo, this is:
+     * <ul>
+     * <li>Received Galileo time of week, at the measurement time in nanoseconds.</li>
+     * </ul>
+     * <pre>
+     *     E1BC code lock   : [ 0   4ms ]  : STATE_GAL_E1BC_CODE_LOCK is set
+     *     E1C 2nd code lock: [ 0 100ms ]  : STATE_GAL_E1C_2ND_CODE_LOCK is set
+     *     E1B page         : [ 0    2s ]  : STATE_GAL_E1B_PAGE_SYNC is set
+     *     Time of week     : [ 0 1week ]  : STATE_GAL_TOW_DECODED is set</pre>
      *
-     *     E1BC code lock  : [ 0   4ms ]   : STATE_GAL_E1BC_CODE_LOCK is set
-     *     E1C 2nd code lock : [ 0   100ms ]   : STATE_GAL_E1C_2ND_CODE_LOCK is set
+     * <p>For SBAS, this is:
+     * <ul>
+     * <li>Received SBAS time, at the measurement time in nanoseconds.</li>
+     * </ul>
      *
-     *     E1B page        : [ 0    2s ]   : STATE_GAL_E1B_PAGE_SYNC is set
-     *     Time of week    : [ 0 1week ]   : STATE_GAL_TOW_DECODED is set
-     *
-     *   For SBAS, this is:
-     *     Received SBAS time, at the measurement time in nanoseconds.
-     *
-     *   Given the highest sync state that can be achieved, per each satellite, valid range for
-     *   this field can be:
+     * <p>Given the highest sync state that can be achieved, per each satellite, valid range for
+     * this field can be:
+     * <pre>
      *     Searching       : [ 0       ]   : STATE_UNKNOWN
      *     C/A code lock   : [ 0   1ms ]   : STATE_CODE_LOCK is set
      *     Symbol sync     : [ 0   2ms ]   : STATE_SYMBOL_SYNC is set
-     *     Message         : [ 0    1s ]   : STATE_SBAS_SYNC is set
+     *     Message         : [ 0    1s ]   : STATE_SBAS_SYNC is set</pre>
      */
     public long getReceivedSvTimeNanos() {
         return mReceivedSvTimeNanos;
@@ -410,7 +434,7 @@
     }
 
     /**
-     * Gets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
+     * Gets the error estimate (1-sigma) for the received GNSS time, in nanoseconds.
      */
     public long getReceivedSvTimeUncertaintyNanos() {
         return mReceivedSvTimeUncertaintyNanos;
@@ -427,9 +451,10 @@
 
     /**
      * Gets the Carrier-to-noise density in dB-Hz.
-     * Range: [0, 63].
      *
-     * The value contains the measured C/N0 for the signal at the antenna input.
+     * <p>Typical range: 10-50 db-Hz.
+     *
+     * <p>The value contains the measured C/N0 for the signal at the antenna input.
      */
     public double getCn0DbHz() {
         return mCn0DbHz;
@@ -447,16 +472,18 @@
     /**
      * Gets the Pseudorange rate at the timestamp in m/s.
      *
-     * The reported value includes {@link #getPseudorangeRateUncertaintyMetersPerSecond()}.
+     * <p>The error estimate for this value is
+     * {@link #getPseudorangeRateUncertaintyMetersPerSecond()}.
      *
-     * The value is uncorrected, hence corrections for receiver and satellite clock frequency errors
-     * should not be included.
+     * <p>The value is uncorrected, i.e. corrections for receiver and satellite clock frequency
+     * errors are not included.
      *
-     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver. The
+     * <p>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)
+     * <pre>
+     *      pseudorange rate = -k * doppler shift   (where k is a constant)</pre>
      */
     public double getPseudorangeRateMetersPerSecond() {
         return mPseudorangeRateMetersPerSecond;
@@ -473,7 +500,8 @@
 
     /**
      * Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
-     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * <p>The uncertainty is represented as an absolute (single sided) value.
      */
     public double getPseudorangeRateUncertaintyMetersPerSecond() {
         return mPseudorangeRateUncertaintyMetersPerSecond;
@@ -490,7 +518,8 @@
 
     /**
      * Gets 'Accumulated Delta Range' state.
-     * It indicates whether {@link #getAccumulatedDeltaRangeMeters()} is reset or there is a
+     *
+     * <p>It indicates whether {@link #getAccumulatedDeltaRangeMeters()} is reset or there is a
      * cycle slip (indicating 'loss of lock').
      */
     public int getAccumulatedDeltaRangeState() {
@@ -508,7 +537,8 @@
 
     /**
      * Gets a string representation of the 'Accumulated Delta Range state'.
-     * For internal and logging use only.
+     *
+     * <p>For internal and logging use only.
      */
     private String getAccumulatedDeltaRangeStateString() {
         if (mAccumulatedDeltaRangeState == ADR_STATE_UNKNOWN) {
@@ -536,14 +566,17 @@
 
     /**
      * Gets the accumulated delta range since the last channel reset, in meters.
-     * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyMeters()}.
      *
-     * The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+     * <p>The error estimate for this value is {@link #getAccumulatedDeltaRangeUncertaintyMeters()}.
      *
-     * A positive value indicates that the SV is moving away from the receiver.
+     * <p>The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+     *
+     * <p>A positive value indicates that the SV is moving away from the receiver.
      * 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)
+     *
+     * <pre>
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)</pre>
      */
     public double getAccumulatedDeltaRangeMeters() {
         return mAccumulatedDeltaRangeMeters;
@@ -560,9 +593,10 @@
 
     /**
      * Gets the accumulated delta range's uncertainty (1-Sigma) in meters.
-     * The uncertainty is represented as an absolute (single sided) value.
      *
-     * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+     * <p>The uncertainty is represented as an absolute (single sided) value.
+     *
+     * <p>The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
      */
     public double getAccumulatedDeltaRangeUncertaintyMeters() {
         return mAccumulatedDeltaRangeUncertaintyMeters;
@@ -571,7 +605,7 @@
     /**
      * Sets the accumulated delta range's uncertainty (1-sigma) in meters.
      *
-     * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+     * <p>The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
      *
      * @hide
      */
@@ -581,17 +615,20 @@
     }
 
     /**
-     * Returns true if {@link #getCarrierFrequencyHz()} is available, false otherwise.
+     * Returns {@code true} if {@link #getCarrierFrequencyHz()} is available, {@code false}
+     * otherwise.
      */
     public boolean hasCarrierFrequencyHz() {
         return isFlagSet(HAS_CARRIER_FREQUENCY);
     }
 
     /**
-     * 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.
+     * Gets the carrier frequency at which codes and messages are modulated.
      *
-     * The value is only available if {@link #hasCarrierFrequencyHz()} is true.
+     * <p>For GPS, e.g., it can be L1 or L2.  If the field is not set, it is the primary common use
+     * frequency, e.g. L1 for GPS.
+     *
+     * <p>The value is only available if {@link #hasCarrierFrequencyHz()} is {@code true}.
      */
     public float getCarrierFrequencyHz() {
         return mCarrierFrequencyHz;
@@ -618,7 +655,7 @@
     }
 
     /**
-     * Returns true if {@link #getCarrierCycles()} is available, false otherwise.
+     * Returns {@code true} if {@link #getCarrierCycles()} is available, {@code false} otherwise.
      */
     public boolean hasCarrierCycles() {
         return isFlagSet(HAS_CARRIER_CYCLES);
@@ -626,9 +663,10 @@
 
     /**
      * The number of full carrier cycles between the satellite and the receiver.
-     * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
      *
-     * The value is only available if {@link #hasCarrierCycles()} is true.
+     * <p>The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
+     *
+     * <p>The value is only available if {@link #hasCarrierCycles()} is {@code true}.
      */
     public long getCarrierCycles() {
         return mCarrierCycles;
@@ -655,7 +693,7 @@
     }
 
     /**
-     * Returns true if {@link #getCarrierPhase()} is available, false otherwise.
+     * Returns {@code true} if {@link #getCarrierPhase()} is available, {@code false} otherwise.
      */
     public boolean hasCarrierPhase() {
         return isFlagSet(HAS_CARRIER_PHASE);
@@ -663,13 +701,16 @@
 
     /**
      * Gets the RF phase detected by the receiver.
-     * 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 #getCarrierFrequencyHz()}.
-     * The reported carrier-phase includes {@link #getCarrierPhaseUncertainty()}.
+     * <p>Range: [0.0, 1.0].
      *
-     * The value is only available if {@link #hasCarrierPhase()} is true.
+     * <p>This is the fractional part of the complete carrier phase measurement.
+     *
+     * <p>The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
+     *
+     * <p>The error estimate for this value is {@link #getCarrierPhaseUncertainty()}.
+     *
+     * <p>The value is only available if {@link #hasCarrierPhase()} is {@code true}.
      */
     public double getCarrierPhase() {
         return mCarrierPhase;
@@ -696,7 +737,8 @@
     }
 
     /**
-     * Returns true if {@link #getCarrierPhaseUncertainty()} is available, false otherwise.
+     * Returns {@code true} if {@link #getCarrierPhaseUncertainty()} is available, {@code false}
+     * otherwise.
      */
     public boolean hasCarrierPhaseUncertainty() {
         return isFlagSet(HAS_CARRIER_PHASE_UNCERTAINTY);
@@ -704,9 +746,10 @@
 
     /**
      * Gets the carrier-phase's uncertainty (1-Sigma).
-     * The uncertainty is represented as an absolute (single sided) value.
      *
-     * The value is only available if {@link #hasCarrierPhaseUncertainty()} is true.
+     * <p>The uncertainty is represented as an absolute (single sided) value.
+     *
+     * <p>The value is only available if {@link #hasCarrierPhaseUncertainty()} is {@code true}.
      */
     public double getCarrierPhaseUncertainty() {
         return mCarrierPhaseUncertainty;
@@ -751,7 +794,8 @@
 
     /**
      * Gets a string representation of the 'multi-path indicator'.
-     * For internal and logging use only.
+     *
+     * <p>For internal and logging use only.
      */
     private String getMultipathIndicatorString() {
         switch(mMultipathIndicator) {
@@ -767,7 +811,7 @@
     }
 
     /**
-     * Returns true if {@link #getSnrInDb()} is available, false otherwise.
+     * Returns {@code true} if {@link #getSnrInDb()} is available, {@code false} otherwise.
      */
     public boolean hasSnrInDb() {
         return isFlagSet(HAS_SNR);
@@ -776,7 +820,7 @@
     /**
      * Gets the Signal-to-Noise ratio (SNR) in dB.
      *
-     * The value is only available if {@link #hasSnrInDb()} is true.
+     * <p>The value is only available if {@link #hasSnrInDb()} is {@code true}.
      */
     public double getSnrInDb() {
         return mSnrInDb;
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index ec252a8..3151694 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.TestApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.os.Parcel;
@@ -33,29 +34,11 @@
  * Events are delivered to registered instances of {@link Callback}.
  */
 public final class GnssMeasurementsEvent implements Parcelable {
-    /**
-     * The status of the GNSS measurements event.
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
-    public @interface GnssMeasurementsStatus {}
-
-    /**
-     * The system does not support tracking of GNSS Measurements. This status will not change in the
-     * future.
-     */
+    /** @removed */
     public static final int STATUS_NOT_SUPPORTED = 0;
-
-    /**
-     * GNSS Measurements are successfully being tracked, it will receive updates once they are
-     * available.
-     */
+    /** @removed */
     public static final int STATUS_READY = 1;
-
-    /**
-     * GNSS provider or Location is disabled, updates will not be received until they are enabled.
-     */
+    /** @removed */
     public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
 
     private final GnssClock mClock;
@@ -68,6 +51,32 @@
      * {@link LocationManager#registerGnssMeasurementsCallback}.
      */
     public static abstract class Callback {
+        /**
+         * The status of the GNSS measurements event.
+         * @hide
+         */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_LOCATION_DISABLED})
+        public @interface GnssMeasurementsStatus {}
+
+        /**
+         * The system does not support tracking of GNSS Measurements.
+         *
+         * <p>This status will not change in the future.
+         */
+        public static final int STATUS_NOT_SUPPORTED = 0;
+
+        /**
+         * 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.
+         */
+        public static final int STATUS_LOCATION_DISABLED = 2;
 
         /**
          * Reports the latest collected GNSS Measurements.
@@ -80,6 +89,10 @@
         public void onStatusChanged(@GnssMeasurementsStatus int status) {}
     }
 
+    /**
+     * @hide
+     */
+    @TestApi
     public GnssMeasurementsEvent(GnssClock clock, GnssMeasurement[] measurements) {
         if (clock == null) {
             throw new InvalidParameterException("Parameter 'clock' must not be null.");
@@ -94,6 +107,10 @@
         mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection);
     }
 
+    /**
+     * Gets the GNSS receiver clock information associated with the measurements for the current
+     * event.
+     */
     @NonNull
     public GnssClock getClock() {
         return mClock;
diff --git a/core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl b/location/java/android/location/GnssNavigationMessage.aidl
similarity index 62%
rename from core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl
rename to location/java/android/location/GnssNavigationMessage.aidl
index a2c62cd..1cdd510 100644
--- a/core/java/android/net/IConnectivityMetricsLoggerSubscriber.aidl
+++ b/location/java/android/location/GnssNavigationMessage.aidl
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package android.net;
+package android.location;
 
-import android.net.ConnectivityMetricsEvent;
-
-/** {@hide} */
-oneway interface IConnectivityMetricsLoggerSubscriber {
-
-    void onEvents(in ConnectivityMetricsEvent[] events);
-}
+parcelable GnssNavigationMessage;
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index a5eace8..aa26111 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -34,7 +34,7 @@
     private static final byte[] EMPTY_ARRAY = new byte[0];
 
     /**
-     * The type of the GPS Clock.
+     * The type of the GNSS Navigation Message
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
@@ -81,6 +81,51 @@
      */
     public static final int STATUS_PARITY_REBUILT = (1<<1);
 
+    /**
+     * Used for receiving GNSS satellite Navigation Messages from the GNSS engine.
+     *
+     * <p>You can implement this interface and call
+     * {@link LocationManager#registerGnssNavigationMessageCallback}.
+     */
+    public static abstract class Callback {
+        /**
+         * The status of GNSS measurements event.
+         * @hide
+         */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_LOCATION_DISABLED})
+        public @interface GnssNavigationMessageStatus {}
+
+        /**
+         * The system does not support tracking of GNSS Navigation Messages.
+         *
+         * This status will not change in the future.
+         */
+        public static final int STATUS_NOT_SUPPORTED = 0;
+
+        /**
+         * GNSS Navigation Messages are successfully being tracked, it will receive updates once
+         * they are available.
+         */
+        public static final int STATUS_READY = 1;
+
+        /**
+         * GNSS provider or Location is disabled, updated will not be received until they are
+         * enabled.
+         */
+        public static final int STATUS_LOCATION_DISABLED = 2;
+
+        /**
+         * Returns the latest collected GNSS Navigation Message.
+         */
+        public void onGnssNavigationMessageReceived(GnssNavigationMessage event) {}
+
+        /**
+         * Returns the latest status of the GNSS Navigation Messages sub-system.
+         */
+        public void onStatusChanged(@GnssNavigationMessageStatus int status) {}
+    }
+
     // End enumerations in sync with gps.h
 
     private int mType;
@@ -170,15 +215,16 @@
     }
 
     /**
-     * Gets the Pseudo-random number.
-     * Range: [1, 32].
+     * Gets the satellite ID.
+     *
+     * <p>Range varies by constellation.  See definition at {@code GnssStatus#getSvid(int)}
      */
     public int getSvid() {
         return mSvid;
     }
 
     /**
-     * Sets the Pseud-random number.
+     * Sets the satellite ID.
      * @hide
      */
     @TestApi
@@ -187,10 +233,25 @@
     }
 
     /**
-     * Gets the Message Identifier.
-     * It provides an index so the complete Navigation Message can be assembled. i.e. for L1 C/A
-     * 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.
+     * Gets the Message identifier.
+     *
+     * <p>This provides an index to help with complete Navigation Message assembly. Similar
+     * identifiers within the data bits themselves often supplement this information, in ways even
+     * more specific to each message type; see the relevant satellite constellation ICDs for
+     * details.
+     *
+     * <ul>
+     * <li> For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame id' of the
+     * navigation message, in the range of 1-25 (Subframe 1, 2, 3 does not contain a 'frame id' and
+     * this value can be set to -1.)</li>
+     * <li> For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.</li>
+     * <li> For BeiDou D1, this refers to the frame number in the range of 1-24</li>
+     * <li> For Beidou D2, this refers to the frame number, in the range of 1-120</li>
+     * <li> For Galileo F/NAV nominal frame structure, this refers to the subframe number, in the
+     * range of 1-12</li>
+     * <li> For Galileo I/NAV nominal frame structure, this refers to the subframe number in the
+     * range of 1-24</li>
+     * </ul>
      */
     public int getMessageId() {
         return mMessageId;
@@ -206,10 +267,18 @@
     }
 
     /**
-     * Gets the Sub-message Identifier.
-     * If required by {@link #getType()}, this value contains a sub-index within the current message
-     * (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.
+     * Gets the sub-message identifier, relevant to the {@link #getType()} of the message.
+     *
+     * <ul>
+     * <li> For GPS L1 C/A, BeiDou D1 &amp; BeiDou D2, the submessage id corresponds to the subframe
+     * number of the navigation message, in the range of 1-5.</li>
+     * <li>For Glonass L1 C/A, this refers to the String number, in the range from 1-15</li>
+     * <li>For Galileo F/NAV, this refers to the page type in the range 1-6</li>
+     * <li>For Galileo I/NAV, this refers to the word type in the range 1-10+</li>
+     * <li>For Galileo in particular, the type information embedded within the data bits may be even
+     * more useful in interpretation, than the nominal page and word types provided in this
+     * field.</li>
+     * </ul>
      */
     public int getSubmessageId() {
         return mSubmessageId;
@@ -225,8 +294,25 @@
     }
 
     /**
-     * Gets the data associated with the Navigation Message.
-     * The bytes (or words) specified using big endian format (MSB first).
+     * Gets the data of the reported GPS message.
+     *
+     * <p>The bytes (or words) specified using big endian format (MSB first).
+     *
+     * <ul>
+     * <li>For GPS L1 C/A, Beidou D1 &amp; Beidou D2, each subframe contains 10 30-bit words. Each
+     * word (30 bits) should be fit into the last 30 bits in a 4-byte word (skip B31 and B32), with
+     * MSB first, for a total of 40 bytes, covering a time period of 6, 6, and 0.6 seconds,
+     * respectively.</li>
+     * <li>For Glonass L1 C/A, each string contains 85 data bits, including the checksum.  These
+     * bits should be fit into 11 bytes, with MSB first (skip B86-B88), covering a time period of 2
+     * seconds.</li>
+     * <li>For Galileo F/NAV, each word consists of 238-bit (sync &amp; tail symbols excluded). Each
+     * word should be fit into 30-bytes, with MSB first (skip B239, B240), covering a time period of
+     * 10 seconds.</li>
+     * <li>For Galileo I/NAV, each page contains 2 page parts, even and odd, with a total of 2x114 =
+     * 228 bits, (sync &amp; tail excluded) that should be fit into 29 bytes, with MSB first (skip
+     * B229-B232).</li>
+     * </ul>
      */
     @NonNull
     public byte[] getData() {
diff --git a/location/java/android/location/GnssNavigationMessageCallbackTransport.java b/location/java/android/location/GnssNavigationMessageCallbackTransport.java
index 4204b99..1eafd02 100644
--- a/location/java/android/location/GnssNavigationMessageCallbackTransport.java
+++ b/location/java/android/location/GnssNavigationMessageCallbackTransport.java
@@ -20,12 +20,12 @@
 import android.os.RemoteException;
 
 /**
- * A handler class to manage transport callback for {@link GnssNavigationMessageEvent.Callback}.
+ * A handler class to manage transport callback for {@link GnssNavigationMessage.Callback}.
  *
  * @hide
  */
 class GnssNavigationMessageCallbackTransport
-        extends LocalListenerHelper<GnssNavigationMessageEvent.Callback> {
+        extends LocalListenerHelper<GnssNavigationMessage.Callback> {
     private final ILocationManager mLocationManager;
 
     private final IGnssNavigationMessageListener mListenerTransport = new ListenerTransport();
@@ -51,11 +51,11 @@
 
     private class ListenerTransport extends IGnssNavigationMessageListener.Stub {
         @Override
-        public void onGnssNavigationMessageReceived(final GnssNavigationMessageEvent event) {
-            ListenerOperation<GnssNavigationMessageEvent.Callback> operation =
-                    new ListenerOperation<GnssNavigationMessageEvent.Callback>() {
+        public void onGnssNavigationMessageReceived(final GnssNavigationMessage event) {
+            ListenerOperation<GnssNavigationMessage.Callback> operation =
+                    new ListenerOperation<GnssNavigationMessage.Callback>() {
                 @Override
-                public void execute(GnssNavigationMessageEvent.Callback callback)
+                public void execute(GnssNavigationMessage.Callback callback)
                         throws RemoteException {
                     callback.onGnssNavigationMessageReceived(event);
                 }
@@ -65,10 +65,10 @@
 
         @Override
         public void onStatusChanged(final int status) {
-            ListenerOperation<GnssNavigationMessageEvent.Callback> operation =
-                    new ListenerOperation<GnssNavigationMessageEvent.Callback>() {
+            ListenerOperation<GnssNavigationMessage.Callback> operation =
+                    new ListenerOperation<GnssNavigationMessage.Callback>() {
                 @Override
-                public void execute(GnssNavigationMessageEvent.Callback callback)
+                public void execute(GnssNavigationMessage.Callback callback)
                         throws RemoteException {
                     callback.onStatusChanged(status);
                 }
diff --git a/location/java/android/location/GnssNavigationMessageEvent.java b/location/java/android/location/GnssNavigationMessageEvent.java
index 992dfc3..f7e5665 100644
--- a/location/java/android/location/GnssNavigationMessageEvent.java
+++ b/location/java/android/location/GnssNavigationMessageEvent.java
@@ -28,10 +28,11 @@
 /**
  * A class implementing a container for data associated with a navigation message event.
  * Events are delivered to registered instances of {@link Callback}.
+ * @removed
  */
 public final class GnssNavigationMessageEvent implements Parcelable {
     /**
-     * The status of GPS measurements event.
+     * The status of GNSS measurements event.
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
@@ -39,38 +40,40 @@
     public @interface GnssNavigationMessageStatus {}
 
     /**
-     * The system does not support tracking of GPS Navigation Messages. This status will not change
-     * in the future.
+     * The system does not support tracking of GNSS Navigation Messages.
+     *
+     * This status will not change in the future.
      */
     public static final int STATUS_NOT_SUPPORTED = 0;
 
     /**
-     * GPS Navigation Messages are successfully being tracked, it will receive updates once they are
-     * available.
+     * GNSS Navigation Messages 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, updated will not be received until they are enabled.
+     * GNSS provider or Location is disabled, updated will not be received until they are enabled.
      */
     public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
 
     private final GnssNavigationMessage mNavigationMessage;
 
     /**
-     * Used for receiving GPS satellite Navigation Messages from the GPS engine.
-     * You can implement this interface and call
+     * Used for receiving GNSS satellite Navigation Messages from the GNSS engine.
+     *
+     * <p>You can implement this interface and call
      * {@link LocationManager#registerGnssNavigationMessageCallback}.
      */
     public static abstract class Callback {
 
         /**
-         * Returns the latest collected GPS Navigation Message.
+         * Returns the latest collected GNSS Navigation Message.
          */
         public void onGnssNavigationMessageReceived(GnssNavigationMessageEvent event) {}
 
         /**
-         * Returns the latest status of the GPS Navigation Messages sub-system.
+         * Returns the latest status of the GNSS Navigation Messages sub-system.
          */
         public void onStatusChanged(@GnssNavigationMessageStatus int status) {}
     }
diff --git a/location/java/android/location/GnssNmeaListener.java b/location/java/android/location/GnssNmeaListener.java
index 6c9b08a..756ae49 100644
--- a/location/java/android/location/GnssNmeaListener.java
+++ b/location/java/android/location/GnssNmeaListener.java
@@ -23,8 +23,9 @@
 * See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
 * You can implement this interface and call {@link LocationManager#addNmeaListener}
 * to receive NMEA data from the GNSS engine.
+* @removed
 */
 public interface GnssNmeaListener {
     /** Called when an NMEA message is received. */
     void onNmeaReceived(long timestamp, String nmea);
-}
\ No newline at end of file
+}
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index d76feec..e834c30 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -23,9 +23,11 @@
 
 /**
  * This class represents the current state of the GNSS engine.
- * This class is used in conjunction with the {@link GnssStatusCallback}.
+ * This class is used in conjunction with the {@link GnssStatus.Callback}.
  */
 public final class GnssStatus {
+    // these must match the definitions in gps.h
+
     /** Unknown constellation type. */
     public static final int CONSTELLATION_UNKNOWN = 0;
     /** Constellation type constant for GPS. */
@@ -41,16 +43,6 @@
     /** Constellation type constant for Galileo. */
     public static final int CONSTELLATION_GALILEO = 6;
 
-    /**
-     * Constellation type.
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({CONSTELLATION_UNKNOWN, CONSTELLATION_GPS, CONSTELLATION_SBAS, CONSTELLATION_GLONASS,
-            CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO})
-    public @interface ConstellationType {}
-
-    // these must match the definitions in gps.h
     /** @hide */
     public static final int GNSS_SV_FLAGS_NONE = 0;
     /** @hide */
@@ -67,6 +59,42 @@
     /** @hide */
     public static final int CONSTELLATION_TYPE_MASK = 0xf;
 
+    /**
+     * Used for receiving notifications when GNSS events happen.
+     */
+    public static abstract class Callback {
+        /**
+         * Called when GNSS system has started.
+         */
+        public void onStarted() {}
+
+        /**
+         * Called when GNSS system has stopped.
+         */
+        public void onStopped() {}
+
+        /**
+         * Called when the GNSS system has received its first fix since starting.
+         * @param ttffMillis the time from start to first fix in milliseconds.
+         */
+        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) {}
+    }
+
+    /**
+     * Constellation type.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({CONSTELLATION_UNKNOWN, CONSTELLATION_GPS, CONSTELLATION_SBAS, CONSTELLATION_GLONASS,
+            CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO})
+    public @interface ConstellationType {}
+
     /* These package private values are modified by the LocationManager class */
     /* package */ int[] mSvidWithFlags;
     /* package */ float[] mCn0DbHz;
@@ -83,15 +111,21 @@
         mAzimuths = azimuths;
     }
 
+    /** @removed */
+    public int getNumSatellites() {
+        return getSatelliteCount();
+    }
+
     /**
      * Gets the total number of satellites in satellite list.
      */
-    public int getNumSatellites() {
+    public int getSatelliteCount() {
         return mSvCount;
     }
 
     /**
-     * Retrieves the constellation type of the satellite at the specified position.
+     * Retrieves the constellation type of the satellite at the specified index.
+     *
      * @param satIndex the index of the satellite in the list.
      */
     @ConstellationType
@@ -101,7 +135,30 @@
     }
 
     /**
-     * Retrieves the pseudo-random number of the satellite at the specified position.
+     * Gets the identification number for the satellite at the specific index.
+     *
+     * <p>This svid is pseudo-random number for most constellations. It is FCN &amp; OSN number for
+     * Glonass.
+     *
+     * <p>The distinction is made by looking at constellation field
+     * {@link #getConstellationType(int)} Expected values are in the range of:
+     *
+     * <ul>
+     * <li>GPS: 1-32</li>
+     * <li>SBAS: 120-151, 183-192</li>
+     * <li>GLONASS:
+     * <ul>
+     *   <li>The least significant 8 bits, signed, are the orbital slot number (OSN) in the range
+     *   from 1-24, if known, or -127 if unknown</li>
+     *   <li>The next least signficant 8 bits, signed, are the frequency channel number (FCN) in the
+     *   range from -7 to +6, if known, and -127, if unknown</li>
+     *   <li>At least one of the two (FCN &amp; OSN) shall be set to a known value</li>
+     * </ul></li>
+     * <li>QZSS: 193-200</li>
+     * <li>Galileo: 1-36</li>
+     * <li>Beidou: 1-37</li>
+     * </ul>
+     *
      * @param satIndex the index of the satellite in the list.
      */
     public int getSvid(int satIndex) {
@@ -109,7 +166,9 @@
     }
 
     /**
-     * Retrieves the signal-noise ration of the satellite at the specified position.
+     * Retrieves the carrier-to-noise density at the antenna of the satellite at the specified index
+     * in dB-Hz.
+     *
      * @param satIndex the index of the satellite in the list.
      */
     public float getCn0DbHz(int satIndex) {
@@ -117,7 +176,8 @@
     }
 
     /**
-     * Retrieves the elevation of the satellite at the specified position.
+     * Retrieves the elevation of the satellite at the specified index.
+     *
      * @param satIndex the index of the satellite in the list.
      */
     public float getElevationDegrees(int satIndex) {
@@ -125,31 +185,46 @@
     }
 
     /**
-     * Retrieves the azimuth the satellite at the specified position.
+     * Retrieves the azimuth the satellite at the specified index.
+     *
      * @param satIndex the index of the satellite in the list.
      */
     public float getAzimuthDegrees(int satIndex) {
         return mAzimuths[satIndex];
     }
 
-    /**
-     * Detects whether the satellite at the specified position has ephemeris data.
-     * @param satIndex the index of the satellite in the list.
-     */
+    /** @removed */
     public boolean hasEphemeris(int satIndex) {
-        return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+        return hasEphemerisData(satIndex);
     }
 
     /**
-     * Detects whether the satellite at the specified position has almanac data.
+     * Reports whether the satellite at the specified index has ephemeris data.
+     *
      * @param satIndex the index of the satellite in the list.
      */
+    public boolean hasEphemerisData(int satIndex) {
+        return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+    }
+
+    /** @removed */
     public boolean hasAlmanac(int satIndex) {
+        return hasAlmanacData(satIndex);
+    }
+
+    /**
+     * Reports whether the satellite at the specified index has almanac data.
+     *
+     * @param satIndex the index of the satellite in the list.
+     */
+    public boolean hasAlmanacData(int satIndex) {
         return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
     }
 
     /**
-     * Detects whether the satellite at the specified position is used in fix.
+     * Reports whether the satellite at the specified index was used in the calculation of the most
+     * recent position fix.
+     *
      * @param satIndex the index of the satellite in the list.
      */
     public boolean usedInFix(int satIndex) {
diff --git a/location/java/android/location/GnssStatusCallback.java b/location/java/android/location/GnssStatusCallback.java
index 0d2955a..bf295ef 100644
--- a/location/java/android/location/GnssStatusCallback.java
+++ b/location/java/android/location/GnssStatusCallback.java
@@ -18,6 +18,7 @@
 
 /**
  * Used for receiving notifications when GNSS events happen.
+ * @removed
  */
 public abstract class GnssStatusCallback {
     /**
diff --git a/location/java/android/location/GpsSatellite.java b/location/java/android/location/GpsSatellite.java
index 820f5746..788d01e 100644
--- a/location/java/android/location/GpsSatellite.java
+++ b/location/java/android/location/GpsSatellite.java
@@ -18,8 +18,12 @@
 
 /**
  * This class represents the current state of a GPS satellite.
+ *
  * This class is used in conjunction with the {@link GpsStatus} class.
+ *
+ * @deprecated use {@link GnssStatus} and {@link GnssStatus.Callback}.
  */
+@Deprecated
 public final class GpsSatellite {
     /* These package private values are modified by the GpsStatus class */
     boolean mValid;
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index bc518f9..038247b 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -24,8 +24,12 @@
 
 /**
  * This class represents the current state of the GPS engine.
- * This class is used in conjunction with the {@link Listener} interface.
+ *
+ * <p>This class is used in conjunction with the {@link Listener} interface.
+ *
+ * @deprecated use {@link GnssStatus} and {@link GnssStatus.Callback}.
  */
+@Deprecated
 public final class GpsStatus {
     private static final int NUM_SATELLITES = 255;
 
@@ -102,7 +106,9 @@
 
     /**
      * Used for receiving notifications when GPS status has changed.
+     * @deprecated use {@link GnssStatus.Callback} instead.
      */
+    @Deprecated
     public interface Listener {
         /**
          * Called to report changes in the GPS status.
@@ -130,7 +136,9 @@
      * See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
      * You can implement this interface and call {@link LocationManager#addNmeaListener}
      * to receive NMEA data from the GPS engine.
+     * @deprecated use {@link OnNmeaMessageListener} instead.
      */
+    @Deprecated
     public interface NmeaListener {
         void onNmeaReceived(long timestamp, String nmea);
     }
diff --git a/location/java/android/location/IGnssNavigationMessageListener.aidl b/location/java/android/location/IGnssNavigationMessageListener.aidl
index de6129c..3e49b5b 100644
--- a/location/java/android/location/IGnssNavigationMessageListener.aidl
+++ b/location/java/android/location/IGnssNavigationMessageListener.aidl
@@ -16,12 +16,12 @@
 
 package android.location;
 
-import android.location.GnssNavigationMessageEvent;
+import android.location.GnssNavigationMessage;
 
 /**
  * {@hide}
  */
 oneway interface IGnssNavigationMessageListener {
-    void onGnssNavigationMessageReceived(in GnssNavigationMessageEvent event);
+    void onGnssNavigationMessageReceived(in GnssNavigationMessage event);
     void onStatusChanged(in int status);
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 28db099..b246360 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -70,10 +70,16 @@
             new HashMap<>();
     private final HashMap<GpsStatus.NmeaListener, GnssStatusListenerTransport> mGpsNmeaListeners =
             new HashMap<>();
-    private final HashMap<GnssStatusCallback, GnssStatusListenerTransport> mGnssStatusListeners =
+    private final HashMap<GnssStatusCallback, GnssStatusListenerTransport>
+            mOldGnssStatusListeners = new HashMap<>();
+    private final HashMap<GnssStatus.Callback, GnssStatusListenerTransport> mGnssStatusListeners =
             new HashMap<>();
-    private final HashMap<GnssNmeaListener, GnssStatusListenerTransport> mGnssNmeaListeners =
+    private final HashMap<GnssNmeaListener, GnssStatusListenerTransport> mOldGnssNmeaListeners =
             new HashMap<>();
+    private final HashMap<OnNmeaMessageListener, GnssStatusListenerTransport> mGnssNmeaListeners =
+            new HashMap<>();
+    private final HashMap<GnssNavigationMessageEvent.Callback, GnssNavigationMessage.Callback>
+            mNavigationMessageBridge = new HashMap<>();
     private GnssStatus mGnssStatus;
     private int mTimeToFirstFix;
 
@@ -1392,8 +1398,10 @@
 
         private final GpsStatus.Listener mGpsListener;
         private final GpsStatus.NmeaListener mGpsNmeaListener;
-        private final GnssStatusCallback mGnssCallback;
-        private final GnssNmeaListener mGnssNmeaListener;
+        private final GnssStatusCallback mOldGnssCallback;
+        private final GnssStatus.Callback mGnssCallback;
+        private final GnssNmeaListener mOldGnssNmeaListener;
+        private final OnNmeaMessageListener mGnssNmeaListener;
 
         private class GnssHandler extends Handler {
             public GnssHandler(Handler handler) {
@@ -1408,7 +1416,7 @@
                             int length = mNmeaBuffer.size();
                             for (int i = 0; i < length; i++) {
                                 Nmea nmea = mNmeaBuffer.get(i);
-                                mGnssNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea);
+                                mGnssNmeaListener.onNmeaMessage(nmea.mNmea, nmea.mTimestamp);
                             }
                             mNmeaBuffer.clear();
                         }
@@ -1456,7 +1464,8 @@
             mGnssHandler = new GnssHandler(handler);
             mGpsNmeaListener = null;
             mNmeaBuffer = null;
-            mGnssCallback = new GnssStatusCallback() {
+            mOldGnssCallback = null;
+            mGnssCallback = new GnssStatus.Callback() {
                 @Override
                 public void onStarted() {
                     mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STARTED);
@@ -1477,6 +1486,7 @@
                     mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
                 }
             };
+            mOldGnssNmeaListener = null;
             mGnssNmeaListener = null;
         }
 
@@ -1489,10 +1499,12 @@
             mGnssHandler = new GnssHandler(handler);
             mGpsNmeaListener = listener;
             mNmeaBuffer = new ArrayList<Nmea>();
+            mOldGnssCallback = null;
             mGnssCallback = null;
-            mGnssNmeaListener = new GnssNmeaListener() {
+            mOldGnssNmeaListener = null;
+            mGnssNmeaListener = new OnNmeaMessageListener() {
                 @Override
-                public void onNmeaReceived(long timestamp, String nmea) {
+                public void onNmeaMessage(String nmea, long timestamp) {
                     mGpsNmeaListener.onNmeaReceived(timestamp, nmea);
                 }
             };
@@ -1503,8 +1515,45 @@
         }
 
         GnssStatusListenerTransport(GnssStatusCallback callback, Handler handler) {
+            mOldGnssCallback = callback;
+            mGnssCallback = new GnssStatus.Callback() {
+                @Override
+                public void onStarted() {
+                    mOldGnssCallback.onStarted();
+                }
+
+                @Override
+                public void onStopped() {
+                    mOldGnssCallback.onStopped();
+                }
+
+                @Override
+                public void onFirstFix(int ttff) {
+                    mOldGnssCallback.onFirstFix(ttff);
+                }
+
+                @Override
+                public void onSatelliteStatusChanged(GnssStatus status) {
+                    mOldGnssCallback.onSatelliteStatusChanged(status);
+                }
+            };
+            mGnssHandler = new GnssHandler(handler);
+            mOldGnssNmeaListener = null;
+            mGnssNmeaListener = null;
+            mNmeaBuffer = null;
+            mGpsListener = null;
+            mGpsNmeaListener = null;
+        }
+
+        GnssStatusListenerTransport(GnssStatus.Callback callback) {
+            this(callback, null);
+        }
+
+        GnssStatusListenerTransport(GnssStatus.Callback callback, Handler handler) {
+            mOldGnssCallback = null;
             mGnssCallback = callback;
             mGnssHandler = new GnssHandler(handler);
+            mOldGnssNmeaListener = null;
             mGnssNmeaListener = null;
             mNmeaBuffer = null;
             mGpsListener = null;
@@ -1517,7 +1566,29 @@
 
         GnssStatusListenerTransport(GnssNmeaListener listener, Handler handler) {
             mGnssCallback = null;
+            mOldGnssCallback = null;
             mGnssHandler = new GnssHandler(handler);
+            mOldGnssNmeaListener = listener;
+            mGnssNmeaListener = new OnNmeaMessageListener() {
+                @Override
+                public void onNmeaMessage(String message, long timestamp) {
+                    mOldGnssNmeaListener.onNmeaReceived(timestamp, message);
+                }
+            };
+            mGpsListener = null;
+            mGpsNmeaListener = null;
+            mNmeaBuffer = new ArrayList<Nmea>();
+        }
+
+        GnssStatusListenerTransport(OnNmeaMessageListener listener) {
+            this(listener, null);
+        }
+
+        GnssStatusListenerTransport(OnNmeaMessageListener listener, Handler handler) {
+            mOldGnssCallback = null;
+            mGnssCallback = null;
+            mGnssHandler = new GnssHandler(handler);
+            mOldGnssNmeaListener = null;
             mGnssNmeaListener = listener;
             mGpsListener = null;
             mGpsNmeaListener = null;
@@ -1589,7 +1660,7 @@
      * @return true if the listener was successfully added
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
-     * @deprecated use {@link #registerGnssStatusCallback(GnssStatusCallback)} instead.
+     * @deprecated use {@link #registerGnssStatusCallback(GnssStatus.Callback)} instead.
      */
     @Deprecated
     @RequiresPermission(ACCESS_FINE_LOCATION)
@@ -1617,6 +1688,7 @@
      * Removes a GPS status listener.
      *
      * @param listener GPS status listener object to remove
+     * @deprecated use {@link #unregisterGnssStatusCallback(GnssStatus.Callback)} instead.
      */
     @Deprecated
     public void removeGpsStatusListener(GpsStatus.Listener listener) {
@@ -1630,7 +1702,6 @@
         }
     }
 
-
     /**
      * Registers a GNSS status listener.
      *
@@ -1639,6 +1710,7 @@
      * @return true if the listener was successfully added
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     * @removed
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssStatusCallback(GnssStatusCallback callback) {
@@ -1654,10 +1726,73 @@
      * @return true if the listener was successfully added
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     * @removed
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssStatusCallback(GnssStatusCallback callback, Handler handler) {
         boolean result;
+        if (mOldGnssStatusListeners.get(callback) != null) {
+            // listener is already registered
+            return true;
+        }
+        try {
+            GnssStatusListenerTransport transport =
+                    new GnssStatusListenerTransport(callback, handler);
+            result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
+            if (result) {
+                mOldGnssStatusListeners.put(callback, transport);
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        return result;
+    }
+
+    /**
+     * Removes a GNSS status listener.
+     *
+     * @param callback GNSS status listener object to remove
+     * @removed
+     */
+    public void unregisterGnssStatusCallback(GnssStatusCallback callback) {
+        try {
+            GnssStatusListenerTransport transport = mOldGnssStatusListeners.remove(callback);
+            if (transport != null) {
+                mService.unregisterGnssStatusCallback(transport);
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Registers a GNSS status listener.
+     *
+     * @param callback GNSS status listener object to register
+     *
+     * @return true if the listener was successfully added
+     *
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGnssStatusCallback(GnssStatus.Callback callback) {
+        return registerGnssStatusCallback(callback, null);
+    }
+
+    /**
+     * Registers a GNSS status listener.
+     *
+     * @param callback GNSS status listener object to register
+     * @param handler the handler that the callback runs on.
+     *
+     * @return true if the listener was successfully added
+     *
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGnssStatusCallback(GnssStatus.Callback callback, Handler handler) {
+        boolean result;
         if (mGnssStatusListeners.get(callback) != null) {
             // listener is already registered
             return true;
@@ -1681,7 +1816,7 @@
      *
      * @param callback GNSS status listener object to remove
      */
-    public void unregisterGnssStatusCallback(GnssStatusCallback callback) {
+    public void unregisterGnssStatusCallback(GnssStatus.Callback callback) {
         try {
             GnssStatusListenerTransport transport = mGnssStatusListeners.remove(callback);
             if (transport != null) {
@@ -1700,7 +1835,7 @@
      * @return true if the listener was successfully added
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
-     * @deprecated use {@link #addNmeaListener(GnssNmeaListener)} instead.
+     * @deprecated use {@link #addNmeaListener(OnNmeaMessageListener)} instead.
      */
     @Deprecated
     @RequiresPermission(ACCESS_FINE_LOCATION)
@@ -1728,6 +1863,7 @@
      * Removes an NMEA listener.
      *
      * @param listener a {@link GpsStatus.NmeaListener} object to remove
+     * @deprecated use {@link #removeNmeaListener(OnNmeaMessageListener)} instead.
      */
     @Deprecated
     public void removeNmeaListener(GpsStatus.NmeaListener listener) {
@@ -1749,6 +1885,7 @@
      * @return true if the listener was successfully added
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     * @removed
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean addNmeaListener(GnssNmeaListener listener) {
@@ -1764,6 +1901,7 @@
      * @return true if the listener was successfully added
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     * @removed
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean addNmeaListener(GnssNmeaListener listener, Handler handler) {
@@ -1778,6 +1916,69 @@
                     new GnssStatusListenerTransport(listener, handler);
             result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
             if (result) {
+                mOldGnssNmeaListeners.put(listener, transport);
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        return result;
+    }
+
+    /**
+     * Removes an NMEA listener.
+     *
+     * @param listener a {@link GnssNmeaListener} object to remove
+     * @removed
+     */
+    public void removeNmeaListener(GnssNmeaListener listener) {
+        try {
+            GnssStatusListenerTransport transport = mOldGnssNmeaListeners.remove(listener);
+            if (transport != null) {
+                mService.unregisterGnssStatusCallback(transport);
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Adds an NMEA listener.
+     *
+     * @param listener a {@link OnNmeaMessageListener} object to register
+     *
+     * @return true if the listener was successfully added
+     *
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean addNmeaListener(OnNmeaMessageListener listener) {
+        return addNmeaListener(listener, null);
+    }
+
+    /**
+     * Adds an NMEA listener.
+     *
+     * @param listener a {@link OnNmeaMessageListener} object to register
+     * @param handler the handler that the listener runs on.
+     *
+     * @return true if the listener was successfully added
+     *
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean addNmeaListener(OnNmeaMessageListener listener, Handler handler) {
+        boolean result;
+
+        if (mGpsNmeaListeners.get(listener) != null) {
+            // listener is already registered
+            return true;
+        }
+        try {
+            GnssStatusListenerTransport transport =
+                    new GnssStatusListenerTransport(listener, handler);
+            result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
+            if (result) {
                 mGnssNmeaListeners.put(listener, transport);
             }
         } catch (RemoteException e) {
@@ -1790,9 +1991,9 @@
     /**
      * Removes an NMEA listener.
      *
-     * @param listener a {@link GnssNmeaListener} object to remove
+     * @param listener a {@link OnNmeaMessageListener} object to remove
      */
-    public void removeNmeaListener(GnssNmeaListener listener) {
+    public void removeNmeaListener(OnNmeaMessageListener listener) {
         try {
             GnssStatusListenerTransport transport = mGnssNmeaListeners.remove(listener);
             if (transport != null) {
@@ -1843,7 +2044,8 @@
      * No-op method to keep backward-compatibility.
      * Don't use it. Use {@link #unregisterGnssMeasurementsCallback} instead.
      * @hide
-     * @deprecated
+     * @deprecated use {@link #unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback)}
+     * instead.
      */
     @Deprecated
     @SystemApi
@@ -1872,10 +2074,23 @@
     }
 
     /**
-     * Registers a GPS Navigation Message callback.
+     * No-op method to keep backward-compatibility.
+     * Don't use it. Use {@link #unregisterGnssNavigationMessageCallback} instead.
+     * @hide
+     * @deprecated use {@link #unregisterGnssNavigationMessageCallback(GnssMeasurements.Callback)}
+     * instead
+     */
+    @Deprecated
+    @SystemApi
+    public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
+    }
+
+    /**
+     * Registers a GNSS Navigation Message callback.
      *
      * @param callback a {@link GnssNavigationMessageEvent.Callback} object to register.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     * @removed
      */
     public boolean registerGnssNavigationMessageCallback(
             GnssNavigationMessageEvent.Callback callback) {
@@ -1883,40 +2098,80 @@
     }
 
     /**
-     * Registers a GPS Navigation Message callback.
+     * Registers a GNSS Navigation Message callback.
      *
      * @param callback a {@link GnssNavigationMessageEvent.Callback} object to register.
      * @param handler the handler that the callback runs on.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     * @removed
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGnssNavigationMessageCallback(
+            final GnssNavigationMessageEvent.Callback callback, Handler handler) {
+        GnssNavigationMessage.Callback bridge = new GnssNavigationMessage.Callback() {
+            @Override
+            public void onGnssNavigationMessageReceived(GnssNavigationMessage message) {
+                GnssNavigationMessageEvent event = new GnssNavigationMessageEvent(message);
+                callback.onGnssNavigationMessageReceived(event);
+            }
+
+            @Override
+            public void onStatusChanged(int status) {
+                callback.onStatusChanged(status);
+            }
+        };
+        mNavigationMessageBridge.put(callback, bridge);
+        return mGnssNavigationMessageCallbackTransport.add(bridge, handler);
+    }
+
+    /**
+     * Unregisters a GNSS Navigation Message callback.
+     *
+     * @param callback a {@link GnssNavigationMessageEvent.Callback} object to remove.
+     * @removed
+     */
+    public void unregisterGnssNavigationMessageCallback(
+            GnssNavigationMessageEvent.Callback callback) {
+        mGnssNavigationMessageCallbackTransport.remove(
+                mNavigationMessageBridge.remove(
+                        callback));
+    }
+
+    /**
+     * Registers a GNSS Navigation Message callback.
+     *
+     * @param callback a {@link GnssNavigationMessage.Callback} object to register.
+     * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     */
+    public boolean registerGnssNavigationMessageCallback(
+            GnssNavigationMessage.Callback callback) {
+        return registerGnssNavigationMessageCallback(callback, null);
+    }
+
+    /**
+     * Registers a GNSS Navigation Message callback.
+     *
+     * @param callback a {@link GnssNavigationMessage.Callback} object to register.
+     * @param handler the handler that the callback runs on.
+     * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssNavigationMessageCallback(
-            GnssNavigationMessageEvent.Callback callback, Handler handler) {
+            GnssNavigationMessage.Callback callback, Handler handler) {
         return mGnssNavigationMessageCallbackTransport.add(callback, handler);
     }
 
     /**
-     * Unregisters a GPS Navigation Message callback.
+     * Unregisters a GNSS Navigation Message callback.
      *
-     * @param callback a {@link GnssNavigationMessageEvent.Callback} object to remove.
+     * @param callback a {@link GnssNavigationMessage.Callback} object to remove.
      */
     public void unregisterGnssNavigationMessageCallback(
-            GnssNavigationMessageEvent.Callback callback) {
+            GnssNavigationMessage.Callback callback) {
         mGnssNavigationMessageCallbackTransport.remove(callback);
     }
 
     /**
-     * No-op method to keep backward-compatibility.
-     * Don't use it. Use {@link #unregisterGnssNavigationMessageCallback} instead.
-     * @hide
-     * @deprecated
-     */
-    @Deprecated
-    @SystemApi
-    public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
-    }
-
-    /**
      * Retrieves information about the current status of the GPS engine.
      * This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged}
      * callback to ensure that the data is copied atomically.
diff --git a/location/java/android/location/OnNmeaMessageListener.java b/location/java/android/location/OnNmeaMessageListener.java
new file mode 100644
index 0000000..ccf6ce8
--- /dev/null
+++ b/location/java/android/location/OnNmeaMessageListener.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.location;
+
+/**
+* Used for receiving NMEA sentences from the GNSS.
+* NMEA 0183 is a standard for communicating with marine electronic devices
+* and is a common method for receiving data from a GNSS, typically over a serial port.
+* See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
+* You can implement this interface and call {@link LocationManager#addNmeaListener}
+* to receive NMEA data from the GNSS engine.
+*/
+public interface OnNmeaMessageListener {
+    /**
+     * Called when an NMEA message is received.
+     * @param message NMEA message
+     * @param timestamp milliseconds since January 1, 1970.
+     */
+    void onNmeaMessage(String message, long timestamp);
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 0a8c692..00eff91 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2157,7 +2157,7 @@
                                 final RecordConfigChangeCallbackData cbData =
                                         (RecordConfigChangeCallbackData) msg.obj;
                                 if (cbData.mCb != null) {
-                                    cbData.mCb.onRecordConfigChanged(cbData.mConfigs);
+                                    cbData.mCb.onRecordingConfigChanged(cbData.mConfigs);
                                 }
                                 break;
                             default:
@@ -2746,7 +2746,7 @@
          * @param configs array containing the results of
          *      {@link AudioManager#getActiveRecordingConfigurations()}.
          */
-        public void onRecordConfigChanged(AudioRecordingConfiguration[] configs) {}
+        public void onRecordingConfigChanged(AudioRecordingConfiguration[] configs) {}
     }
 
     private static class AudioRecordingCallbackInfo {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index b6ff41e..621129d 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -596,14 +596,14 @@
      * AudioTrack player = new AudioTrack.Builder()
      *         .setAudioAttributes(new AudioAttributes.Builder()
      *                  .setUsage(AudioAttributes.USAGE_ALARM)
-     *                  .setContentType(CONTENT_TYPE_MUSIC)
+     *                  .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
      *                  .build())
      *         .setAudioFormat(new AudioFormat.Builder()
      *                 .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
-     *                 .setSampleRate(441000)
+     *                 .setSampleRate(44100)
      *                 .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
      *                 .build())
-     *         .setBufferSize(minBuffSize)
+     *         .setBufferSizeInBytes(minBuffSize)
      *         .build();
      * </pre>
      * <p>
diff --git a/media/java/android/media/DrmInitData.java b/media/java/android/media/DrmInitData.java
index 06fe6ff..170d9de 100644
--- a/media/java/android/media/DrmInitData.java
+++ b/media/java/android/media/DrmInitData.java
@@ -28,6 +28,12 @@
 public abstract class DrmInitData {
 
     /**
+     * Prevent public constuctor access
+     */
+    /* package private */ DrmInitData() {
+    }
+
+    /**
      * Retrieves initialization data for a given DRM scheme, specified by its UUID.
      *
      * @param schemeUuid The DRM scheme's UUID.
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index e987885..3d7e744 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -235,8 +235,6 @@
     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. */
@@ -447,7 +445,7 @@
             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_ISO_SPEED_RATINGS, 34855),
             new ExifTag(TAG_OECF, 34856),
             new ExifTag(TAG_EXIF_VERSION, 36864),
             new ExifTag(TAG_DATETIME_ORIGINAL, 36867),
@@ -1161,7 +1159,7 @@
             if (datetime == null) return -1;
             long msecs = datetime.getTime();
 
-            String subSecs = getAttribute(TAG_SUBSECTIME);
+            String subSecs = getAttribute(TAG_SUBSEC_TIME);
             if (subSecs != null) {
                 try {
                     long sub = Long.valueOf(subSecs);
@@ -1553,7 +1551,7 @@
         convertToDouble(TAG_EXPOSURE_TIME);
         convertToDouble(TAG_F_NUMBER);
         convertToDouble(TAG_SUBJECT_DISTANCE);
-        convertToInt(TAG_ISO);
+        convertToInt(TAG_ISO_SPEED_RATINGS);
         convertToDouble(TAG_EXPOSURE_BIAS_VALUE);
         convertToInt(TAG_WHITE_BALANCE);
         convertToInt(TAG_LIGHT_SOURCE);
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index 1fee587..983ca75 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -45,8 +45,7 @@
     private static final int NUM_MEDIA_SOUND_STREAMS = 1;
 
     private SoundPool mSoundPool;
-    private int[]     mSoundIds;
-    private int       mSoundIdToPlay;
+    private SoundState[] mSounds;
 
     private static final String[] SOUND_FILES = {
         "/system/media/audio/ui/camera_click.ogg",
@@ -88,22 +87,57 @@
      */
     public static final int STOP_VIDEO_RECORDING  = 3;
 
-    private static final int SOUND_NOT_LOADED = -1;
+    /**
+     * States for SoundState.
+     * STATE_NOT_LOADED             : sample not loaded
+     * STATE_LOADING                : sample being loaded: waiting for load completion callback
+     * STATE_LOADING_PLAY_REQUESTED : sample being loaded and playback request received
+     * STATE_LOADED                 : sample loaded, ready for playback
+     */
+    private static final int STATE_NOT_LOADED             = 0;
+    private static final int STATE_LOADING                = 1;
+    private static final int STATE_LOADING_PLAY_REQUESTED = 2;
+    private static final int STATE_LOADED                 = 3;
 
+    private class SoundState {
+        public final int name;
+        public int id;
+        public int state;
+
+        public SoundState(int name) {
+            this.name = name;
+            id = 0; // 0 is an invalid sample ID.
+            state = STATE_NOT_LOADED;
+        }
+    }
     /**
      * Construct a new MediaActionSound instance. Only a single instance is
      * needed for playing any platform media action sound; you do not need a
      * separate instance for each sound type.
      */
     public MediaActionSound() {
-        mSoundPool = new SoundPool(NUM_MEDIA_SOUND_STREAMS,
-                AudioManager.STREAM_SYSTEM_ENFORCED, 0);
+        mSoundPool = new SoundPool.Builder()
+                .setMaxStreams(NUM_MEDIA_SOUND_STREAMS)
+                .setAudioAttributes(new AudioAttributes.Builder()
+                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+                    .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
+                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                    .build())
+                .build();
         mSoundPool.setOnLoadCompleteListener(mLoadCompleteListener);
-        mSoundIds = new int[SOUND_FILES.length];
-        for (int i = 0; i < mSoundIds.length; i++) {
-            mSoundIds[i] = SOUND_NOT_LOADED;
+        mSounds = new SoundState[SOUND_FILES.length];
+        for (int i = 0; i < mSounds.length; i++) {
+            mSounds[i] = new SoundState(i);
         }
-        mSoundIdToPlay = SOUND_NOT_LOADED;
+    }
+
+    private int loadSound(SoundState sound) {
+        int id = mSoundPool.load(SOUND_FILES[sound.name], 1);
+        if (id > 0) {
+            sound.state = STATE_LOADING;
+            sound.id = id;
+        }
+        return id;
     }
 
     /**
@@ -118,13 +152,22 @@
      * @see #START_VIDEO_RECORDING
      * @see #STOP_VIDEO_RECORDING
      */
-    public synchronized void load(int soundName) {
+    public void load(int soundName) {
         if (soundName < 0 || soundName >= SOUND_FILES.length) {
             throw new RuntimeException("Unknown sound requested: " + soundName);
         }
-        if (mSoundIds[soundName] == SOUND_NOT_LOADED) {
-            mSoundIds[soundName] =
-                    mSoundPool.load(SOUND_FILES[soundName], 1);
+        SoundState sound = mSounds[soundName];
+        synchronized (sound) {
+            switch (sound.state) {
+            case STATE_NOT_LOADED:
+                if (loadSound(sound) <= 0) {
+                    Log.e(TAG, "load() error loading sound: " + soundName);
+                }
+                break;
+            default:
+                Log.e(TAG, "load() called in wrong state: " + sound + " for sound: "+ soundName);
+                break;
+            }
         }
     }
 
@@ -159,16 +202,31 @@
      * @see #START_VIDEO_RECORDING
      * @see #STOP_VIDEO_RECORDING
      */
-    public synchronized void play(int soundName) {
+    public void play(int soundName) {
         if (soundName < 0 || soundName >= SOUND_FILES.length) {
             throw new RuntimeException("Unknown sound requested: " + soundName);
         }
-        if (mSoundIds[soundName] == SOUND_NOT_LOADED) {
-            mSoundIdToPlay =
-                    mSoundPool.load(SOUND_FILES[soundName], 1);
-            mSoundIds[soundName] = mSoundIdToPlay;
-        } else {
-            mSoundPool.play(mSoundIds[soundName], 1.0f, 1.0f, 0, 0, 1.0f);
+        SoundState sound = mSounds[soundName];
+        synchronized (sound) {
+            switch (sound.state) {
+            case STATE_NOT_LOADED:
+                loadSound(sound);
+                if (loadSound(sound) <= 0) {
+                    Log.e(TAG, "play() error loading sound: " + soundName);
+                    break;
+                }
+                // FALL THROUGH
+
+            case STATE_LOADING:
+                sound.state = STATE_LOADING_PLAY_REQUESTED;
+                break;
+            case STATE_LOADED:
+                mSoundPool.play(sound.id, 1.0f, 1.0f, 0, 0, 1.0f);
+                break;
+            default:
+                Log.e(TAG, "play() called in wrong state: " + sound.state + " for sound: "+ soundName);
+                break;
+            }
         }
     }
 
@@ -176,14 +234,37 @@
             new SoundPool.OnLoadCompleteListener() {
         public void onLoadComplete(SoundPool soundPool,
                 int sampleId, int status) {
-            if (status == 0) {
-                if (mSoundIdToPlay == sampleId) {
-                    soundPool.play(sampleId, 1.0f, 1.0f, 0, 0, 1.0f);
-                    mSoundIdToPlay = SOUND_NOT_LOADED;
+            for (SoundState sound : mSounds) {
+                if (sound.id != sampleId) {
+                    continue;
                 }
-            } else {
-                Log.e(TAG, "Unable to load sound for playback (status: " +
-                        status + ")");
+                int playSoundId = 0;
+                synchronized (sound) {
+                    if (status != 0) {
+                        sound.state = STATE_NOT_LOADED;
+                        sound.id = 0;
+                        Log.e(TAG, "OnLoadCompleteListener() error: " + status +
+                                " loading sound: "+ sound.name);
+                        return;
+                    }
+                    switch (sound.state) {
+                    case STATE_LOADING:
+                        sound.state = STATE_LOADED;
+                        break;
+                    case STATE_LOADING_PLAY_REQUESTED:
+                        playSoundId = sound.id;
+                        sound.state = STATE_LOADED;
+                        break;
+                    default:
+                        Log.e(TAG, "OnLoadCompleteListener() called in wrong state: "
+                                + sound.state + " for sound: "+ sound.name);
+                        break;
+                    }
+                }
+                if (playSoundId != 0) {
+                    soundPool.play(playSoundId, 1.0f, 1.0f, 0, 0, 1.0f);
+                }
+                break;
             }
         }
     };
@@ -195,6 +276,12 @@
      */
     public void release() {
         if (mSoundPool != null) {
+            for (SoundState sound : mSounds) {
+                synchronized (sound) {
+                    sound.state = STATE_NOT_LOADED;
+                    sound.id = 0;
+                }
+            }
             mSoundPool.release();
             mSoundPool = null;
         }
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index b1c1b79..2bd9781 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -2666,12 +2666,13 @@
         public static final int HEVCHighTierLevel62 = 0x2000000;
 
         // from OMX_VIDEO_DOLBYVISIONPROFILETYPE
-        public static final int DolbyVisionProfileDvavDer = 0x1;
-        public static final int DolbyVisionProfileDvavDen = 0x2;
-        public static final int DolbyVisionProfileDvheDer = 0x3;
-        public static final int DolbyVisionProfileDvheDen = 0x4;
-        public static final int DolbyVisionProfileDvheDtr = 0x5;
-        public static final int DolbyVisionProfileDvheStn = 0x6;
+        public static final int DolbyVisionProfileDvavPer = 0x1;
+        public static final int DolbyVisionProfileDvavPen = 0x2;
+        public static final int DolbyVisionProfileDvheDer = 0x4;
+        public static final int DolbyVisionProfileDvheDen = 0x8;
+        public static final int DolbyVisionProfileDvheDtr = 0x10;
+        public static final int DolbyVisionProfileDvheStn = 0x20;
+        public static final int DolbyVisionProfileDvheDth = 0x40;
 
         // from OMX_VIDEO_DOLBYVISIONLEVELTYPE
         public static final int DolbyVisionLevelHd24    = 0x1;
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 177344a..24a400e4 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -275,16 +275,23 @@
                     return initDataMap.get(schemeUuid);
                 }
             };
-        } else if (formatMap.containsKey("crypto-key")) {
-            ByteBuffer buf = (ByteBuffer) formatMap.get("crypto-key");
-            buf.rewind();
-            final byte[] data = new byte[buf.remaining()];
-            buf.get(data);
-            return new DrmInitData() {
-                public SchemeInitData get(UUID schemeUuid) {
-                    return new DrmInitData.SchemeInitData("webm", data);
+        } else {
+            int numTracks = getTrackCount();
+            for (int i = 0; i < numTracks; ++i) {
+                Map<String, Object> trackFormatMap = getTrackFormatNative(i);
+                if (!trackFormatMap.containsKey("crypto-key")) {
+                    continue;
                 }
-            };
+                ByteBuffer buf = (ByteBuffer) trackFormatMap.get("crypto-key");
+                buf.rewind();
+                final byte[] data = new byte[buf.remaining()];
+                buf.get(data);
+                return new DrmInitData() {
+                    public SchemeInitData get(UUID schemeUuid) {
+                        return new DrmInitData.SchemeInitData("webm", data);
+                    }
+                };
+            }
         }
         return null;
     }
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index c1805cb..7c6adad 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -72,7 +72,7 @@
 
     /**
      * 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.
+     * The value of {@code EXTRA_PAGE} should be greater than or equal to 0.
      *
      * @see #EXTRA_PAGE_SIZE
      */
diff --git a/media/java/android/media/browse/MediaBrowserUtils.java b/media/java/android/media/browse/MediaBrowserUtils.java
index b06e598..2943e60 100644
--- a/media/java/android/media/browse/MediaBrowserUtils.java
+++ b/media/java/android/media/browse/MediaBrowserUtils.java
@@ -50,7 +50,7 @@
             startIndex1 = 0;
             endIndex1 = Integer.MAX_VALUE;
         } else {
-            startIndex1 = pageSize1 * (page1 - 1);
+            startIndex1 = pageSize1 * page1;
             endIndex1 = startIndex1 + pageSize1 - 1;
         }
 
@@ -58,7 +58,7 @@
             startIndex2 = 0;
             endIndex2 = Integer.MAX_VALUE;
         } else {
-            startIndex2 = pageSize2 * (page2 - 1);
+            startIndex2 = pageSize2 * page2;
             endIndex2 = startIndex2 + pageSize2 - 1;
         }
 
diff --git a/media/java/android/media/midi/IMidiDeviceServer.aidl b/media/java/android/media/midi/IMidiDeviceServer.aidl
index c2cc2b9..d5115de 100644
--- a/media/java/android/media/midi/IMidiDeviceServer.aidl
+++ b/media/java/android/media/midi/IMidiDeviceServer.aidl
@@ -28,7 +28,8 @@
     void closeDevice();
 
     // connects the input port pfd to the specified output port
-    void connectPorts(IBinder token, in ParcelFileDescriptor pfd, int outputPortNumber);
+    // Returns the PID of the called process.
+    int connectPorts(IBinder token, in ParcelFileDescriptor pfd, int outputPortNumber);
 
     MidiDeviceInfo getDeviceInfo();
     void setDeviceInfo(in MidiDeviceInfo deviceInfo);
diff --git a/media/java/android/media/midi/MidiDevice.java b/media/java/android/media/midi/MidiDevice.java
index e1990cd..e4588fe 100644
--- a/media/java/android/media/midi/MidiDevice.java
+++ b/media/java/android/media/midi/MidiDevice.java
@@ -19,6 +19,7 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -181,9 +182,16 @@
         }
          try {
             IBinder token = new Binder();
-            mDeviceServer.connectPorts(token, pfd, outputPortNumber);
-            // close our copy of the file descriptor
-            IoUtils.closeQuietly(pfd);
+            int calleePid = mDeviceServer.connectPorts(token, pfd, outputPortNumber);
+            // If the service is a different Process then it will duplicate the pfd
+            // and we can safely close this one.
+            // But if the service is in the same Process then closing the pfd will
+            // kill the connection. So don't do that.
+            if (calleePid != Process.myPid()) {
+                // close our copy of the file descriptor
+                IoUtils.closeQuietly(pfd);
+            }
+
             return new MidiConnection(token, inputPort);
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in connectPorts");
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index 19ff624..f0abf71 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -254,7 +254,7 @@
         }
 
         @Override
-        public void connectPorts(IBinder token, ParcelFileDescriptor pfd,
+        public int connectPorts(IBinder token, ParcelFileDescriptor pfd,
                 int outputPortNumber) {
             MidiInputPort inputPort = new MidiInputPort(pfd, outputPortNumber);
             MidiDispatcher dispatcher = mOutputPortDispatchers[outputPortNumber];
@@ -270,6 +270,7 @@
             synchronized (mPortClients) {
                 mPortClients.put(token, client);
             }
+            return Process.myPid(); // for caller to detect same process ID
         }
 
         @Override
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index acf94f4c..03dc699 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -116,10 +116,10 @@
     private final int mType;
     private final boolean mIsHardwareInput;
 
-    // TODO: Remove mLabel and mIconUri when createTvInputInfo() is removed.
-    private String mLabel;
+    // TODO: Remove mIconUri when createTvInputInfo() is removed.
     private Uri mIconUri;
 
+    private final CharSequence mLabel;
     private final int mLabelResId;
     private final Icon mIcon;
     private final Icon mIconStandby;
@@ -161,8 +161,8 @@
         TvInputInfo info = new TvInputInfo.Builder(context, service)
                 .setHdmiDeviceInfo(hdmiDeviceInfo)
                 .setParentId(parentId)
+                .setLabel(label)
                 .build();
-        info.mLabel = label;
         info.mIconUri = iconUri;
         return info;
     }
@@ -215,8 +215,8 @@
                     throws XmlPullParserException, IOException {
         TvInputInfo info = new TvInputInfo.Builder(context, service)
                 .setTvInputHardwareInfo(hardwareInfo)
+                .setLabel(label)
                 .build();
-        info.mLabel = label;
         info.mIconUri = iconUri;
         return info;
     }
@@ -247,7 +247,7 @@
     }
 
     private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
-            int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
+            CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
             String setupActivity, String settingsActivity, boolean canRecord, int tunerCount,
             HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch, String parentId,
             Bundle extras) {
@@ -255,6 +255,7 @@
         mId = id;
         mType = type;
         mIsHardwareInput = isHardwareInput;
+        mLabel = label;
         mLabelResId = labelResId;
         mIcon = icon;
         mIconStandby = iconStandby;
@@ -570,7 +571,7 @@
         dest.writeString(mId);
         dest.writeInt(mType);
         dest.writeByte(mIsHardwareInput ? (byte) 1 : 0);
-        dest.writeString(mLabel);
+        TextUtils.writeToParcel(mLabel, dest, flags);
         dest.writeParcelable(mIconUri, flags);
         dest.writeInt(mLabelResId);
         dest.writeParcelable(mIcon, flags);
@@ -612,7 +613,7 @@
         mId = in.readString();
         mType = in.readInt();
         mIsHardwareInput = in.readByte() == 1;
-        mLabel = in.readString();
+        mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
         mIconUri = in.readParcelable(null);
         mLabelResId = in.readInt();
         mIcon = in.readParcelable(null);
@@ -660,6 +661,7 @@
 
         private final Context mContext;
         private final ResolveInfo mResolveInfo;
+        private CharSequence mLabel;
         private int mLabelResId;
         private Icon mIcon;
         private Icon mIconStandby;
@@ -746,12 +748,31 @@
         /**
          * Sets the label.
          *
+         * @param label The text to be used as label.
+         * @return This Builder object to allow for chaining of calls to builder methods.
+         * @hide
+         */
+        @SystemApi
+        public Builder setLabel(CharSequence label) {
+            if (mLabelResId != 0) {
+                throw new IllegalStateException("Resource ID for label is already set.");
+            }
+            this.mLabel = label;
+            return this;
+        }
+
+        /**
+         * Sets the label.
+         *
          * @param resId The resource ID of the text to use.
          * @return This Builder object to allow for chaining of calls to builder methods.
          * @hide
          */
         @SystemApi
         public Builder setLabel(int resId) {
+            if (mLabel != null) {
+                throw new IllegalStateException("Label text is already set.");
+            }
             this.mLabelResId = resId;
             return this;
         }
@@ -868,8 +889,8 @@
                 type = TYPE_TUNER;
             }
             parseServiceMetadata(type);
-            return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabelResId, mIcon,
-                    mIconStandby, mIconDisconnected, mSetupActivity, mSettingsActivity,
+            return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabel, mLabelResId,
+                    mIcon, mIconStandby, mIconDisconnected, mSetupActivity, mSettingsActivity,
                     mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount,
                     mHdmiDeviceInfo, isConnectedToHdmiSwitch, mParentId, mExtras);
         }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index ae86632..6954045 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -657,9 +657,9 @@
         if (page == -1 && pageSize == -1) {
             return list;
         }
-        int fromIndex = pageSize * (page - 1);
+        int fromIndex = pageSize * page;
         int toIndex = fromIndex + pageSize;
-        if (page < 1 || pageSize < 1 || fromIndex >= list.size()) {
+        if (page < 0 || pageSize < 1 || fromIndex >= list.size()) {
             return Collections.EMPTY_LIST;
         }
         if (toIndex > list.size()) {
diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp
index 537b56d..d07942b 100644
--- a/media/jni/android_media_MediaDataSource.cpp
+++ b/media/jni/android_media_MediaDataSource.cpp
@@ -155,4 +155,8 @@
     return 0;
 }
 
+String8 JMediaDataSource::toString() {
+    return String8::format("JMediaDataSource(pid %d, uid %d)", getpid(), getuid());
+}
+
 }  // namespace android
diff --git a/media/jni/android_media_MediaDataSource.h b/media/jni/android_media_MediaDataSource.h
index 34624eb..378baf4 100644
--- a/media/jni/android_media_MediaDataSource.h
+++ b/media/jni/android_media_MediaDataSource.h
@@ -46,6 +46,7 @@
     virtual status_t getSize(off64_t* size);
     virtual void close();
     virtual uint32_t getFlags();
+    virtual String8 toString();
 
 private:
     // Protect all member variables with mLock because this object will be
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 5722cb0..39f2a32 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -882,7 +882,7 @@
                 break;
             }
 
-            info.mThumbCompressedSize = image_data.thumbnail_length;
+            info.mThumbCompressedSize = image_data.thumbnail.length;
             info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
             info.mImagePixWidth = image_data.full_width;
             info.mImagePixHeight = image_data.full_height;
@@ -932,19 +932,19 @@
                     break;
                 }
 
-                if (image_data.thumbnail_length == 0) {
+                if (image_data.thumbnail.length == 0) {
                     // No thumbnail.
                     break;
                 }
 
-                result = malloc(image_data.thumbnail_length);
+                result = malloc(image_data.thumbnail.length);
                 if (result) {
                     piex::Error err = stream.get()->GetData(
-                            image_data.thumbnail_offset,
-                            image_data.thumbnail_length,
+                            image_data.thumbnail.offset,
+                            image_data.thumbnail.length,
                             (std::uint8_t *)result);
                     if (err == piex::Error::kOk) {
-                        outThumbSize = image_data.thumbnail_length;
+                        outThumbSize = image_data.thumbnail.length;
                     } else {
                         free(result);
                     }
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 dde9bda..312d9aa 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
@@ -61,7 +61,7 @@
     private static final String[] EXIF_TAGS = {
             ExifInterface.TAG_MAKE,
             ExifInterface.TAG_MODEL,
-            ExifInterface.TAG_APERTURE,
+            ExifInterface.TAG_F_NUMBER,
             ExifInterface.TAG_DATETIME,
             ExifInterface.TAG_EXPOSURE_TIME,
             ExifInterface.TAG_FLASH,
@@ -77,7 +77,7 @@
             ExifInterface.TAG_GPS_TIMESTAMP,
             ExifInterface.TAG_IMAGE_LENGTH,
             ExifInterface.TAG_IMAGE_WIDTH,
-            ExifInterface.TAG_ISO,
+            ExifInterface.TAG_ISO_SPEED_RATINGS,
             ExifInterface.TAG_ORIENTATION,
             ExifInterface.TAG_WHITE_BALANCE
     };
@@ -288,7 +288,7 @@
         // Checks values.
         assertStringTag(exifInterface, ExifInterface.TAG_MAKE, expectedValue.make);
         assertStringTag(exifInterface, ExifInterface.TAG_MODEL, expectedValue.model);
-        assertFloatTag(exifInterface, ExifInterface.TAG_APERTURE, expectedValue.aperture);
+        assertFloatTag(exifInterface, ExifInterface.TAG_F_NUMBER, expectedValue.aperture);
         assertStringTag(exifInterface, ExifInterface.TAG_DATETIME, expectedValue.datetime);
         assertFloatTag(exifInterface, ExifInterface.TAG_EXPOSURE_TIME, expectedValue.exposureTime);
         assertFloatTag(exifInterface, ExifInterface.TAG_FLASH, expectedValue.flash);
@@ -308,7 +308,7 @@
         assertStringTag(exifInterface, ExifInterface.TAG_GPS_TIMESTAMP, expectedValue.gpsTimestamp);
         assertIntTag(exifInterface, ExifInterface.TAG_IMAGE_LENGTH, expectedValue.imageLength);
         assertIntTag(exifInterface, ExifInterface.TAG_IMAGE_WIDTH, expectedValue.imageWidth);
-        assertStringTag(exifInterface, ExifInterface.TAG_ISO, expectedValue.iso);
+        assertStringTag(exifInterface, ExifInterface.TAG_ISO_SPEED_RATINGS, expectedValue.iso);
         assertIntTag(exifInterface, ExifInterface.TAG_ORIENTATION, expectedValue.orientation);
         assertIntTag(exifInterface, ExifInterface.TAG_WHITE_BALANCE, expectedValue.whiteBalance);
     }
diff --git a/packages/CtsShim/Android.mk b/packages/CtsShim/Android.mk
new file mode 100644
index 0000000..537b171
--- /dev/null
+++ b/packages/CtsShim/Android.mk
@@ -0,0 +1,61 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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)
+
+###########################################################
+# Variant: Privileged app
+
+include $(CLEAR_VARS)
+# this needs to be a privileged application
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SDK_VERSION := current
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PACKAGE_NAME := CtsShimPriv
+
+#TODO need to find the correct certificate
+#Change in conjunction with cts/hostsidetests/appsecurity/test-apps/IntentFilterApp
+LOCAL_CERTIFICATE := platform
+LOCAL_MANIFEST_FILE := priv_shim/AndroidManifest.xml
+
+include $(BUILD_PACKAGE)
+
+
+
+###########################################################
+# Variant: System app
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SDK_VERSION := current
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PACKAGE_NAME := CtsShim
+
+#TODO need to find the correct certificate
+#Change in conjunction with cts/hostsidetests/appsecurity/test-apps/IntentFilterApp
+LOCAL_CERTIFICATE := platform
+LOCAL_MANIFEST_FILE := shim/AndroidManifest.xml
+
+include $(BUILD_PACKAGE)
+
+
diff --git a/packages/CtsShim/priv_shim/AndroidManifest.xml b/packages/CtsShim/priv_shim/AndroidManifest.xml
new file mode 100644
index 0000000..0a3f823
--- /dev/null
+++ b/packages/CtsShim/priv_shim/AndroidManifest.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Manifest for the privileged CTS shim -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.priv.ctsshim">
+    <application android:label="CtsShim">
+
+        <!-- These activities don't actually exist; define them just to test the filters !-->
+
+        <!-- install test; [some] high priority filters granted -->
+        <activity android:name=".InstallPriority">
+            <!-- normal actions; priority will be granted -->
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.SEARCH" />
+                <category android:name="android.intent.category.INFO" />
+            </intent-filter>
+
+            <!-- protected actions; priority will be denied -->
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.BROWSABLE" />
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.SEND" />
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.SEND_MULTIPLE" />
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.SENDTO" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; single, equivalent filter -->
+        <activity android:name=".UpgradeMatch">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.MATCH" />
+                <category android:name="android.intent.category.INFO" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; multiple, equivalent filters -->
+        <activity android:name=".UpgradeMatchMultiple">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.MATCH_MULTIPLE" />
+                <category android:name="android.intent.category.INFO" />
+            </intent-filter>
+
+            <intent-filter android:priority="150">
+                <action android:name="com.android.cts.action.MATCH_MULTIPLE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="http" />
+                <data android:scheme="https" />
+                <data android:host="www.google.com" android:port="80" />
+                <data android:host="www.google.com" android:port="8080" />
+                <data android:host="goo.gl" android:port="443" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; lower priority -->
+        <activity android:name=".UpgradeLowerPriority">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.LOWER_PRIORITY" />
+                <category android:name="android.intent.category.INFO" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; action subset -->
+        <activity android:name=".UpgradeActionSubset">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.ACTION_SUB" />
+                <action android:name="com.android.cts.action.ACTION_SUB_2" />
+                <action android:name="com.android.cts.action.ACTION_SUB_3" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; category subset -->
+        <activity android:name=".UpgradeCategorySubset">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.CATEGORY_SUB" />
+                <category android:name="android.intent.category.INFO" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; scheme subset -->
+        <activity android:name=".UpgradeSchemeSubset">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.SCHEME_SUB" />
+                <data android:scheme="content" />
+                <data android:scheme="flubber" />
+                <data android:scheme="zoodle" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; authority subset -->
+        <activity android:name=".UpgradeAuthoritySubset">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.AUTHORITY_SUB" />
+                <data android:host="www.google.com" android:port="80" />
+                <data android:host="www.google.com" android:port="8080" />
+                <data android:host="mail.google.com" android:port="80" />
+                <data android:host="goo.gl" android:port="443" />
+            </intent-filter>
+        </activity>
+
+
+        <!-- upgrade test; new action -->
+        <activity android:name=".UpgradeNewAction">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.NEW_ACTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; new category -->
+        <activity android:name=".UpgradeNewCategory">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.NEW_CATEGORY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; new scheme -->
+        <activity android:name=".UpgradeNewScheme">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.NEW_SCHEME" />
+                <data android:scheme="content" />
+            </intent-filter>
+        </activity>
+
+        <!-- upgrade test; new authority -->
+        <activity android:name=".UpgradeNewAuthority">
+            <intent-filter android:priority="100">
+                <action android:name="com.android.cts.action.NEW_AUTHORITY" />
+                <data android:host="www.google.com" android:port="80" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
+
diff --git a/packages/CtsShim/shim/AndroidManifest.xml b/packages/CtsShim/shim/AndroidManifest.xml
new file mode 100644
index 0000000..ee4b547
--- /dev/null
+++ b/packages/CtsShim/shim/AndroidManifest.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Manifest for the system CTS shim -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.system.ctsshim">
+    <application android:label="CtsShim">
+
+        <!-- These activities don't actually exist; define them just to test the filters !-->
+
+        <!-- install test; high priority filter DENIED -->
+        <activity android:name=".InstallPriority">
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.SEARCH" />
+                <category android:name="android.intent.category.INFO" />
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.BROWSABLE" />
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.SEND" />
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.SEND_MULTIPLE" />
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.SENDTO" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
+
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 14609b2..69912ab 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -43,9 +43,9 @@
 
         <activity
             android:name=".LauncherActivity"
-            android:theme="@android:style/Theme.NoDisplay"
-            android:icon="@mipmap/ic_launcher_download"
-            android:label="@string/downloads_label">
+            android:label="@string/downloads_label"
+            android:icon="@mipmap/ic_launcher_downloads"
+            android:theme="@android:style/Theme.NoDisplay">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -54,23 +54,23 @@
 
         <activity
             android:name=".FilesActivity"
-            android:theme="@style/DocumentsTheme"
-            android:icon="@mipmap/ic_launcher_download"
             android:label="@string/downloads_label"
-            android:documentLaunchMode="intoExisting">
+            android:icon="@mipmap/ic_launcher_downloads"
+            android:documentLaunchMode="intoExisting"
+            android:theme="@style/DocumentsTheme">
             <intent-filter>
                 <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" />
             </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.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:mimeType="application/zip"
diff --git a/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
index 1c3ed80..0013b6b 100644
--- a/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
+++ b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
@@ -2,6 +2,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.documentsui.appperftests">
 
+    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
+
     <application>
         <uses-library android:name="android.test.runner" />
 
diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
index d6e8a96..ce2fc13 100644
--- a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
+++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
@@ -17,6 +17,8 @@
 package com.android.documentsui;
 
 import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -91,12 +93,15 @@
     }
 
     private void killProviders() throws Exception {
-        final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+        final Context context = getInstrumentation().getContext();
+        final PackageManager pm = context.getPackageManager();
+        final ActivityManager am = (ActivityManager) context.getSystemService(
+                Context.ACTIVITY_SERVICE);
         final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
         final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, 0);
         for (ResolveInfo info : providers) {
             final String packageName = info.providerInfo.packageName;
-            mDevice.executeShellCommand("am force-stop " + packageName);
+            am.killBackgroundProcesses(packageName);
         }
     }
 }
diff --git a/packages/DocumentsUI/res/drawable/drag_shadow_background.xml b/packages/DocumentsUI/res/drawable/drag_shadow_background.xml
new file mode 100644
index 0000000..49465cb
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/drag_shadow_background.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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+  <solid android:color="@color/item_doc_background" />
+  <stroke
+      android:width="1dp"
+      android:color="#ff9f9f9f" />
+  <corners
+      android:bottomRightRadius="3dp"
+      android:bottomLeftRadius="3dp"
+      android:topLeftRadius="3dp"
+      android:topRightRadius="3dp"/>
+</shape>
diff --git a/packages/DocumentsUI/res/layout/drag_shadow_layout.xml b/packages/DocumentsUI/res/layout/drag_shadow_layout.xml
new file mode 100644
index 0000000..26613ef
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/drag_shadow_layout.xml
@@ -0,0 +1,44 @@
+<?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="match_parent"
+    android:layout_height="match_parent"
+    android:paddingStart="8dp"
+    android:paddingEnd="8dp"
+    android:orientation="horizontal"
+    android:gravity="center_vertical|left"
+    android:background="@drawable/drag_shadow_background">
+
+    <ImageView
+        android:id="@android:id/icon"
+        android:layout_width="@dimen/root_icon_size"
+        android:layout_height="@dimen/root_icon_size"
+        android:scaleType="centerInside"
+        android:contentDescription="@null"
+        android:duplicateParentState="true"/>
+
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:maxLines="1"
+        android:ellipsize="end"
+        android:textAlignment="viewStart"
+        android:textColor="@color/item_title"
+        android:paddingStart="8dp"/>
+
+</LinearLayout>
diff --git a/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_downloads.png
similarity index 100%
rename from packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png
rename to packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_downloads.png
similarity index 100%
rename from packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png
rename to packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_downloads.png
similarity index 100%
rename from packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png
rename to packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_downloads.png
similarity index 100%
rename from packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png
rename to packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_downloads.png
similarity index 100%
rename from packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png
rename to packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_downloads.png
Binary files differ
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index 75d9b4b..1a7c620 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Kon nie dokument hernoem nie"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige lêers is omgeskakel"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Gee <xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang tot <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>-gids op <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Gee <xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang tot <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>-gids?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Gee <xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang tot jou data, insluitend foto\'s en video\'s, op <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Moenie weer vra nie"</string>
     <string name="allow" msgid="7225948811296386551">"Laat toe"</string>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index 922b9ca..ca43dab 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ሰነዱን ዳግም መሰየም አልተሳካም"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"አንዳንድ ፋይሎች ተለውጠዋል"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> በ<xliff:g id="STORAGE"><i>^3</i></xliff:g> ላይ የ<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ማውጫ መደረሻ ይሰጠው?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"የ<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ማውጫ መዳረሻ ለ<xliff:g id="APPNAME"><b>^1</b></xliff:g> ይሰጠው?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"በ<xliff:g id="STORAGE"><i>^2</i></xliff:g> ላይ ያሉትን ፎቶዎች እና ቪዲዮዎች ጨምሮ የውሂብዎ መዳረሻ ለ<xliff:g id="APPNAME"><b>^1</b></xliff:g> ይሰጥ?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"ዳግም አትጠይቅ"</string>
     <string name="allow" msgid="7225948811296386551">"ይፍቀዱ"</string>
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index f48c542..e6fac50 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -139,6 +139,7 @@
     <string name="rename_error" msgid="4203041674883412606">"أخفقت إعادة تسمية المستند."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"تم تحويل بعض الملفات"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"هل تريد منح التطبيق <xliff:g id="APPNAME"><b>^1</b></xliff:g> حق الوصول إلى الدليل <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> على <xliff:g id="STORAGE"><i>^3</i></xliff:g>؟"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"هل تريد تمكين <xliff:g id="APPNAME"><b>^1</b></xliff:g> من الدخول إلى دليل <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>؟"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"هل تريد منح <xliff:g id="APPNAME"><b>^1</b></xliff:g> حق الوصول إلى بياناتك، بما في ذلك الصور ومقاطع الفيديو على <xliff:g id="STORAGE"><i>^2</i></xliff:g>؟"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"عدم السؤال مرة أخرى"</string>
     <string name="allow" msgid="7225948811296386551">"السماح"</string>
diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
index a4d6f51..75a0686 100644
--- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml
+++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Sənəd adını dəyişmək uğursuz oldu"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bəzi fayllar konvertasiya edilib"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> yaddaşında <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> kataloquna <xliff:g id="APPNAME"><b>^1</b></xliff:g> girişi təqdim edilsin?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> kataloquna <xliff:g id="APPNAME"><b>^1</b></xliff:g> girişi təqdim edilsin?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> yaddaşında foto və videolar daxil olmaqla datanıza <xliff:g id="APPNAME"><b>^1</b></xliff:g> girişi təmin edilsin?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Bir daha soruşmayın"</string>
     <string name="allow" msgid="7225948811296386551">"İcazə verin"</string>
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index 2c4fe5c..34c08bd 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -118,6 +118,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Preimenovanje dokumenta nije uspelo"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke datoteke su konvertovane"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Želite li da aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> odobrite pristup direktorijumu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> na memorijskom prostoru <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Želite da dozvolite da <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristupa direktorijumu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Želite da li da dozvolite da aplikacija <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristupa podacima, uključujući slike i video snimke, na lokaciji <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ne pitaj ponovo"</string>
     <string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
diff --git a/packages/DocumentsUI/res/values-be-rBY/strings.xml b/packages/DocumentsUI/res/values-be-rBY/strings.xml
index 6e4113e..8493c477 100644
--- a/packages/DocumentsUI/res/values-be-rBY/strings.xml
+++ b/packages/DocumentsUI/res/values-be-rBY/strings.xml
@@ -125,6 +125,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Не атрымалася перайменаваць дакумент"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Некаторыя файлы былі сканвертаваныя"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Даць праграме <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да дырэкторыі <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> у <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Даць праграме <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да дырэкторыі <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Даць <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да вашых даных, у тым ліку фатаграфій і відэа, на <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Больш не пытацца"</string>
     <string name="allow" msgid="7225948811296386551">"Дазволіць"</string>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 4b24a0e..1914bf5 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Преименуването на документа не бе успешно"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Някои файлове бяха преобразувани"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Да се предостави ли на <xliff:g id="APPNAME"><b>^1</b></xliff:g> достъп до директорията „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“ в/ъв <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Да се предостави ли на <xliff:g id="APPNAME"><b>^1</b></xliff:g> достъп до директорията „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Да се предостави ли на <xliff:g id="APPNAME"><b>^1</b></xliff:g> достъп до данните ви в хранилището (<xliff:g id="STORAGE"><i>^2</i></xliff:g>), включително снимки и видеоклипове?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Без повторно питане"</string>
     <string name="allow" msgid="7225948811296386551">"Разрешаване"</string>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index 79cd382..d931c2b 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"দস্তাবেজের পুনঃনামকরণ ব্যর্থ হয়েছে৷"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"কিছু ফাইল রূপান্তরিত হয়েছে"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> কে <xliff:g id="STORAGE"><i>^3</i></xliff:g> এ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> সংগ্রহ অ্যাক্সেস করার মঞ্জুরি দিতে চান?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> কে <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> সংগ্রহ অ্যাক্সেস করার অনুমতি দেবেন?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> এ থাকা ফটো ও ভিডিওগুলি সমেত <xliff:g id="APPNAME"><b>^1</b></xliff:g> কে আপনার ডেটা অ্যাক্সেস করার অনুমতি দেবেন?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"আর জিজ্ঞাসা করবেন না"</string>
     <string name="allow" msgid="7225948811296386551">"অনুমতি দিন"</string>
diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
index 14d6716..47ff436 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml
+++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
@@ -118,6 +118,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Nije uspjelo preimenovanje dokumenta"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke od datoteka su pretvorene"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Omogućiti <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristup direktoriju <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> sa <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Odobriti aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristup direktoriju <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Želite li odobriti aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> pristup svojim podacima, uključujući fotografije i video zapise, na <xliff:g id="STORAGE"><i>^2</i></xliff:g> ?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ne pitaj ponovo"</string>
     <string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 73998b1..09af97d 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"No s\'ha pogut canviar el nom del document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"S\'han convertit alguns fitxers"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Vols que l\'aplicació <xliff:g id="APPNAME"><b>^1</b></xliff:g> tingui accés al directori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> de l\'emmagatzematge <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vols que l\'aplicació <xliff:g id="APPNAME"><b>^1</b></xliff:g> tingui accés al directori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vols que l\'aplicació <xliff:g id="APPNAME"><b>^1</b></xliff:g> tingui accés a les dades de <xliff:g id="STORAGE"><i>^2</i></xliff:g>, incloses les fotos i els vídeos?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"No m\'ho demanis més"</string>
     <string name="allow" msgid="7225948811296386551">"Permet"</string>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index ffabe77..cba2e0e 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -125,6 +125,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Dokument se nepodařilo přejmenovat."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Některé soubory byly převedeny"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Chcete aplikaci <xliff:g id="APPNAME"><b>^1</b></xliff:g> udělit přístup k adresáři <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> v úložišti <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Chcete aplikaci <xliff:g id="APPNAME"><b>^1</b></xliff:g> udělit přístup k adresáři <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Chcete aplikaci <xliff:g id="APPNAME"><b>^1</b></xliff:g> udělit přístup ke svým datům v úložišti <xliff:g id="STORAGE"><i>^2</i></xliff:g>, včetně fotek a videí?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Příště se neptat"</string>
     <string name="allow" msgid="7225948811296386551">"Povolit"</string>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index bf328ab..f048e34 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Dokumentet kunne ikke omdøbes"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nogle filer er konverteret"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Vil du give <xliff:g id="APPNAME"><b>^1</b></xliff:g> adgang til mappen <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> på <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vil du give <xliff:g id="APPNAME"><b>^1</b></xliff:g> adgang til indekset <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vil du give <xliff:g id="APPNAME"><b>^1</b></xliff:g> adgang til dine data, herunder billeder og videoer på <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Spørg ikke igen"</string>
     <string name="allow" msgid="7225948811296386551">"Tillad"</string>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index 9ccb564..a6eae70 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Dokument konnte nicht umbenannt werden"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Einige Dateien wurden konvertiert"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> Zugriff auf das Verzeichnis <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> auf <xliff:g id="STORAGE"><i>^3</i></xliff:g> geben?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Möchtest du <xliff:g id="APPNAME"><b>^1</b></xliff:g> Zugriff auf das Verzeichnis <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> geben?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Möchtest du <xliff:g id="APPNAME"><b>^1</b></xliff:g> Zugriff auf deine Daten auf <xliff:g id="STORAGE"><i>^2</i></xliff:g> geben, einschließlich Fotos und Videos?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Nicht mehr fragen"</string>
     <string name="allow" msgid="7225948811296386551">"Zulassen"</string>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index f23a35d..7dc2067 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Αποτυχία μετονομασίας εγγράφου"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Ορισμένα αρχεία μετατράπηκαν"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Να εκχωρηθεί στην εφαρμογή <xliff:g id="APPNAME"><b>^1</b></xliff:g> πρόσβαση στον κατάλογο <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> στον αποθηκευτικό χώρο <xliff:g id="STORAGE"><i>^3</i></xliff:g>;"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Εκχώρηση πρόσβασης στην εφαρμογή <xliff:g id="APPNAME"><b>^1</b></xliff:g> στον κατάλογο <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>;"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Θέλετε να εκχωρήσετε πρόσβαση στα δεδομένα σας στην εφαρμογή <xliff:g id="APPNAME"><b>^1</b></xliff:g>, συμπεριλαμβανομένων των φωτογραφιών και των βίντεό σας, στον αποθηκευτικό χώρο <xliff:g id="STORAGE"><i>^2</i></xliff:g>;"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Να μην ερωτηθώ ξανά"</string>
     <string name="allow" msgid="7225948811296386551">"Να επιτρέπεται"</string>
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index f82f988..8524de5 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory on <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Don\'t ask again"</string>
     <string name="allow" msgid="7225948811296386551">"Allow"</string>
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index f82f988..8524de5 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory on <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Don\'t ask again"</string>
     <string name="allow" msgid="7225948811296386551">"Allow"</string>
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index f82f988..8524de5 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory on <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> directory?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Grant <xliff:g id="APPNAME"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Don\'t ask again"</string>
     <string name="allow" msgid="7225948811296386551">"Allow"</string>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 5c823d0..87641a7 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"No se pudo cambiar el nombre del documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se convirtieron algunos archivos"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"¿Otorgar acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> al directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> en <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"¿Quieres otorgar acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> al directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"¿Quieres otorgar acceso a la app de <xliff:g id="APPNAME"><b>^1</b></xliff:g> a tus datos, incluidas tus fotos y videos en <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"No volver a preguntar"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 60d1d1c..9054561 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Error al cambiar el nombre del documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se han convertido algunos archivos"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"¿Permitir que <xliff:g id="APPNAME"><b>^1</b></xliff:g> acceda al directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> (<xliff:g id="STORAGE"><i>^3</i></xliff:g>)?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"¿Permitir que <xliff:g id="APPNAME"><b>^1</b></xliff:g> acceda al directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"¿Permitir que <xliff:g id="APPNAME"><b>^1</b></xliff:g> acceda a tus datos, incluidos los vídeos y las fotos, de <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"No volver a preguntar"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index 0fdc435..4bb2a9b 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Dokumendi ümbernimetamine ebaõnnestus"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Mõned failid teisendati"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Kas anda rakendusele <xliff:g id="APPNAME"><b>^1</b></xliff:g> juurdepääs kataloogile <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> salvestusruumis <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Kas anda rakendusele <xliff:g id="APPNAME"><b>^1</b></xliff:g> juurdepääs kataloogile <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Kas anda rakendusele <xliff:g id="APPNAME"><b>^1</b></xliff:g> juurdepääs teie andmetele (sh fotod ja videod) salvestusruumis <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ära enam küsi"</string>
     <string name="allow" msgid="7225948811296386551">"Luba"</string>
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index b54e542..d2bf89d 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Ezin izan zaio aldatu izena dokumentuari"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Artxibo batzuk bihurtu dira"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> aplikazioari <xliff:g id="STORAGE"><i>^3</i></xliff:g> unitateko <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> direktorioa atzitzeko baimena eman nahi diozu?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> aplikazioari <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> direktoriorako sarbidea eman nahi diozu?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> aplikazioari zure datuak atzitzea baimendu nahi diozu, besteak beste, <xliff:g id="STORAGE"><i>^2</i></xliff:g> biltegian dituzun argazkiak eta bideoak?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ez galdetu berriro"</string>
     <string name="allow" msgid="7225948811296386551">"Onartu"</string>
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index cc7eeb5..1a4c035 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"نام سند تغییر نکرد"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"بعضی از فایل‌ها تبدیل شدند"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"به <xliff:g id="APPNAME"><b>^1</b></xliff:g> اجازه داده شود به فهرست راهنمای <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> در <xliff:g id="STORAGE"><i>^3</i></xliff:g> دسترسی داشته باشد؟"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"به <xliff:g id="APPNAME"><b>^1</b></xliff:g> اجازه دسترسی به دایرکتوری <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> داده شود؟"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"به <xliff:g id="APPNAME"><b>^1</b></xliff:g> اجازه می‌دهید به داده‌هایتان دسترسی پیدا کند، از جمله عکس‌ها و ویدیوهایتان در <xliff:g id="STORAGE"><i>^2</i></xliff:g>؟"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"دوباره سؤال نشود"</string>
     <string name="allow" msgid="7225948811296386551">"ارزیابی‌شده"</string>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 17e4d75..dfcfe89 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Dokumentin nimen muuttaminen epäonnistui."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Joitakin tiedostoja muunnettiin."</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Myönnetäänkö sovellukselle <xliff:g id="APPNAME"><b>^1</b></xliff:g> sijainnissa <xliff:g id="STORAGE"><i>^3</i></xliff:g> olevan hakemiston <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> käyttöoikeus?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Saako <xliff:g id="APPNAME"><b>^1</b></xliff:g> käyttää hakemistoa <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Myönnetäänkö sovellukselle <xliff:g id="APPNAME"><b>^1</b></xliff:g> sijainnissa <xliff:g id="STORAGE"><i>^2</i></xliff:g> olevien tietojesi, mukaan lukien valokuviesi ja videoidesi, käyttöoikeus?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Älä kysy uudestaan"</string>
     <string name="allow" msgid="7225948811296386551">"Salli"</string>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index 5dbf5ebe..543e226 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Impossible de renommer le document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Accorder à <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accès au répertoire <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> sur <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Accorder à <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accès au répertoire <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Voulez-vous accorder l\'accès à vos données à <xliff:g id="APPNAME"><b>^1</b></xliff:g>, y compris vos photos et vos vidéos, sur <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ne plus me demander"</string>
     <string name="allow" msgid="7225948811296386551">"Autoriser"</string>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index 127d0da..05716d7 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Échec du changement de nom du document."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Autoriser <xliff:g id="APPNAME"><b>^1</b></xliff:g> à accéder à l\'annuaire \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\" sur <xliff:g id="STORAGE"><i>^3</i></xliff:g> ?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Autoriser <xliff:g id="APPNAME"><b>^1</b></xliff:g> à accéder à l\'annuaire \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\" ?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Autoriser <xliff:g id="APPNAME"><b>^1</b></xliff:g> à accéder à vos données, y compris les photos et les vidéos, sur <xliff:g id="STORAGE"><i>^2</i></xliff:g> ?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ne plus demander"</string>
     <string name="allow" msgid="7225948811296386551">"Autoriser"</string>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index 4cce3c9..5797a96 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Non se puido cambiar o nome do documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Convertéronse algúns ficheiros"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Queres outorgar acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no almacenamento de <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Queres darlle acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao directorio <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Queres darlle acceso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> aos teus datos almacenados en <xliff:g id="STORAGE"><i>^2</i></xliff:g>, incluídos vídeos e fotos?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Non preguntar de novo"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index 1db54f9..48e43c4 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"દસ્તાવેજનું નામ બદલવામાં નિષ્ફળ થયાં"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"કેટલીક ફાઇલો રૂપાંતરિત કરી હતી"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="STORAGE"><i>^3</i></xliff:g> પર <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> નિર્દેશિકાની ઍક્સેસ આપીએ?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> નિર્દેશિકાની ઍક્સેસ આપીએ?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ને <xliff:g id="STORAGE"><i>^2</i></xliff:g> પર ફોટા અને વિડિઓઝ સહિત તમારા ડેટાની અ‍ૅક્સેસ આપીએ?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"ફરીથી પૂછશો નહીં"</string>
     <string name="allow" msgid="7225948811296386551">"મંજૂરી આપો"</string>
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index de1e25e..fa82ee8 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"दस्‍तावेज़ का नाम बदलना विफल रहा"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"कुछ फ़ाइलें रूपांतरित हो गई थीं"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="STORAGE"><i>^3</i></xliff:g> पर <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिका का एक्सेस दें?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिका का एक्सेस प्रदान करें?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> को <xliff:g id="STORAGE"><i>^2</i></xliff:g> पर मौजूद फ़ोटो और वीडियो सहित, अपने डेटा का एक्सेस प्रदान करें?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"फिर से ना पूछें"</string>
     <string name="allow" msgid="7225948811296386551">"अनुमति दें"</string>
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index bf91c6a..7988c71 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -118,6 +118,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Naziv dokumenta nije promijenjen"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke su datoteke konvertirane"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Želite li aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> odobriti pristup direktoriju <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> na pohrani <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Želite li aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> odobriti da pristupa direktoriju <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Želite li aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dopustiti pristup podacima, uključujući fotografije i videozapise na vanjskoj pohrani (<xliff:g id="STORAGE"><i>^2</i></xliff:g>)?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Više me ne pitaj"</string>
     <string name="allow" msgid="7225948811296386551">"Dopusti"</string>
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index f955318..fb666b5 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Nem sikerült átnevezni a dokumentumot"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Egyes fájlokat konvertált a rendszer"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Hozzáférést biztosít a(z) <xliff:g id="APPNAME"><b>^1</b></xliff:g> számára a(z) <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> könyvtárhoz itt: <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Hozzáférést biztosít a(z) <xliff:g id="APPNAME"><b>^1</b></xliff:g> alkalmazásnak a(z) <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> könyvtárhoz?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Hozzáférést biztosít a(z) <xliff:g id="APPNAME"><b>^1</b></xliff:g> számára az Ön adataihoz, beleértve a következő tárhelyen található képekhez és videókhoz: <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ne jelenjen meg többé"</string>
     <string name="allow" msgid="7225948811296386551">"Engedélyezés"</string>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index b1af92c..f6c3ad5 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Չհաջողվեց վերանվանել փաստաթուղթը"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Որոշ ֆայլեր փոխարկվել են"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> հավելվածին տրամադրե՞լ <xliff:g id="STORAGE"><i>^3</i></xliff:g>-ի <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> գրացուցակն օգտագործելու թույլտվություն:"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> հավելվածին տրամադրե՞լ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> գրացուցակն օգտագործելու թույլտվություն:"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> հավելվածին տրամադրե՞լ <xliff:g id="STORAGE"><i>^2</i></xliff:g>-ում պահվող ձեր տվյալները, այդ թվում նաև լուսանկարները և տեսանյութերը, օգտագործելու թույլտվություն:"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Այլևս չհարցնել"</string>
     <string name="allow" msgid="7225948811296386551">"Թույլատրել"</string>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index 87576fb..a8aee52 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Gagal mengganti nama dokumen"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Beberapa file dikonversi"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses ke direktori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> di <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses ke direktori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses ke data Anda, termasuk foto dan video, di <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Jangan tanya lagi"</string>
     <string name="allow" msgid="7225948811296386551">"Izinkan"</string>
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index d3be73a..88aaced 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Ekki tókst að endurnefna skjalið"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sumum skrám var umbreytt"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Veita <xliff:g id="APPNAME"><b>^1</b></xliff:g> aðgang að skráasafninu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> á <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Viltu veita <xliff:g id="APPNAME"><b>^1</b></xliff:g> aðgang að skráasafninu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Veita <xliff:g id="APPNAME"><b>^1</b></xliff:g> aðgang að gögnunum þínum, þar á meðal myndum og myndskeiðum, á <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ekki spyrja aftur"</string>
     <string name="allow" msgid="7225948811296386551">"Leyfa"</string>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index 736d31c..b7497db 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Ridenominazione documento non riuscita"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alcuni file sono stati convertiti"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Concedere all\'app <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accesso alla directory <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> su <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Concedere all\'app <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accesso alla directory <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Concedere all\'app <xliff:g id="APPNAME"><b>^1</b></xliff:g> l\'accesso ai tuoi dati, inclusi video e foto, sull\'unità <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Non chiedermelo più"</string>
     <string name="allow" msgid="7225948811296386551">"Consenti"</string>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 2446a4b..4498f8c 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -125,6 +125,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ניסיון שינוי שם המסמך נכשל"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"קבצים מסוימים הומרו"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"האם להעניק לאפליקציה <xliff:g id="APPNAME"><b>^1</b></xliff:g> גישה לספריה <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> באחסון <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"האם להעניק לאפליקציה <xliff:g id="APPNAME"><b>^1</b></xliff:g> גישה אל ספריית <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"האם להעניק לאפליקציה <xliff:g id="APPNAME"><b>^1</b></xliff:g> גישה לנתונים שלך, כולל תמונות וסרטונים, השמורים ב<xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"אל תשאל שוב"</string>
     <string name="allow" msgid="7225948811296386551">"אפשר"</string>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index dc39b99..bfb1c3a 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ドキュメントの名前を変更できませんでした"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"一部のファイルが変換されました"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"「<xliff:g id="STORAGE"><i>^3</i></xliff:g>」の「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」ディレクトリに「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」へのアクセスを許可しますか?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」アプリに「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」ディレクトリへのアクセスを許可しますか?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g>の写真や動画などのデータへのアクセスを「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」に許可しますか?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"今後表示しない"</string>
     <string name="allow" msgid="7225948811296386551">"許可"</string>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index 0af8dd9..f0e9e86 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"დოკუმენტის გადარქმევა ვერ მოხერხდა"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ზოგიერთი ფაილი გარდაქმნილია"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"გსურთ, <xliff:g id="APPNAME"><b>^1</b></xliff:g> სარგებლობდეს <xliff:g id="STORAGE"><i>^3</i></xliff:g>-ის დირექტორიაზე „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“ წვდომის უფლებით?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"გსურთ, <xliff:g id="APPNAME"><b>^1</b></xliff:g> სარგებლობდეს დირექტორიაზე „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“ წვდომის უფლებით?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"გსურთ, <xliff:g id="APPNAME"><b>^1</b></xliff:g> სარგებლობდეს <xliff:g id="STORAGE"><i>^2</i></xliff:g>-ზე არსებულ მონაცემებზე, მათ შორის, ფოტოებსა და ვიდეოებზე, წვდომის უფლებით?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"აღარ მკითხოთ"</string>
     <string name="allow" msgid="7225948811296386551">"უფლების მიცემა"</string>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index 3d6b758..2687900 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Құжат қайта аталмады"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Кейбір файлдар түрлендірілді"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> қолданбасына <xliff:g id="STORAGE"><i>^3</i></xliff:g> қоймасындағы <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> каталогына өтуге рұқсат беру керек пе?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> қолданбасына <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> каталогына қатынас беру керек пе?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> <xliff:g id="STORAGE"><i>^2</i></xliff:g> қоймасындағы деректерге, соның ішінде фотосуреттерге және бейнелерге кіру мүмкіндігін беру керек пе?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Қайта сұралмасын"</string>
     <string name="allow" msgid="7225948811296386551">"Рұқсат беру"</string>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index 0eb1396..ea24043 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"បានបរាជ័យក្នុងការប្តូរឈ្មោះឯកសារ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ឯកសារមួយចំនួនត្រូវបានបម្លែង"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"ផ្តល់សិទ្ធិឲ្យ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ចូលដំណើរការថត <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> នៅលើ <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"ផ្តល់សិទ្ធិឲ្យ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ចូលដំណើរការថត <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ឬ?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"ផ្តល់សិទ្ធិអនុញ្ញាតដល់ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ដើម្បីចូលដំណើរការទិន្នន័យរបស់អ្នក រាប់បញ្ចូលទាំងរូបថត និងវីដេអូ នៅលើ <xliff:g id="STORAGE"><i>^2</i></xliff:g> ឬទេ?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"កុំសួរទៀត"</string>
     <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត​"</string>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index a5a8ab2..c756009 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ಡಾಕ್ಯುಮೆಂಟ್ ಮರುಹೆಸರಿಸಲು ವಿಫಲವಾಗಿದೆ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ಕೆಲವು ಫೈಲ್‌ಗಳನ್ನು ಪರಿವರ್ತಿಸಲಾಗಿದೆ"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> ರಲ್ಲಿ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ಡೈರೆಕ್ಟರಿಗೆ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ಪ್ರವೇಶ ನೀಡುವುದೇ?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g><xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ಡೈರೆಕ್ಟರಿ ಪ್ರವೇಶಿಸಲು ಅನುಮತಿಸುವುದೇ?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> ಸಂಗ್ರಹಣೆಯಲ್ಲಿನ ಪೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APPNAME"><b>^1</b></xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುವುದೇ?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"ಮತ್ತೆ ಕೇಳಬೇಡಿ"</string>
     <string name="allow" msgid="7225948811296386551">"ಅನುಮತಿಸು"</string>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index 9975ce0..4d5dcf9 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"문서 이름을 변경하지 못했습니다."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"일부 파일이 변환되었습니다."</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>이(가) <xliff:g id="STORAGE"><i>^3</i></xliff:g>에서 <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> 디렉토리에 액세스하도록 허용하시겠습니까?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>이(가) <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> 디렉토리에 액세스하도록 허용하시겠습니까?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>에서 사진, 동영상 등 <xliff:g id="STORAGE"><i>^2</i></xliff:g>의 내 데이터에 액세스하도록 허용하시겠습니까?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"다시 묻지 않음"</string>
     <string name="allow" msgid="7225948811296386551">"허용"</string>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index be2aca8..1b39039 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Документтин аталышы өзгөртүлбөй калды"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Айрым файлдардын форматы өзгөртүлдү"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> колдонмосуна <xliff:g id="STORAGE"><i>^3</i></xliff:g> түзмөгүндөгү <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> папканы пайдалануу мүмкүнчүлүгү берилсинби?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> колдонмосуна <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> каталогун пайдалануу мүмкүнчүлүгү берилсинби?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> колдонмосуна <xliff:g id="STORAGE"><i>^2</i></xliff:g> түзмөгүндөгү дайындарыңыз, сүрөттөрүңүз жана видеолоруңузду пайдалануу мүмкүнчүлүгү берилсинби?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Экинчи суралбасын"</string>
     <string name="allow" msgid="7225948811296386551">"Уруксат берүү"</string>
@@ -130,7 +131,7 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> куржун мазмуну менен жок кылынсынбы?</item>
     </plurals>
     <plurals name="delete_items_confirmation_message" formatted="false" msgid="5376214433530243459">
-      <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>
+      <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/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index ed96464..a4f381d 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ປ່ຽນຊື່ເອກະສານບໍ່ສຳເລັດ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ປ່ຽນແປງບາງໄຟລ໌ແລ້ວ"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"ອະນຸຍາດສິດເຂົ້າເຖິງໃຫ້ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ເພື່ອເຂົ້າໄດເຣກທໍຣີ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ຢູ່ <xliff:g id="STORAGE"><i>^3</i></xliff:g> ບໍ?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"ອະນຸມັດ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ໃຫ້ເຂົ້າຫາໄດເຣັກທໍຣີ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ບໍ?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"ອະນຸມັດໃຫ້ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ເຂົ້າເຖິງຂໍ້ມູນຂອງທ່ານ ເຊິ່ງຮວມເຖິງຮູບພາບ ແລະ ວິດີໂອໃນ <xliff:g id="STORAGE"><i>^2</i></xliff:g> ໄດ້ບໍ?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"ບໍ່ຕ້ອງຖາມຄືນ"</string>
     <string name="allow" msgid="7225948811296386551">"ອະນຸຍາດ"</string>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 0e95ea0..2e0df93 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -125,6 +125,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Nepavyko pervardyti dokumento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Kai kurie failai buvo konvertuoti"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Suteikti „<xliff:g id="APPNAME"><b>^1</b></xliff:g>“ prieigą prie katalogo „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“ <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Suteikti „<xliff:g id="APPNAME"><b>^1</b></xliff:g>“ prieigą prie katalogo „<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>“?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Suteikti programai „<xliff:g id="APPNAME"><b>^1</b></xliff:g>“ prieigą prie duomenų, įskaitant nuotraukas ir vaizdo įrašus, <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Daugiau neklausti"</string>
     <string name="allow" msgid="7225948811296386551">"Leisti"</string>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 9f39f2e..fb81aa0 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -118,6 +118,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Neizdevās pārdēvēt dokumentu"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Daži faili tika pārveidoti."</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Vai atļaut lietotnei <xliff:g id="APPNAME"><b>^1</b></xliff:g> piekļūt direktorijam <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> šajā krātuvē: <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vai piešķirt lietotnei <xliff:g id="APPNAME"><b>^1</b></xliff:g> piekļuvi direktorijam <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vai atļaut lietotnei <xliff:g id="APPNAME"><b>^1</b></xliff:g> piekļūt jūsu datiem, tostarp fotoattēliem un videoklipiem, šajā krātuvē: <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Turpmāk vairs nejautāt"</string>
     <string name="allow" msgid="7225948811296386551">"Atļaut"</string>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index bc3b7fa..ad428a0 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Не успеа да се преименува документот"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Некои датотеки беа конвертирани"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Овозможете пристап на <xliff:g id="APPNAME"><b>^1</b></xliff:g> до директориумот <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> на <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Овозможете пристап на <xliff:g id="APPNAME"><b>^1</b></xliff:g> до директориумот <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Да се овозможи пристап на <xliff:g id="APPNAME"><b>^1</b></xliff:g> до вашите податоци, вклучувајќи фотографии и видеа, на <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Не прашувај повторно"</string>
     <string name="allow" msgid="7225948811296386551">"Дозволи"</string>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index 9a7509f..5a16512 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ഡോക്യുമെന്റിന്റെ പേരുമാറ്റുന്നത് പരാജയപ്പെട്ടു"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ചില ഫയലുകൾ പരിവർത്തനം ചെയ്യപ്പെട്ടു"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> സ്റ്റോറേജിലെ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> എന്ന ഡയറക്റ്ററിയിലേക്ക് <xliff:g id="APPNAME"><b>^1</b></xliff:g> ആപ്പിന് ആക്സസ് അനുവദിക്കണോ?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> എന്ന ഡയറക്ടറിയിലേക്ക് <xliff:g id="APPNAME"><b>^1</b></xliff:g> ആപ്പിന് ആക്സസ് അനുവദിക്കണോ?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> സ്റ്റോറേജിലെ ഫോട്ടോകളും വീഡിയോകളും ഉൾപ്പെടെ, നിങ്ങളുടെ ഡാറ്റയിലേക്ക് <xliff:g id="APPNAME"><b>^1</b></xliff:g> ആപ്പിന് ആക്സസ്സ് അനുവദിക്കണോ?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"വീണ്ടും ആവശ്യപ്പെടരുത്"</string>
     <string name="allow" msgid="7225948811296386551">"അനുവദിക്കുക"</string>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index f424f8e..cf2c2d4 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Баримт бичгийн нэрийн өөрчилж чадсангүй"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Зарим файлыг хөрвүүлсэн"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g>-д байгаа <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> лавлагаанд хандахыг <xliff:g id="APPNAME"><b>^1</b></xliff:g>-д зөвшөөрөх үү?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> лавлагаанд хандах эрхийг <xliff:g id="APPNAME"><b>^1</b></xliff:g>-д олгох уу?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g>-д байгаа зураг, видео гэх мэт таны өгөгдөлд <xliff:g id="APPNAME"><b>^1</b></xliff:g> хандахыг зөвшөөрөх үү?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Дахин бүү асуу"</string>
     <string name="allow" msgid="7225948811296386551">"Зөвшөөрөх"</string>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index 556c1e6..09dd133 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"दस्तऐवज पुनर्नामित करण्‍यात अयशस्वी झाले"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"काही फायली रूपांतरित केल्या होत्या"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> वर <xliff:g id="APPNAME"><b>^1</b></xliff:g> ला <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिकेवर प्रवेशाची मंजूरी द्यायची?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ला <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिकमध्ये प्रवेश मंजूर करायचा?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ला <xliff:g id="STORAGE"><i>^2</i></xliff:g> वर फोटो आणि व्हिडिओंसह, आपल्या डेटामध्ये प्रवेश करण्याची मंजूरी द्यायची?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"पुन्हा विचारू नका"</string>
     <string name="allow" msgid="7225948811296386551">"अनुमती द्या"</string>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 0f2af2f..9eb3d49 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Gagal menamakan semula dokumen"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sesetengah fail telah ditukarkan"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses kepada direktori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> di <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses kepada direktori <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Beri <xliff:g id="APPNAME"><b>^1</b></xliff:g> akses kepada data anda, termasuk foto dan video pada <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Jangan tanya lagi"</string>
     <string name="allow" msgid="7225948811296386551">"Benarkan"</string>
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 6acbc80..7c637c4 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"စာရွက်စာတမ်းကို အမည်ပြောင်းခြင်း မအောင်မြင်ပါ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"အချို့ဖိုင်များကို ပြောင်းလဲထားသည်"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ကို <xliff:g id="STORAGE"><i>^3</i></xliff:g> ရှိ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> လမ်းညွှန်အား အသုံးပြုခွင့်ပေးမလား။"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> အား <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> စာရင်းကို အသုံးပြုခွင့်ပေးမလား။"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> ရှိဓာတ်ပုံများနှင့် ဗီဒီယိုများအပါအဝင် သင့်ဒေတာများကို <xliff:g id="APPNAME"><b>^1</b></xliff:g> အားအသုံးပြုခွင့်ပေးမလား။"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"နောက်ထပ်မမေးပါနှင့်"</string>
     <string name="allow" msgid="7225948811296386551">"ခွင့်ပြုသည်"</string>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index c2c983e..3c344eb 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Kunne ikke gi dokumentet nytt navn"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Noen filer er konvertert"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Vil du gi <xliff:g id="APPNAME"><b>^1</b></xliff:g> tilgang til <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>-katalogen på <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vil du gi <xliff:g id="APPNAME"><b>^1</b></xliff:g> tilgang til <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>-katalogen?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vil du gi <xliff:g id="APPNAME"><b>^1</b></xliff:g> tilgang til dataene dine – inkludert bilder og videoer – på <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ikke spør igjen"</string>
     <string name="allow" msgid="7225948811296386551">"Tillat"</string>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index 31c4c2c..9fef037 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"कागजात पुन: नामाकरण गर्न असफल भयो"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"केही फाइलहरू परिवर्तन गरिएका थिए"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> लाई <xliff:g id="STORAGE"><i>^3</i></xliff:g> मा भएको <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिकामा पहुँच गर्न अनुमति दिने हो?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> लाई <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> निर्देशिकामाथि पहुँच गर्न अनुमति प्रदान गर्ने हो?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> लाई <xliff:g id="STORAGE"><i>^2</i></xliff:g> मा भएका तस्बिर र भिडियोहरू लगायत तपाईँको डेटामा पहुँच गर्नका लागि अनुमति दिने हो?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"फेरि नसोध्नुहोस्"</string>
     <string name="allow" msgid="7225948811296386551">"अनुमति दिनुहोस्"</string>
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index 385b507..c5b9d76 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Kan naam van document niet wijzigen"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige bestanden zijn geconverteerd"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang verlenen tot de map <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> op <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang verlenen tot de map <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> toegang verlenen tot je gegevens, waaronder foto\'s en video\'s, op <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Niet meer vragen"</string>
     <string name="allow" msgid="7225948811296386551">"Toestaan"</string>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index 7603f58..7d5e14a 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ਦਸਤਾਵੇਜ਼ ਦਾ ਮੁੜ-ਨਾਮਕਰਨ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ਕੁਝ ਫ਼ਾਈਲਾਂ ਤਬਦੀਲ ਕੀਤੀਆਂ ਗਈਆਂ ਸਨ"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="STORAGE"><i>^3</i></xliff:g> \'ਤੇ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ਡਾਇਰੈਕਟਰੀ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ਡਾਇਰੈਕਟਰੀ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"ਕੀ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ਨੂੰ <xliff:g id="STORAGE"><i>^2</i></xliff:g> \'ਤੇ ਫੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਸਮੇਤ, ਤੁਹਾਡੇ ਡੈਟੇ \'ਤੇ ਪਹੁੰਚ ਦੇਣੀ ਹੈ?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"ਦੁਬਾਰਾ ਨਾ ਪੁੱਛੋ"</string>
     <string name="allow" msgid="7225948811296386551">"ਆਗਿਆ ਦਿਓ"</string>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index b234a9e..ca007d7 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -125,6 +125,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Nie udało się zmienić nazwy dokumentu"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektóre pliki zostały przekonwertowane"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Zezwolić aplikacji <xliff:g id="APPNAME"><b>^1</b></xliff:g> na dostęp do katalogu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> w pamięci masowej <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Przyznać aplikacji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dostęp do katalogu <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Zezwolić aplikacji <xliff:g id="APPNAME"><b>^1</b></xliff:g> na dostęp do Twoich danych, w tym zdjęć i filmów, zapisanych w pamięci <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Nie pytaj ponownie"</string>
     <string name="allow" msgid="7225948811296386551">"Zezwól"</string>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index 634ac96..21359c7 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Conceder ao <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Conceder acesso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no/na <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Não perguntar novamente"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index 5440801..aea1249 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Falha ao mudar o nome do documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns ficheiros foram convertidos"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Pretende conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no(a) <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Pretende conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Pretende conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no(a) <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Não perguntar novamente"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 634ac96..21359c7 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Conceder ao <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Conceder acesso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no/na <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Não perguntar novamente"</string>
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index 3dc93ef..4b833b1 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -118,6 +118,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Documentul nu a putut fi redenumit"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Unele fișiere au fost convertite"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Permiteți aplicației <xliff:g id="APPNAME"><b>^1</b></xliff:g> accesul la directorul <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> de pe <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Permiteți aplicației <xliff:g id="APPNAME"><b>^1</b></xliff:g> să acceseze directorul <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Permiteți aplicației <xliff:g id="APPNAME"><b>^1</b></xliff:g> să vă acceseze datele, inclusiv fotografiile și videoclipurile, de pe <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Nu mai întreba"</string>
     <string name="allow" msgid="7225948811296386551">"Permiteți"</string>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index fef3015..6ba635d 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -125,6 +125,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Не удалось переименовать документ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Формат некоторых файлов изменен"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Открыть приложению \"<xliff:g id="APPNAME"><b>^1</b></xliff:g>\" доступ к папке \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\" на устройстве \"<xliff:g id="STORAGE"><i>^3</i></xliff:g>\"?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Открыть приложению \"<xliff:g id="APPNAME"><b>^1</b></xliff:g>\" доступ к папке \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\"?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Открыть приложению \"<xliff:g id="APPNAME"><b>^1</b></xliff:g>\" доступ к вашим данным, включая фото и видео, на носителе: <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Больше не спрашивать"</string>
     <string name="allow" msgid="7225948811296386551">"Разрешить"</string>
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index d49c2f3..41c9d4a 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ලේඛනය යළි නම් කිරීම අසාර්ථක විය"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"සමහර ගොනු පරිවර්තනය කරන ලදී"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> හට <xliff:g id="STORAGE"><i>^3</i></xliff:g> මත <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> නාමාවලිය වෙත ප්‍රවේශය දෙන්නද?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ප්‍රවේශය <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> නාමාවලිය වෙත ලබා දෙන්නද?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> හි, ඡායාරූප සහ වීඩියෝ ඇතුළුව, ඔබේ දත්තවලට <xliff:g id="APPNAME"><b>^1</b></xliff:g> හට ප්‍රවේශය ලබා දෙන්නද?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"නැවත අසන්න එපා"</string>
     <string name="allow" msgid="7225948811296386551">"අවසර දෙන්න"</string>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index bd75175..1ff01b0 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -125,6 +125,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Premenovanie dokumentu zlyhalo"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektoré súbory boli konvertované"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Udeliť aplikácii <xliff:g id="APPNAME"><b>^1</b></xliff:g> prístup k adresáru <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> v úložisku <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Udeliť aplikácii <xliff:g id="APPNAME"><b>^1</b></xliff:g> prístup k adresáru <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Chcete aplikácii <xliff:g id="APPNAME"><b>^1</b></xliff:g> udeliť prístup k dátam (vrátane fotiek a videí) v úložisku <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Nabudúce sa nepýtať"</string>
     <string name="allow" msgid="7225948811296386551">"Povoliť"</string>
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index 78ec8fe..d8b983c 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -125,6 +125,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Dokumenta ni bilo mogoče preimenovati"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nekatere datoteke so bile pretvorjene"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Želite aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dovoliti dostop do imenika <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> v shrambi <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Želite aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dovoliti dostop do imenika <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Odobrite aplikaciji <xliff:g id="APPNAME"><b>^1</b></xliff:g> dostop do podatkov, vključno s fotografijami in videoposnetki, v shrambi <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ne sprašuj več"</string>
     <string name="allow" msgid="7225948811296386551">"Dovoli"</string>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index 662e7f0..933a537 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Riemërtimi i dokumentit dështoi"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Disa skedarë u konvertuan"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Jepi aplikacionit <xliff:g id="APPNAME"><b>^1</b></xliff:g> qasje te direktoria <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> në <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"T\'i jepet aplikacionit <xliff:g id="APPNAME"><b>^1</b></xliff:g> qasje te direktoria <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"T\'i jepet aplikacionit <xliff:g id="APPNAME"><b>^1</b></xliff:g> qasje te të dhënat, duke përfshirë fotografitë dhe videot, në <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Mos pyet përsëri"</string>
     <string name="allow" msgid="7225948811296386551">"Lejo"</string>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index 690f81c..0505f42 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -118,6 +118,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Преименовање документа није успело"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Неке датотеке су конвертоване"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Желите ли да апликацији <xliff:g id="APPNAME"><b>^1</b></xliff:g> одобрите приступ директоријуму <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> на меморијском простору <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Желите да дозволите да <xliff:g id="APPNAME"><b>^1</b></xliff:g> приступа директоријуму <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Желите да ли да дозволите да апликација <xliff:g id="APPNAME"><b>^1</b></xliff:g> приступа подацима, укључујући слике и видео снимке, на локацији <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Не питај поново"</string>
     <string name="allow" msgid="7225948811296386551">"Дозволи"</string>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index 1849782..99f334b 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Det gick inte att byta namn på dokumentet"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Vissa filer konverterades"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Vill du ge <xliff:g id="APPNAME"><b>^1</b></xliff:g> åtkomst till katalogen <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> på <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Vill du ge <xliff:g id="APPNAME"><b>^1</b></xliff:g> åtkomst till katalogen <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Vill du ge <xliff:g id="APPNAME"><b>^1</b></xliff:g> åtkomst till din data (inklusive foton och videor) på <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Fråga inte igen"</string>
     <string name="allow" msgid="7225948811296386551">"Tillåt"</string>
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index bf4b744..566e6a4 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Imeshindwa kubadilisha jina la hati"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Baadhi ya faili zimebadilishwa muundo"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Ungependa kuruhusu <xliff:g id="APPNAME"><b>^1</b></xliff:g> ifikie saraka ya <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> kwenye <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Ungependa kuruhusu <xliff:g id="APPNAME"><b>^1</b></xliff:g> ifikie saraka ya <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Ungependa kuruhusu <xliff:g id="APPNAME"><b>^1</b></xliff:g> ifikie data yako, ikiwa ni pamoja na picha na video kwenye <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Usiniulize tena"</string>
     <string name="allow" msgid="7225948811296386551">"Ruhusu"</string>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 43d29e2..9a8b4ec 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ஆவணத்திற்கு மறுபெயரிடுவதில் தோல்வி"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"சில கோப்புகள் மாற்றப்பட்டன"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="STORAGE"><i>^3</i></xliff:g> இல் உள்ள <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> கோப்பகத்தை அணுக <xliff:g id="APPNAME"><b>^1</b></xliff:g>ஐ அனுமதிக்கவா?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> கோப்பகத்தை அணுக, <xliff:g id="APPNAME"><b>^1</b></xliff:g>ஐ அனுமதிக்கவா?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g> இல் உள்ள படங்கள், வீடியோக்கள் உட்பட எல்லா தரவையும் அணுக, <xliff:g id="APPNAME"><b>^1</b></xliff:g>ஐ அனுமதிக்கவா?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"மீண்டும் கேட்காதே"</string>
     <string name="allow" msgid="7225948811296386551">"அனுமதி"</string>
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index c9233ec..224d0db 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"పత్రం పేరు మార్చడంలో విఫలమైంది"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"కొన్ని పైల్‌లు మార్చబడ్డాయి"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>కి <xliff:g id="STORAGE"><i>^3</i></xliff:g>లో <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> డైరెక్టరీ ప్రాప్యతను మంజూరు చేయాలా?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g>కి <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> డైరెక్టరీ ప్రాప్యతను మంజూరు చేయాలా?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="STORAGE"><i>^2</i></xliff:g>లో ఫోటోలు మరియు వీడియోలతో సహా మీ డేటా ప్రాప్యతను <xliff:g id="APPNAME"><b>^1</b></xliff:g>కి మంజూరు చేయాలా?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"మళ్లీ అడగవద్దు"</string>
     <string name="allow" msgid="7225948811296386551">"అనుమతించండి"</string>
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 491e984..af07584 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"ไม่สามารถเปลี่ยนชื่อเอกสาร"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"แปลงบางไฟล์แล้ว"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"ให้สิทธิ์ <xliff:g id="APPNAME"><b>^1</b></xliff:g> ในการเข้าถึงไดเรกทอรี <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ใน <xliff:g id="STORAGE"><i>^3</i></xliff:g> ไหม"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"ให้สิทธิ์ <xliff:g id="APPNAME"><b>^1</b></xliff:g> เข้าถึงไดเรกทอรี <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ไหม"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"ให้สิทธิ์ <xliff:g id="APPNAME"><b>^1</b></xliff:g> เข้าถึงข้อมูลของคุณ รวมถึงรูปภาพและวิดีโอใน <xliff:g id="STORAGE"><i>^2</i></xliff:g> ไหม"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"ไม่ต้องถามอีก"</string>
     <string name="allow" msgid="7225948811296386551">"อนุญาต"</string>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index 27d6671..b2acf05 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Hindi napalitan ang pangalan ng dokumento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Na-convert ang ilang file"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Bigyan ang <xliff:g id="APPNAME"><b>^1</b></xliff:g> ng access sa directory ng <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> sa <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Bibigyan ang <xliff:g id="APPNAME"><b>^1</b></xliff:g> ng access sa direktoryong <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Bigyan ang <xliff:g id="APPNAME"><b>^1</b></xliff:g> ng access sa iyong data, kabilang ang mga larawan at video, sa <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Huwag nang tatanunging muli"</string>
     <string name="allow" msgid="7225948811296386551">"Payagan"</string>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index dda9f28..c5653c9 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Dokümanın adı değiştirilemedi"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bazı dosyalar dönüştürüldü"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> uygulamasına <xliff:g id="STORAGE"><i>^3</i></xliff:g> depolama alanındaki <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> dizinine erişim izni verilsin mi?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> dizinine erişmek için <xliff:g id="APPNAME"><b>^1</b></xliff:g> uygulamasına izin verilsin mi?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> uygulamasının, fotoğraflar ve videolar dahil olmak üzere <xliff:g id="STORAGE"><i>^2</i></xliff:g> üzerindeki verilerinize erişmesine izin verilsin mi?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Tekrar sorma"</string>
     <string name="allow" msgid="7225948811296386551">"İzin Ver"</string>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index ec7e1d6..21532b6 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -125,6 +125,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Не вдалося перейменувати документ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Деякі файли конвертовано"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Надати додатку <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ до каталогу <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> на пристрої пам’яті <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Надати додатку <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ до каталогу \"<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>\"?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Надати додатку <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ до ваших даних, зокрема до фотографій і відео, які містить <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Не запитувати знову"</string>
     <string name="allow" msgid="7225948811296386551">"Дозвол."</string>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index 4ea9985..eb0cfc8 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"دستاویز کا نام تبدیل کرنے میں ناکام"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"کچھ فائلوں کو تبدیل کیا گیا تھا"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> کو <xliff:g id="STORAGE"><i>^3</i></xliff:g> پر <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ڈائرکٹری تک رسائی عطا کریں؟"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> کو <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ڈائرکٹری تک رسائی دیں؟"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> کو اپنے ڈیٹا بشمول <xliff:g id="STORAGE"><i>^2</i></xliff:g> پر موجود تصاویر اور ویڈیوز تک رسائی عطا کریں؟"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"دوبارہ نہ پوچھیں"</string>
     <string name="allow" msgid="7225948811296386551">"اجازت دیں"</string>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index dffbba5..2654308 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -110,7 +110,8 @@
     <string name="menu_rename" msgid="7678802479104285353">"Qayta nomlash"</string>
     <string name="rename_error" msgid="4203041674883412606">"Hujjatni qayta nomlab bo‘lmadi"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bir nechta fayllar o‘girildi"</string>
-    <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ilovasining <xliff:g id="STORAGE"><i>^3</i></xliff:g> xotirasidagi “<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>” jildiga kirishiga ruxsat berilsinmi?"</string>
+    <string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ilovasiga <xliff:g id="STORAGE"><i>^3</i></xliff:g> xotirasidagi “<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>” jildidan foydalanishiga ruxsat berilsinmi?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ilovasiga “<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>” jildidan foydalanishiga ruxsat berilsinmi?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> ilovasiga <xliff:g id="STORAGE"><i>^2</i></xliff:g> xotirasidagi ma’lumotlardan, jumladan, rasmlar va videolardan foydalanishiga ruxsat berilsinmi?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Boshqa so‘ralmasin"</string>
     <string name="allow" msgid="7225948811296386551">"Ruxsat berish"</string>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index 127c2d3..9af7db0 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Không đổi được tên tài liệu"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Đã chuyển đổi một số tệp"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Cấp cho <xliff:g id="APPNAME"><b>^1</b></xliff:g> quyền truy cập vào thư mục <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> trong <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Cấp cho <xliff:g id="APPNAME"><b>^1</b></xliff:g> quyền truy cập thư mục <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Cấp cho <xliff:g id="APPNAME"><b>^1</b></xliff:g> quyền truy cập vào dữ liệu của bạn, kể cả ảnh và video trên <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Không hỏi lại"</string>
     <string name="allow" msgid="7225948811296386551">"Cho phép"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index 45d22a3..e3db1a0 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"无法重命名文档"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分文件已转换成其他格式"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问 <xliff:g id="STORAGE"><i>^3</i></xliff:g>上的“<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>”目录吗?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>目录吗?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问您 <xliff:g id="STORAGE"><i>^2</i></xliff:g>上的数据(包括照片和视频)吗?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"不再询问"</string>
     <string name="allow" msgid="7225948811296386551">"允许"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index 08aefdd..f13a4bd1 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"無法重新命名文件"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"要為「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」開放 <xliff:g id="STORAGE"><i>^3</i></xliff:g>上的「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」目錄存取權嗎?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"要為「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」開放「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」目錄的存取權嗎?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"要向「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」開放 <xliff:g id="STORAGE"><i>^2</i></xliff:g>上的相片和影片等資料的存取權嗎?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"不要再詢問"</string>
     <string name="allow" msgid="7225948811296386551">"允許"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index 90c932c..f8f8282 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"無法重新命名文件"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"要允許<xliff:g id="APPNAME"><b>^1</b></xliff:g>存取 <xliff:g id="STORAGE"><i>^3</i></xliff:g>上的「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」目錄嗎?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"要允許<xliff:g id="APPNAME"><b>^1</b></xliff:g>存取「<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>」目錄嗎?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"要允許「<xliff:g id="APPNAME"><b>^1</b></xliff:g>」存取 <xliff:g id="STORAGE"><i>^2</i></xliff:g>上的資料 (包括相片和影片) 嗎?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"不要再詢問"</string>
     <string name="allow" msgid="7225948811296386551">"允許"</string>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index e83bb3d..a0b9f7f 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -111,6 +111,7 @@
     <string name="rename_error" msgid="4203041674883412606">"Yehlulekile ukuqamba kabusha idokhumenti"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Amanye amafayela aguqulelwe"</string>
     <string name="open_external_dialog_request" msgid="5789329484285817629">"Nika i-<xliff:g id="APPNAME"><b>^1</b></xliff:g> ukufinyelela ekuqondiseni kwe-<xliff:g id="DIRECTORY"><i>^2</i></xliff:g> ku-<xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
+    <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Nika ukufinyelela kwe-<xliff:g id="APPNAME"><b>^1</b></xliff:g> kwinkomba ye-<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
     <string name="open_external_dialog_root_request" msgid="8899108702926347720">"Nikeza i-<xliff:g id="APPNAME"><b>^1</b></xliff:g> ukufinyelela kudatha yakho, okufaka izithombe namavidiyo, ku-<xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
     <string name="never_ask_again" msgid="4295278542972859268">"Ungaphindi ubuze"</string>
     <string name="allow" msgid="7225948811296386551">"Vumela"</string>
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index 1660e26..cf0643d 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -31,6 +31,7 @@
     <color name="accent">@*android:color/accent_material_light</color>
     <color name="accent_dark">@*android:color/accent_material_dark</color>
     <color name="action_mode">@color/material_grey_400</color>
+    <color name="status_bar_color">@*android:color/material_blue_grey_950</color>
 
     <color name="band_select_background">#88ffffff</color>
     <color name="band_select_border">#44000000</color>
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index 6590bbe..f0cab08 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -20,13 +20,15 @@
 
     <!-- Intentionally unset. Vendors should set this in an overlay. -->
     <string name="trusted_quick_viewer_package" translatable="false"></string>
+
+    <!-- overridden for RTL langs -->
     <bool name="list_divider_inset_left">true</bool>
-    <!-- Indicates if the home directory should be hidden in the roots list, that is presented
-         in the drawer/left side panel ) -->
-    <bool name="home_root_hidden">true</bool>
-    <!-- Indicates if the advanced roots like internal storage should be shown in the roots list.
-         When enabled there is no menu option to toggle internal storage visibility. -->
-    <bool name="advanced_roots_shown">false</bool>
+
+    <!-- Flags setup as productivity oriented in which case Downloads app will be presented
+             as Files app. Including showing of the Documents and "advanced" roots. -->
+    <bool name="productivity_device">false</bool>
+
     <!-- Indicates if search view is taking the whole toolbar space -->
     <bool name="full_bar_search_view">true</bool>
+
 </resources>
diff --git a/packages/DocumentsUI/res/values/dimens.xml b/packages/DocumentsUI/res/values/dimens.xml
index 5af7da3..e682994 100644
--- a/packages/DocumentsUI/res/values/dimens.xml
+++ b/packages/DocumentsUI/res/values/dimens.xml
@@ -38,4 +38,8 @@
     <dimen name="drag_shadow_size">120dp</dimen>
     <dimen name="grid_item_elevation">2dp</dimen>
     <dimen name="max_drawer_width">280dp</dimen>
+
+    <dimen name="drag_shadow_width">160dp</dimen>
+    <dimen name="drag_shadow_height">48dp</dimen>
+
 </resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index fb557ca..eb99a0d 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -18,9 +18,6 @@
     <!-- Title of the documents application [CHAR LIMIT=32] -->
     <string name="app_label">Documents</string>
 
-    <!-- Title of the standalone files activity. [CHAR LIMIT=32] -->
-    <string name="files_label">Files</string>
-
     <!-- Title of the standalone downloads activity. [CHAR LIMIT=32] -->
     <string name="downloads_label">Downloads</string>
 
@@ -223,6 +220,12 @@
         <item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item>
     </plurals>
 
+    <!-- Label text showing user how many items are being dragged. Can be one or more elements. -->
+    <plurals name="elements_dragged">
+        <item quantity="one"><xliff:g id="count" example="1">%1$d</xliff:g> item</item>
+        <item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> items</item>
+    </plurals>
+
     <!-- Dialog text shown to users when asking if they want to delete a file (a confirmation) -->
     <string name="delete_filename_confirmation_message">Delete \"<xliff:g id="name" example="cat.jpg">%1$s</xliff:g>\"?</string>
     <!-- Dialog text shown to users when asking if they want to delete a folder (a confirmation) -->
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index b0996aa..9f09ebc 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -30,6 +30,7 @@
         <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:statusBarColor">@color/status_bar_color</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 cca6473..4ee37a5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -19,10 +19,9 @@
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
 import static com.android.documentsui.State.ACTION_CREATE;
+import static com.android.documentsui.State.ACTION_GET_CONTENT;
 import static com.android.documentsui.State.ACTION_OPEN;
 import static com.android.documentsui.State.ACTION_OPEN_TREE;
-import static com.android.documentsui.State.ACTION_GET_CONTENT;
-import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION;
 import static com.android.documentsui.State.MODE_GRID;
 
 import android.app.Activity;
@@ -37,14 +36,12 @@
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.MessageQueue;
 import android.os.MessageQueue.IdleHandler;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
 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;
@@ -104,8 +101,6 @@
     @CallSuper
     @Override
     public void onCreate(Bundle icicle) {
-        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
-
         // Record the time when onCreate is invoked for metric.
         mStartTime = new Date().getTime();
 
@@ -135,7 +130,6 @@
         mSearchManager = new SearchViewManager(this, icicle);
 
         DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar);
-        Display.adjustToolbar(toolbar, this);
         setActionBar(toolbar);
         mNavigator = new NavigationView(
                 mDrawer,
@@ -220,8 +214,7 @@
         includeState(state);
 
         // Advanced roots are shown by deafult without menu option if forced by config or intent.
-        state.showAdvanced = getResources().getBoolean(R.bool.advanced_roots_shown)
-                || intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
+        state.showAdvanced = Shared.shouldShowDeviceRoot(this, intent);
         // Menu option is shown for whitelisted intents if advanced roots are not shown by default.
         state.showAdvancedOption = !state.showAdvanced &&
                 (state.action == ACTION_OPEN ||
@@ -264,6 +257,7 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
+        Metrics.logMenuAction(this, item.getItemId());
 
         switch (item.getItemId()) {
             case android.R.id.home:
@@ -469,11 +463,11 @@
      * Method can be overridden if the change of the behavior of the the child activity is needed.
      */
     public Uri getDefaultRoot() {
-        return Shared.isHomeRootHidden(this)
-                ? DocumentsContract.buildRootUri("com.android.providers.downloads.documents",
-                        "downloads")
-                : DocumentsContract.buildHomeUri();
-            }
+        return Shared.shouldShowDocumentsRoot(this, getIntent())
+                ? DocumentsContract.buildHomeUri()
+                : DocumentsContract.buildRootUri(
+                        "com.android.providers.downloads.documents", "downloads");
+    }
 
     void setDisplayAdvancedDevices(boolean display) {
         mState.showAdvanced = display;
@@ -627,10 +621,12 @@
                 return true;
             }
         } else if (keyCode == KeyEvent.KEYCODE_TAB) {
+            Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_SWITCH_FOCUS);
             // Tab toggles focus on the navigation drawer.
             toggleNavDrawerFocus();
             return true;
         } else if (keyCode == KeyEvent.KEYCODE_DEL) {
+            Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_BACK);
             popDir();
             return true;
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Display.java b/packages/DocumentsUI/src/com/android/documentsui/Display.java
index d46a3ea..8b13222 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Display.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Display.java
@@ -20,8 +20,6 @@
 import android.content.Context;
 import android.graphics.Point;
 import android.util.TypedValue;
-import android.view.WindowManager;
-import android.widget.Toolbar;
 
 /*
  * Convenience class for getting display related attributes
@@ -47,41 +45,12 @@
      * Returns action bar height in raw pixels.
      */
     public static float actionBarHeight(Context context) {
-        int height = 0;
+        int actionBarHeight = 0;
         TypedValue tv = new TypedValue();
         if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
-            height = TypedValue.complexToDimensionPixelSize(tv.data,
+            actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,
                     context.getResources().getDisplayMetrics());
         }
-        return height;
-    }
-
-    /*
-     * Returns status bar height in raw pixels.
-     */
-    private static int statusBarHeight(Context context) {
-        int height = 0;
-        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen",
-                "android");
-        if (resourceId > 0) {
-            height = context.getResources().getDimensionPixelSize(resourceId);
-        }
-        return height;
-    }
-
-    /*
-     * Adjusts toolbar for the layout with translucent status bar. Increases the
-     * height of the toolbar and adds padding at the top to accommodate status bar visible above
-     * toolbar.
-     */
-    public static void adjustToolbar(Toolbar toolbar, Activity activity) {
-        if ((activity.getWindow().getAttributes().flags
-                & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) != 0) {
-            int statusBarHeight = Display.statusBarHeight(activity);
-            toolbar.getLayoutParams().height = (int) (Display.actionBarHeight(activity)
-                    + statusBarHeight);
-            toolbar.setPadding(toolbar.getPaddingLeft(), statusBarHeight, toolbar.getPaddingRight(),
-                    toolbar.getPaddingBottom());
-        }
+        return actionBarHeight;
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 5788420..40b54d3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -203,8 +203,8 @@
                        mState.action == ACTION_PICK_COPY_DESTINATION) {
                 title = getResources().getString(R.string.title_save);
             } else {
-                // If all else fails, just call it "Downloads".
-                title = getResources().getString(R.string.downloads_label);
+                // If all else fails, just call it "Documents".
+                title = getResources().getString(R.string.app_label);
             }
         }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
index 9005442..5ea6cfa 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
@@ -69,7 +69,7 @@
         final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
 
         mRoots = new RootsCache(this);
-        mRoots.updateAsync();
+        mRoots.updateAsync(false);
 
         mThumbnails = new ThumbnailCache(memoryClassBytes / 4);
 
@@ -105,7 +105,7 @@
                 final String packageName = data.getSchemeSpecificPart();
                 mRoots.updatePackageAsync(packageName);
             } else {
-                mRoots.updateAsync();
+                mRoots.updateAsync(true);
             }
         }
     };
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
index 7a4099a..14e6b69 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -84,7 +84,7 @@
 
         View drawer = activity.findViewById(R.id.drawer_roots);
         Toolbar toolbar = (Toolbar) activity.findViewById(R.id.roots_toolbar);
-        Display.adjustToolbar(toolbar, activity);
+
         drawer.getLayoutParams().width = calculateDrawerWidth(activity);
 
         ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 68c0c2a..527eb78 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -180,7 +180,10 @@
 
     @Override
     public String getDrawerTitle() {
-        return getResources().getString(R.string.downloads_label);
+        Intent intent = getIntent();
+        return (intent != null && intent.hasExtra(Intent.EXTRA_TITLE))
+                ? intent.getStringExtra(Intent.EXTRA_TITLE)
+                : getTitle().toString();
     }
 
     @Override
@@ -212,19 +215,22 @@
             case R.id.menu_create_dir:
                 assert(canCreateDirectory());
                 showCreateDirectoryDialog();
-                return true;
+                break;
             case R.id.menu_new_window:
                 createNewWindow();
-                return true;
+                break;
             case R.id.menu_paste_from_clipboard:
                 DirectoryFragment dir = getDirectoryFragment();
                 if (dir != null) {
                     dir.pasteFromClipboard();
                 }
-                return true;
+                break;
+            default:
+                return super.onOptionsItemSelected(item);
         }
 
-        return super.onOptionsItemSelected(item);
+        Metrics.logMenuAction(this, item.getItemId());
+        return true;
     }
 
     private void createNewWindow() {
@@ -346,18 +352,21 @@
             case KeyEvent.KEYCODE_A:
                 dir = getDirectoryFragment();
                 if (dir != null) {
+                    Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_SELECT_ALL);
                     dir.selectAllFiles();
                 }
                 return true;
             case KeyEvent.KEYCODE_C:
                 dir = getDirectoryFragment();
                 if (dir != null) {
+                    Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_COPY);
                     dir.copySelectedToClipboard();
                 }
                 return true;
             case KeyEvent.KEYCODE_V:
                 dir = getDirectoryFragment();
                 if (dir != null) {
+                    Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_PASTE);
                     dir.pasteFromClipboard();
                 }
                 return true;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
index 7930c28..5cb6ca3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
@@ -87,9 +87,24 @@
         startActivity(intent);
     }
 
-    static final Intent createLaunchIntent(Context context) {
-        Intent intent = new Intent(context, FilesActivity.class);
+    static final Intent createLaunchIntent(Activity activity) {
+        Intent intent = new Intent(activity, FilesActivity.class);
         intent.setData(buildLaunchUri());
+
+        // Relay any config overrides bits present in the original intent.
+        Intent original = activity.getIntent();
+        if (original != null) {
+            if (original.hasExtra(Shared.EXTRA_PRODUCTIVITY_MODE)) {
+                intent.putExtra(
+                        Shared.EXTRA_PRODUCTIVITY_MODE,
+                        original.getBooleanExtra(Shared.EXTRA_PRODUCTIVITY_MODE, false));
+            }
+            if (original.hasExtra(Intent.EXTRA_TITLE)) {
+                intent.putExtra(
+                        Intent.EXTRA_TITLE,
+                        original.getStringExtra(Intent.EXTRA_TITLE));
+            }
+        }
         return intent;
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index f1f47c8..05cc7e6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -29,6 +29,7 @@
 import android.net.Uri;
 import android.provider.DocumentsContract;
 import android.util.Log;
+import android.view.KeyEvent;
 
 import com.android.documentsui.State.ActionType;
 import com.android.documentsui.model.DocumentInfo;
@@ -67,6 +68,10 @@
     private static final String COUNT_FILEOP_CANCELED = "docsui_fileop_canceled";
     private static final String COUNT_STARTUP_MS = "docsui_startup_ms";
     private static final String COUNT_DRAWER_OPENED = "docsui_drawer_opened";
+    private static final String COUNT_DRAG_N_DROP = "docsui_drag_n_drop";
+    private static final String COUNT_SEARCH = "docsui_search";
+    private static final String COUNT_MENU_ACTION = "docsui_menu_action";
+    private static final String COUNT_KEYBOARD_ACTION = "docsui_keyboard_action";
 
     // Indices for bucketing roots in the roots histogram. "Other" is the catch-all index for any
     // root that is not explicitly recognized by the Metrics code (see {@link
@@ -196,8 +201,71 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface MetricsOpType {}
 
-    // Codes representing different launch actions. These are used for bucketing stats in the
-    // COUNT_LAUNCH_ACTION histogram.
+    // Codes representing different provider types.  Used for sorting file operations when logging.
+    private static final int PROVIDER_INTRA = 0;
+    private static final int PROVIDER_SYSTEM = 1;
+    private static final int PROVIDER_EXTERNAL = 2;
+
+    @IntDef(flag = false, value = {
+            PROVIDER_INTRA,
+            PROVIDER_SYSTEM,
+            PROVIDER_EXTERNAL
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Provider {}
+
+
+    // Codes representing different menu actions. These are used for bucketing stats in the
+    // COUNT_MENU_ACTION histogram.
+    // Both regular toolbar menu and action mode menu operations are included.
+    // Do not change or rearrange these values, that will break historical data. Only add to the
+    // list.
+    // Do not use negative numbers or zero; clearcut only handles positive integers.
+    private static final int ACTION_MENU_OTHER = 1;
+    private static final int ACTION_MENU_GRID = 2;
+    private static final int ACTION_MENU_LIST = 3;
+    private static final int ACTION_MENU_SORT = 4;
+    private static final int ACTION_MENU_SORT_NAME = 5;
+    private static final int ACTION_MENU_SORT_DATE = 6;
+    private static final int ACTION_MENU_SORT_SIZE = 7;
+    private static final int ACTION_MENU_SEARCH = 8;
+    private static final int ACTION_MENU_SHOW_SIZE = 9;
+    private static final int ACTION_MENU_SETTINGS = 10;
+    private static final int ACTION_MENU_COPY_TO = 11;
+    private static final int ACTION_MENU_MOVE_TO = 12;
+    private static final int ACTION_MENU_DELETE = 13;
+    private static final int ACTION_MENU_RENAME = 14;
+    private static final int ACTION_MENU_CREATE_DIR = 15;
+    private static final int ACTION_MENU_SELECT_ALL = 16;
+    private static final int ACTION_MENU_SHARE = 17;
+    private static final int ACTION_MENU_OPEN = 18;
+    private static final int ACTION_MENU_ADVANCED = 19;
+
+    @IntDef(flag = false, value = {
+            ACTION_MENU_OTHER,
+            ACTION_MENU_GRID,
+            ACTION_MENU_LIST,
+            ACTION_MENU_SORT,
+            ACTION_MENU_SORT_NAME,
+            ACTION_MENU_SORT_DATE,
+            ACTION_MENU_SORT_SIZE,
+            ACTION_MENU_SHOW_SIZE,
+            ACTION_MENU_SETTINGS,
+            ACTION_MENU_COPY_TO,
+            ACTION_MENU_MOVE_TO,
+            ACTION_MENU_DELETE,
+            ACTION_MENU_RENAME,
+            ACTION_MENU_CREATE_DIR,
+            ACTION_MENU_SELECT_ALL,
+            ACTION_MENU_SHARE,
+            ACTION_MENU_OPEN,
+            ACTION_MENU_ADVANCED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface MenuAction {}
+
+    // Codes representing different menu actions. These are used for bucketing stats in the
+    // COUNT_MENU_ACTION histogram.
     // Do not change or rearrange these values, that will break historical data. Only add to the
     // list.
     // Do not use negative numbers or zero; clearcut only handles positive integers.
@@ -223,18 +291,30 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface MetricsAction {}
 
-    // Codes representing different provider types.  Used for sorting file operations when logging.
-    private static final int PROVIDER_INTRA = 0;
-    private static final int PROVIDER_SYSTEM = 1;
-    private static final int PROVIDER_EXTERNAL = 2;
+    // Codes representing different keyboard shortcut triggered actions. These are used for
+    // bucketing stats in the COUNT_KEYBOARD_ACTION histogram.
+    // Do not change or rearrange these values, that will break historical data. Only add to the
+    // list.
+    // Do not use negative numbers or zero; clearcut only handles positive integers.
+    public static final int ACTION_KEYBOARD_OTHER = 1;
+    public static final int ACTION_KEYBOARD_PASTE = 2;
+    public static final int ACTION_KEYBOARD_COPY = 3;
+    public static final int ACTION_KEYBOARD_DELETE = 4;
+    public static final int ACTION_KEYBOARD_SELECT_ALL = 5;
+    public static final int ACTION_KEYBOARD_BACK = 6;
+    public static final int ACTION_KEYBOARD_SWITCH_FOCUS = 7;
 
-    @IntDef(flag = true, value = {
-            PROVIDER_INTRA,
-            PROVIDER_SYSTEM,
-            PROVIDER_EXTERNAL
+    @IntDef(flag = false, value = {
+            ACTION_KEYBOARD_OTHER,
+            ACTION_KEYBOARD_PASTE,
+            ACTION_KEYBOARD_COPY,
+            ACTION_KEYBOARD_DELETE,
+            ACTION_KEYBOARD_SELECT_ALL,
+            ACTION_KEYBOARD_BACK,
+            ACTION_KEYBOARD_SWITCH_FOCUS
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface Provider {}
+    public @interface KeyboardAction {}
 
     // Codes representing different actions to open the drawer. They are used for bucketing stats in
     // the COUNT_DRAWER_OPENED histogram.
@@ -440,6 +520,16 @@
     }
 
     /**
+     * Logs keyboard shortcut actions. Since keyboard shortcuts have their corresponding menu items,
+     * they are identified by menu item resource id for convenience.
+     * @param context
+     * @param keyCode
+     */
+    public static void logKeyboardAction(Context context, @KeyboardAction int action) {
+        logHistogram(context, COUNT_KEYBOARD_ACTION, action);
+    }
+
+    /**
      * Logs startup time in milliseconds.
      * @param context
      * @param startupMs Startup time in milliseconds.
@@ -448,6 +538,25 @@
         logHistogram(context, COUNT_STARTUP_MS, startupMs);
     }
 
+    /**
+     * Logs a drag and drop action. Call this when the user drops the content triggering copy.
+     * operation.
+     *
+     * @param context
+     */
+    public static void logDragNDrop(Context context) {
+        logCount(context, COUNT_DRAG_N_DROP);
+    }
+
+    /**
+     * Logs a search. Call this when the search operation is finished.
+     *
+     * @param context
+     */
+    public static void logSearch(Context context) {
+        logCount(context, COUNT_SEARCH);
+    }
+
     private static void logInterProviderFileOps(
             Context context,
             String histogram,
@@ -568,6 +677,74 @@
     }
 
     /**
+     * Logs menu action that was selected by user.
+     * @param context
+     * @param id Resource id of the menu item.
+     */
+    public static void logMenuAction(Context context, int id) {
+        @MenuAction int menuAction = ACTION_MENU_OTHER;
+        switch (id) {
+            case R.id.menu_grid:
+                menuAction = ACTION_MENU_GRID;
+                break;
+            case R.id.menu_list:
+                menuAction = ACTION_MENU_LIST;
+                break;
+            case R.id.menu_sort:
+                menuAction = ACTION_MENU_SORT;
+                break;
+            case R.id.menu_sort_name:
+                menuAction = ACTION_MENU_SORT_NAME;
+                break;
+            case R.id.menu_sort_date:
+                menuAction = ACTION_MENU_SORT_DATE;
+                break;
+            case R.id.menu_sort_size:
+                menuAction = ACTION_MENU_SORT_SIZE;
+                break;
+            case R.id.menu_search:
+                menuAction = ACTION_MENU_SEARCH;
+                break;
+            case R.id.menu_file_size:
+                menuAction = ACTION_MENU_SHOW_SIZE;
+                break;
+            case R.id.menu_settings:
+                menuAction = ACTION_MENU_SETTINGS;
+                break;
+            case R.id.menu_copy_to:
+                menuAction = ACTION_MENU_COPY_TO;
+                break;
+            case R.id.menu_move_to:
+                menuAction = ACTION_MENU_MOVE_TO;
+                break;
+            case R.id.menu_delete:
+                menuAction = ACTION_MENU_DELETE;
+                break;
+            case R.id.menu_rename:
+                menuAction = ACTION_MENU_RENAME;
+                break;
+            case R.id.menu_create_dir:
+                menuAction = ACTION_MENU_CREATE_DIR;
+                break;
+            case R.id.menu_select_all:
+                menuAction = ACTION_MENU_SELECT_ALL;
+                break;
+            case R.id.menu_share:
+                menuAction = ACTION_MENU_SHARE;
+                break;
+            case R.id.menu_open:
+                menuAction = ACTION_MENU_OPEN;
+                break;
+            case R.id.menu_advanced:
+                menuAction = ACTION_MENU_ADVANCED;
+                break;
+            default:
+                break;
+        }
+        logHistogram(context, COUNT_MENU_ACTION, menuAction);
+    }
+
+    /**
      * Internal method for making a MetricsLogger.count call. Increments the given counter by 1.
      *
      * @param context
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 09fadc9..594e02f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -122,7 +122,7 @@
     /**
      * Gather roots from all known storage providers.
      */
-    public void updateAsync() {
+    public void updateAsync(boolean forceRefreshAll) {
 
         // NOTE: This method is called when the UI language changes.
         // For that reason we update our RecentsRoot to reflect
@@ -139,14 +139,15 @@
                 | Root.FLAG_SUPPORTS_CREATE));
         assert(mRecentsRoot.availableBytes == -1);
 
-        new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        new UpdateTask(forceRefreshAll, null)
+                .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
     /**
      * Gather roots from storage providers belonging to given package name.
      */
     public void updatePackageAsync(String packageName) {
-        new UpdateTask(packageName).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        new UpdateTask(false, packageName).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
     /**
@@ -223,23 +224,22 @@
     }
 
     private class UpdateTask extends AsyncTask<Void, Void, Void> {
+        private final boolean mForceRefreshAll;
         private final String mForceRefreshPackage;
 
         private final Multimap<String, RootInfo> mTaskRoots = ArrayListMultimap.create();
         private final HashSet<String> mTaskStoppedAuthorities = new HashSet<>();
 
         /**
-         * Update all roots.
+         * Create task to update roots cache.
+         *
+         * @param forceRefreshAll when true, all previously cached values for
+         *            all packages should be ignored.
+         * @param forceRefreshPackage when non-null, all previously cached
+         *            values for this specific package should be ignored.
          */
-        public UpdateTask() {
-            this(null);
-        }
-
-        /**
-         * Force update roots belonging to given package name. Other roots will
-         * be copied from cached {@link #mRoots} values.
-         */
-        public UpdateTask(String forceRefreshPackage) {
+        public UpdateTask(boolean forceRefreshAll, String forceRefreshPackage) {
+            mForceRefreshAll = forceRefreshAll;
             mForceRefreshPackage = forceRefreshPackage;
         }
 
@@ -247,14 +247,6 @@
         protected Void doInBackground(Void... params) {
             final long start = SystemClock.elapsedRealtime();
 
-            if (mForceRefreshPackage != null) {
-                // We must have previously cached values to fill in non-matching
-                // packages, so wait around for successful first load.
-                if (!waitForFirstLoad()) {
-                    return null;
-                }
-            }
-
             mTaskRoots.put(mRecentsRoot.authority, mRecentsRoot);
 
             final ContentResolver resolver = mContext.getContentResolver();
@@ -300,7 +292,8 @@
                 return;
             }
 
-            final boolean forceRefresh = Objects.equals(mForceRefreshPackage, info.packageName);
+            final boolean forceRefresh = mForceRefreshAll
+                    || Objects.equals(info.packageName, mForceRefreshPackage);
             mTaskRoots.putAll(info.authority, loadRootsForAuthority(mContext.getContentResolver(),
                     info.authority, forceRefresh));
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 5f665c0..8bbcc30 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -17,8 +17,8 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.State.ACTION_OPEN_TREE;
 
+import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
@@ -319,7 +319,8 @@
             for (final RootInfo root : roots) {
                 final RootItem item = new RootItem(root);
 
-                if (root.isHome() && Shared.isHomeRootHidden(context)) {
+                if (root.isHome() &&
+                        !Shared.shouldShowDocumentsRoot(context, ((Activity) context).getIntent())) {
                     continue;
                 } else if (root.isLibrary()) {
                     if (DEBUG) Log.d(TAG, "Adding " + root + " as library.");
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
index 11b8891..945ed34 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
@@ -185,6 +185,9 @@
         if(mFullBar) {
             Menu menu = mActionBar.getMenu();
             menu.setGroupVisible(R.id.group_hide_when_searching, false);
+        } else {
+            // If search in full-bar mode it will be logged in FilesActivity#onOptionsItemSelected
+            Metrics.logMenuAction(mActionBar.getContext(), R.id.menu_search);
         }
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 2c60d4a..1ba836a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -16,19 +16,16 @@
 
 package com.android.documentsui;
 
+import android.app.AlertDialog;
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.Configuration;
+import android.provider.DocumentsContract;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.text.format.Time;
 import android.view.WindowManager;
 
-import com.android.documentsui.State.ActionType;
-
-import static com.android.documentsui.State.ACTION_OPEN_TREE;
-
-import android.app.AlertDialog;
-
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.List;
@@ -45,10 +42,21 @@
             "com.android.documentsui.PICK_COPY_DESTINATION";
 
     /**
+     * Extra flag allowing app to be opened in productivity mode (less downloadsy).
+     * Useful developers and the likes. When set to true overrides the default
+     * config value of productivity_device.
+     */
+    public static final String EXTRA_PRODUCTIVITY_MODE = "com.android.documentsui.PRODUCTIVITY";
+
+    /**
      * Extra boolean flag for {@link ACTION_PICK_COPY_DESTINATION}, which
      * specifies if the destination directory needs to create new directory or not.
      */
     public static final String EXTRA_DIRECTORY_COPY = "com.android.documentsui.DIRECTORY_COPY";
+
+    /**
+     * Extra flag used to store the current stack so user opens in right spot.
+     */
     public static final String EXTRA_STACK = "com.android.documentsui.STACK";
 
     /**
@@ -175,10 +183,33 @@
     }
 
     /*
-     * Indicates if the home directory should be hidden in the roots list.
+     * Returns true if app is running in "productivity mode".
      */
-    public static boolean isHomeRootHidden(Context context) {
-        return context.getResources().getBoolean(R.bool.home_root_hidden);
+    public static boolean productivityMode(Context context) {
+        return context.getResources().getBoolean(R.bool.productivity_device);
     }
 
+    /*
+     * Returns true if app is running in "productivity mode".
+     */
+    private static boolean isProductivityMode(Context context, Intent intent) {
+        return intent.getBooleanExtra(
+                Shared.EXTRA_PRODUCTIVITY_MODE,
+                context.getResources().getBoolean(R.bool.productivity_device));
+    }
+
+    /*
+     * Returns true if "Documents" root should be shown.
+     */
+    public static boolean shouldShowDocumentsRoot(Context context, Intent intent) {
+        return isProductivityMode(context, intent);
+    }
+
+    /*
+     * Returns true if device root should be shown.
+     */
+    public static boolean shouldShowDeviceRoot(Context context, Intent intent) {
+        return isProductivityMode(context, intent)
+                || intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index c7d60e3..f239eb4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -123,9 +123,6 @@
     /** Instance state for every shown directory */
     public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
 
-    /** UI selection */
-    public Selection selectedDocuments = new Selection();
-
     /** Currently copying file */
     public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<>();
 
@@ -202,7 +199,6 @@
         out.writeInt(external ? 1 : 0);
         DurableUtils.writeToParcel(out, stack);
         out.writeMap(dirState);
-        out.writeParcelable(selectedDocuments, 0);
         out.writeList(selectedDocumentsForCopy);
         out.writeList(excludedAuthorities);
         out.writeInt(openableOnly ? 1 : 0);
@@ -233,7 +229,6 @@
             state.external = in.readInt() != 0;
             DurableUtils.readFromParcel(in, state.stack);
             in.readMap(state.dirState, loader);
-            state.selectedDocuments = in.readParcelable(loader);
             in.readList(state.selectedDocumentsForCopy, loader);
             in.readList(state.excludedAuthorities, loader);
             state.openableOnly = in.readInt() != 0;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 73ce0e1..1c85a8a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -40,10 +40,12 @@
 import android.database.Cursor;
 import android.graphics.Canvas;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Parcel;
 import android.os.Parcelable;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
@@ -72,8 +74,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
-import android.widget.Toolbar;
 import android.widget.TextView;
+import android.widget.Toolbar;
 
 import com.android.documentsui.BaseActivity;
 import com.android.documentsui.DirectoryLoader;
@@ -85,6 +87,7 @@
 import com.android.documentsui.Events.MotionInputEvent;
 import com.android.documentsui.Menus;
 import com.android.documentsui.MessageBar;
+import com.android.documentsui.Metrics;
 import com.android.documentsui.R;
 import com.android.documentsui.RecentsLoader;
 import com.android.documentsui.RootsCache;
@@ -105,6 +108,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
 
@@ -223,7 +227,8 @@
         mStateKey = buildStateKey(mRoot, mDocument);
         mQuery = args.getString(Shared.EXTRA_QUERY);
         mType = args.getInt(Shared.EXTRA_TYPE);
-        mSelection = args.getParcelable(Shared.EXTRA_SELECTION);
+        final Selection selection = args.getParcelable(Shared.EXTRA_SELECTION);
+        mSelection = selection != null ? selection : new Selection();
         mSearchMode = args.getBoolean(Shared.EXTRA_SEARCH_MODE);
 
         mIconHelper = new IconHelper(context, MODE_GRID);
@@ -287,14 +292,25 @@
         outState.putParcelable(Shared.EXTRA_ROOT, mRoot);
         outState.putParcelable(Shared.EXTRA_DOC, mDocument);
         outState.putString(Shared.EXTRA_QUERY, mQuery);
-        outState.putParcelable(Shared.EXTRA_SELECTION, mSelection);
-        outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode);
 
+        // Workaround. To avoid crash, write only up to 512 KB of selection.
+        // If more files are selected, then the selection will be lost.
+        final Parcel parcel = Parcel.obtain();
+        try {
+            mSelection.writeToParcel(parcel, 0);
+            if (parcel.dataSize() <= 512 * 1024) {
+                outState.putParcelable(Shared.EXTRA_SELECTION, mSelection);
+            }
+        } finally {
+            parcel.recycle();
+        }
+
+        outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode);
     }
 
     @Override
     public void onActivityResult(@RequestCode int requestCode, int resultCode, Intent data) {
-        switch(requestCode) {
+        switch (requestCode) {
             case REQUEST_COPY_DESTINATION:
                 handleCopyResult(resultCode, data);
                 break;
@@ -487,24 +503,19 @@
         @Override
         public void onSelectionChanged() {
             mSelectionManager.getSelection(mSelected);
-            TypedValue color = new TypedValue();
             if (mSelected.size() > 0) {
                 if (DEBUG) Log.d(TAG, "Maybe starting action mode.");
                 if (mActionMode == null) {
                     if (DEBUG) Log.d(TAG, "Yeah. Starting action mode.");
                     mActionMode = getActivity().startActionMode(this);
                 }
-                getActivity().getTheme().resolveAttribute(R.attr.colorActionMode, color, true);
                 updateActionMenu();
             } else {
                 if (DEBUG) Log.d(TAG, "Finishing action mode.");
                 if (mActionMode != null) {
                     mActionMode.finish();
                 }
-                getActivity().getTheme().resolveAttribute(
-                    android.R.attr.colorPrimaryDark, color, true);
             }
-            getActivity().getWindow().setStatusBarColor(color.data);
 
             if (mActionMode != null) {
                 final String title = Shared.getQuantityString(getActivity(),
@@ -594,6 +605,7 @@
 
         @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+            Metrics.logMenuAction(getContext(), item.getItemId());
 
             Selection selection = mSelectionManager.getSelection(new Selection());
 
@@ -1061,8 +1073,19 @@
     }
 
     public void selectAllFiles() {
+        // Exclude disabled files
+        List<String> enabled = new ArrayList<String>();
+        for (String id : mAdapter.getModelIds()) {
+            Cursor cursor = getModel().getItem(id);
+            String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+            int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+            if (isDocumentEnabled(docMimeType, docFlags)) {
+                enabled.add(id);
+            }
+        }
+
         // Only select things currently visible in the adapter.
-        boolean changed = mSelectionManager.setItemsSelected(mAdapter.getModelIds(), true);
+        boolean changed = mSelectionManager.setItemsSelected(enabled, true);
         if (changed) {
             updateDisplayState();
         }
@@ -1124,6 +1147,7 @@
                     if (Objects.equals(src, dst)) {
                         return false;
                     }
+                    Metrics.logDragNDrop(getContext());
                     copyFromClipData(event.getClipData(), dst);
                     return true;
             }
@@ -1214,41 +1238,68 @@
                 DocumentInfo.fromDirectoryCursor(cursor));
     }
 
-    private Drawable getDragShadowIcon(List<DocumentInfo> docs) {
-        if (docs.size() == 1) {
-            final DocumentInfo doc = docs.get(0);
-            return mIconHelper.getDocumentIcon(getActivity(), doc.authority, doc.documentId,
-                    doc.mimeType, doc.icon);
+    private static class DragShadowBuilder extends View.DragShadowBuilder {
+
+        private final Context mContext;
+        private final IconHelper mIconHelper;
+        private final LayoutInflater mInflater;
+        private final View mShadowView;
+        private final TextView mTitle;
+        private final ImageView mIcon;
+        private final int mWidth;
+        private final int mHeight;
+
+        public DragShadowBuilder(Context context, IconHelper iconHelper, List<DocumentInfo> docs) {
+            mContext = context;
+            mIconHelper = iconHelper;
+            mInflater = LayoutInflater.from(context);
+
+            mWidth = mContext.getResources().getDimensionPixelSize(R.dimen.drag_shadow_width);
+            mHeight= mContext.getResources().getDimensionPixelSize(R.dimen.drag_shadow_height);
+
+            mShadowView = mInflater.inflate(R.layout.drag_shadow_layout, null);
+            mTitle = (TextView) mShadowView.findViewById(android.R.id.title);
+            mIcon = (ImageView) mShadowView.findViewById(android.R.id.icon);
+
+            mTitle.setText(getTitle(docs));
+            mIcon.setImageDrawable(getIcon(docs));
         }
-        return getActivity().getDrawable(R.drawable.ic_doc_generic);
-    }
 
-    private class DrawableShadowBuilder extends View.DragShadowBuilder {
+        private Drawable getIcon(List<DocumentInfo> docs) {
+            if (docs.size() == 1) {
+                final DocumentInfo doc = docs.get(0);
+                return mIconHelper.getDocumentIcon(mContext, doc.authority, doc.documentId,
+                        doc.mimeType, doc.icon);
+            }
+            return mContext.getDrawable(R.drawable.ic_doc_generic);
+        }
 
-        private final Drawable mShadow;
-
-        private final int mShadowDimension;
-
-        public DrawableShadowBuilder(Drawable shadow) {
-            mShadow = shadow;
-            mShadowDimension = getResources().getDimensionPixelSize(
-                    R.dimen.drag_shadow_size);
-            mShadow.setBounds(0, 0, mShadowDimension, mShadowDimension);
+        private String getTitle(List<DocumentInfo> docs) {
+            if (docs.size() == 1) {
+                final DocumentInfo doc = docs.get(0);
+                return doc.displayName;
+            }
+            return Shared.getQuantityString(mContext, R.plurals.elements_dragged, docs.size());
         }
 
         @Override
         public void onProvideShadowMetrics(
                 Point shadowSize, Point shadowTouchPoint) {
-            shadowSize.set(mShadowDimension, mShadowDimension);
-            shadowTouchPoint.set(mShadowDimension / 2, mShadowDimension / 2);
+            shadowSize.set(mWidth, mHeight);
+            shadowTouchPoint.set(mWidth, mHeight);
         }
 
         @Override
         public void onDrawShadow(Canvas canvas) {
-            mShadow.draw(canvas);
+            Rect r = canvas.getClipBounds();
+            // Calling measure is necessary in order for all child views to get correctly laid out.
+            mShadowView.measure(
+                    View.MeasureSpec.makeMeasureSpec(r.right- r.left, View.MeasureSpec.EXACTLY),
+                    View.MeasureSpec.makeMeasureSpec(r.top- r.bottom, View.MeasureSpec.EXACTLY));
+            mShadowView.layout(r.left, r.top, r.right, r.bottom);
+            mShadowView.draw(canvas);
         }
     }
-
     /**
      * Abstract task providing support for loading documents *off*
      * the main thread. And if it isn't obvious, creating a list
@@ -1336,6 +1387,7 @@
                     // This has to be handled here instead of in a keyboard shortcut, because
                     // keyboard shortcuts all have to be modified with the 'Ctrl' key.
                     if (mSelectionManager.hasSelection()) {
+                        Metrics.logKeyboardAction(getContext(), Metrics.ACTION_KEYBOARD_DELETE);
                         deleteDocuments(mSelectionManager.getSelection());
                     }
                     // Always handle the key, even if there was nothing to delete. This is a
@@ -1398,7 +1450,7 @@
                 }
                 v.startDragAndDrop(
                         mClipper.getClipDataForDocuments(docs),
-                        new DrawableShadowBuilder(getDragShadowIcon(docs)),
+                        new DragShadowBuilder(getActivity(), mIconHelper, docs),
                         getDisplayState().stack.peek(),
                         View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ |
                                 View.DRAG_FLAG_GLOBAL_URI_WRITE
@@ -1622,6 +1674,9 @@
     @Override
     public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
         if (!isAdded()) return;
+        if (mSearchMode) {
+            Metrics.logSearch(getContext());
+        }
 
         State state = getDisplayState();
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index faa8e38..016cc9e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -148,11 +148,15 @@
             MenuItem share = menu.findItem(R.id.menu_share);
             MenuItem delete = menu.findItem(R.id.menu_delete);
             MenuItem rename = menu.findItem(R.id.menu_rename);
+            MenuItem selectAll = menu.findItem(R.id.menu_select_all);
 
             open.setVisible(true);
             share.setVisible(false);
             delete.setVisible(false);
             rename.setVisible(false);
+            selectAll.setVisible(mState.allowMultiple);
+
+            Menus.disableHiddenItems(menu);
         }
 
         @Override
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index f294919..69f0e67 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -22,8 +22,10 @@
 import android.app.DownloadManager;
 import android.app.DownloadManager.Request;
 import android.content.Context;
+import android.content.Intent;
 import android.net.Uri;
 import android.os.RemoteException;
+import android.provider.DocumentsContract;
 import android.support.test.uiautomator.Configurator;
 import android.support.test.uiautomator.UiObject;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -69,11 +71,10 @@
                 ROOT_1_ID);
 
         // Separate logic for "Documents" root, which presence depends on the config setting
-        boolean homeRootHidden = context.getResources().getBoolean(R.bool.home_root_hidden);
-        if (homeRootHidden) {
-            bots.roots.assertRootsAbsent("Documents");
-        } else {
+        if (Shared.shouldShowDocumentsRoot(context, new Intent(DocumentsContract.ACTION_BROWSE))) {
             bots.roots.assertRootsPresent("Documents");
+        } else {
+            bots.roots.assertRootsAbsent("Documents");
         }
     }
 
diff --git a/packages/Keyguard/res/drawable/ic_backspace_24dp.xml b/packages/Keyguard/res/drawable/ic_backspace_24dp.xml
index 47c8d14..1e4022e 100644
--- a/packages/Keyguard/res/drawable/ic_backspace_24dp.xml
+++ b/packages/Keyguard/res/drawable/ic_backspace_24dp.xml
@@ -15,6 +15,7 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="24dp"
+        android:autoMirrored="true"
         android:height="24dp"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
diff --git a/packages/Keyguard/res/values/attrs.xml b/packages/Keyguard/res/values/attrs.xml
index 96a5bcc..7cfe631 100644
--- a/packages/Keyguard/res/values/attrs.xml
+++ b/packages/Keyguard/res/values/attrs.xml
@@ -32,6 +32,9 @@
 
     <declare-styleable name="PasswordTextView">
         <attr name="scaledTextSize" format="integer" />
+        <attr name="android:gravity" />
+        <attr name="dotSize" format="dimension" />
+        <attr name="charPadding" format="dimension" />
     </declare-styleable>
 
     <declare-styleable name="CarrierText">
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index 454221a..2b549f1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -77,6 +77,7 @@
             case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
             case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
             case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+            case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
                 return SecurityMode.Password;
 
             case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
index ef8bb0b..2ff7e12 100644
--- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
+++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
@@ -71,6 +71,10 @@
     }
 
     public NumPadKey(Context context, AttributeSet attrs, int defStyle) {
+        this(context, attrs, defStyle, R.layout.keyguard_num_pad_key);
+    }
+
+    protected NumPadKey(Context context, AttributeSet attrs, int defStyle, int contentResource) {
         super(context, attrs, defStyle);
         setFocusable(true);
 
@@ -92,7 +96,7 @@
         mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
-        inflater.inflate(R.layout.keyguard_num_pad_key, this, true);
+        inflater.inflate(contentResource, this, true);
 
         mDigitText = (TextView) findViewById(R.id.digit_text);
         mDigitText.setText(Integer.toString(mDigit));
@@ -113,7 +117,11 @@
             }
         }
 
-        setBackground(mContext.getDrawable(R.drawable.ripple_drawable));
+        a = context.obtainStyledAttributes(attrs, android.R.styleable.View);
+        if (!a.hasValueOrEmpty(android.R.styleable.View_background)) {
+            setBackground(mContext.getDrawable(R.drawable.ripple_drawable));
+        }
+        a.recycle();
         setContentDescription(mDigitText.getText().toString());
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
index 50e7ecb..6eea81b 100644
--- a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
@@ -33,6 +33,7 @@
 import android.text.InputType;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.view.Gravity;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -81,6 +82,7 @@
      * The raw text size, will be multiplied by the scaled density when drawn
      */
     private final int mTextHeightRaw;
+    private final int mGravity;
     private ArrayList<CharState> mTextChars = new ArrayList<>();
     private String mText = "";
     private Stack<CharState> mCharPool = new Stack<>();
@@ -118,6 +120,12 @@
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PasswordTextView);
         try {
             mTextHeightRaw = a.getInt(R.styleable.PasswordTextView_scaledTextSize, 0);
+            mGravity = a.getInt(R.styleable.PasswordTextView_android_gravity, Gravity.CENTER);
+            mDotSize = a.getDimensionPixelSize(R.styleable.PasswordTextView_dotSize,
+                    getContext().getResources().getDimensionPixelSize(R.dimen.password_dot_size));
+            mCharPadding = a.getDimensionPixelSize(R.styleable.PasswordTextView_charPadding,
+                    getContext().getResources().getDimensionPixelSize(
+                            R.dimen.password_char_padding));
         } finally {
             a.recycle();
         }
@@ -125,9 +133,6 @@
         mDrawPaint.setTextAlign(Paint.Align.CENTER);
         mDrawPaint.setColor(0xffffffff);
         mDrawPaint.setTypeface(Typeface.create("sans-serif-light", 0));
-        mDotSize = getContext().getResources().getDimensionPixelSize(R.dimen.password_dot_size);
-        mCharPadding = getContext().getResources().getDimensionPixelSize(R.dimen
-                .password_char_padding);
         mShowPassword = Settings.System.getInt(mContext.getContentResolver(),
                 Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
         mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
@@ -142,11 +147,23 @@
     @Override
     protected void onDraw(Canvas canvas) {
         float totalDrawingWidth = getDrawingWidth();
-        float currentDrawPosition = getWidth() / 2 - totalDrawingWidth / 2;
+        float currentDrawPosition;
+        if ((mGravity & Gravity.START) != 0) {
+            if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                currentDrawPosition = getWidth() - getPaddingRight() - totalDrawingWidth;
+            } else {
+                currentDrawPosition = getPaddingLeft();
+            }
+        } else {
+            currentDrawPosition = getWidth() / 2 - totalDrawingWidth / 2;
+        }
         int length = mTextChars.size();
         Rect bounds = getCharBounds();
         int charHeight = (bounds.bottom - bounds.top);
-        float yPosition = getHeight() / 2;
+        float yPosition =
+                (getHeight() - getPaddingBottom() - getPaddingTop()) / 2 + getPaddingTop();
+        canvas.clipRect(getPaddingLeft(), getPaddingTop(),
+                getWidth()-getPaddingRight(), getHeight()-getPaddingBottom());
         float charLength = bounds.right - bounds.left;
         for (int i = 0; i < length; i++) {
             CharState charState = mTextChars.get(i);
diff --git a/packages/PrintServiceRecommendationService/res/values/strings.xml b/packages/PrintServiceRecommendationService/res/values/strings.xml
index 83d3800..07d0004 100644
--- a/packages/PrintServiceRecommendationService/res/values/strings.xml
+++ b/packages/PrintServiceRecommendationService/res/values/strings.xml
@@ -23,7 +23,7 @@
     <string name="plugin_vendor_brother">Brother</string>
     <string name="plugin_vendor_canon">Canon</string>
     <string name="plugin_vendor_xerox">Xerox</string>
-    <string name="plugin_vendor_samsung">Samsung Electorics</string>
+    <string name="plugin_vendor_samsung">Samsung Electronics</string>
     <string name="plugin_vendor_epson">Epson</string>
     <string name="plugin_vendor_konika_minolta">Konika Minolta</string>
     <string name="plugin_vendor_fuji">Fuji</string>
diff --git a/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml b/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
index fda2768..119943c 100644
--- a/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
+++ b/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
@@ -46,7 +46,7 @@
 
     <vendor>
         <name>@string/plugin_vendor_canon</name>
-        <package>com.xerox.printservice</package>
+        <package>jp.co.canon.android.printservice.plugin</package>
         <mdns-names>
             <mdns-name>Canon</mdns-name>
         </mdns-names>
@@ -54,7 +54,7 @@
 
     <vendor>
         <name>@string/plugin_vendor_xerox</name>
-        <package>jp.co.canon.android.printservice.plugin</package>
+        <package>com.xerox.printservice</package>
         <mdns-names>
             <mdns-name>Xerox</mdns-name>
         </mdns-names>
diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml
index a87afe0..248d0c0 100644
--- a/packages/PrintSpooler/res/layout/print_activity_controls.xml
+++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml
@@ -239,7 +239,8 @@
                     android:singleLine="true"
                     android:ellipsize="end"
                     android:visibility="visible"
-                    android:inputType="textNoSuggestions">
+                    android:inputType="number"
+                    android:digits="0123456789 ,-">
                 </com.android.printspooler.widget.CustomErrorEditText>
 
             </LinearLayout>
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index 0224c6c..fa5ec3f 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Installeer om <xliff:g id="COUNT_1">%1$s</xliff:g> drukkers te ontdek</item>
+      <item quantity="one">Installeer om <xliff:g id="COUNT_0">%1$s</xliff:g> drukker ontdek</item>
+    </plurals>
     <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 98255d4..5ada8d3 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"የሚመከሩ አገልግሎቶች"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"የተሰናከሉ አገልግሎቶች"</string>
     <string name="all_services_title" msgid="5578662754874906455">"ሁሉም አገልግሎቶች"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> አታሚዎች ለማግኘት ይጫኑ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> አታሚዎች ለማግኘት ይጫኑ</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ን በማተም ላይ"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ን በመተው ላይ"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"የአታሚ ስህተት <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index 5f0255c..1208298 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -76,6 +76,14 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"الخدمات الموصى بها"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"الخدمات المعطَّلة"</string>
     <string name="all_services_title" msgid="5578662754874906455">"جميع الخدمات"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="zero">التثبيت لاستكشاف <xliff:g id="COUNT_1">%1$s</xliff:g> طابعات</item>
+      <item quantity="two">التثبيت لاستكشاف طابعتين (<xliff:g id="COUNT_1">%1$s</xliff:g>)</item>
+      <item quantity="few">التثبيت لاستكشاف <xliff:g id="COUNT_1">%1$s</xliff:g> طابعات</item>
+      <item quantity="many">التثبيت لاستكشاف <xliff:g id="COUNT_1">%1$s</xliff:g> طابعة</item>
+      <item quantity="other">التثبيت لاستكشاف <xliff:g id="COUNT_1">%1$s</xliff:g> طابعات</item>
+      <item quantity="one">التثبيت لاستكشاف <xliff:g id="COUNT_0">%1$s</xliff:g> طابعة</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"جارٍ طباعة <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"جارٍ إلغاء <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"خطا في الطابعة <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-az-rAZ/strings.xml b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
index b5dfaf8..4404aad 100644
--- a/packages/PrintSpooler/res/values-az-rAZ/strings.xml
+++ b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> printeri kəşf etmək üçün quraşdırın</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> printeri kəşf etmək üçün quraşdırın</item>
+    </plurals>
     <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 2ac8002..50ce1f9 100644
--- a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
+++ b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
@@ -73,6 +73,11 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Instalirajte da biste otkrili <xliff:g id="COUNT_1">%1$s</xliff:g> štampač</item>
+      <item quantity="few">Instalirajte da biste otkrili <xliff:g id="COUNT_1">%1$s</xliff:g> štampača</item>
+      <item quantity="other">Instalirajte da biste otkrili <xliff:g id="COUNT_1">%1$s</xliff:g> štampača</item>
+    </plurals>
     <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-be-rBY/strings.xml b/packages/PrintSpooler/res/values-be-rBY/strings.xml
index 13d573e..c264f92 100644
--- a/packages/PrintSpooler/res/values-be-rBY/strings.xml
+++ b/packages/PrintSpooler/res/values-be-rBY/strings.xml
@@ -74,6 +74,12 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Рэкамендаваныя службы"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Адключаныя службы"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Усе службы"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Усталюйце, каб знайсці <xliff:g id="COUNT_1">%1$s</xliff:g> прынтар</item>
+      <item quantity="few">Усталюйце, каб знайсці <xliff:g id="COUNT_1">%1$s</xliff:g> прынтары</item>
+      <item quantity="many">Усталюйце, каб знайсці <xliff:g id="COUNT_1">%1$s</xliff:g> прынтараў</item>
+      <item quantity="other">Усталюйце, каб знайсці <xliff:g id="COUNT_1">%1$s</xliff:g> прынтара</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Друк <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Скасоўваецца <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Памылка друку <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index 73c51e9..3dd6ec5 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Препоръчителни услуги"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Деактивирани услуги"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Всички услуги"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Инсталирайте, за да бъдат открити <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+      <item quantity="one">Инсталирайте, за да бъде открит <xliff:g id="COUNT_0">%1$s</xliff:g> принтер</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"„<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“ се отпечатва"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"„<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“ се анулира"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка в принтера при „<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“"</string>
diff --git a/packages/PrintSpooler/res/values-bn-rBD/strings.xml b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
index 25b4660..3789f21 100644
--- a/packages/PrintSpooler/res/values-bn-rBD/strings.xml
+++ b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"প্রস্তাবিত পরিষেবাগুলি"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"অক্ষম করা পরিষেবাগুলি"</string>
     <string name="all_services_title" msgid="5578662754874906455">"সমস্ত পরিষেবা"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g>টি মুদ্রক খুঁজে পেতে ইনস্টল করুন</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g>টি মুদ্রক খুঁজে পেতে ইনস্টল করুন</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> প্রিন্ট করা হচ্ছে"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> বাতিল করা হচ্ছে"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> মুদ্রক ত্রুটি"</string>
diff --git a/packages/PrintSpooler/res/values-bs-rBA/strings.xml b/packages/PrintSpooler/res/values-bs-rBA/strings.xml
index 9a17707..c3c9bb33 100644
--- a/packages/PrintSpooler/res/values-bs-rBA/strings.xml
+++ b/packages/PrintSpooler/res/values-bs-rBA/strings.xml
@@ -73,6 +73,11 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one"> Instaliraj da pronađeš <xliff:g id="COUNT_1">%1$s</xliff:g> štampač</item>
+      <item quantity="few"> Instaliraj da pronađeš <xliff:g id="COUNT_1">%1$s</xliff:g> štampača</item>
+      <item quantity="other"> Instaliraj da pronađeš <xliff:g id="COUNT_1">%1$s</xliff:g> štampača</item>
+    </plurals>
     <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>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index a1df406..f65a63c 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Instal·la\'l per detectar <xliff:g id="COUNT_1">%1$s</xliff:g> impressores</item>
+      <item quantity="one">Instal·la\'l per detectar <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item>
+    </plurals>
     <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 55fb21b..9bfa271 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -74,6 +74,12 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="few">Instalací objevíte <xliff:g id="COUNT_1">%1$s</xliff:g> tiskárny</item>
+      <item quantity="many">Instalací objevíte <xliff:g id="COUNT_1">%1$s</xliff:g> tiskárny</item>
+      <item quantity="other">Instalací objevíte <xliff:g id="COUNT_1">%1$s</xliff:g> tiskáren</item>
+      <item quantity="one">Instalací objevíte <xliff:g id="COUNT_0">%1$s</xliff:g> tiskárnu</item>
+    </plurals>
     <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 49417bd..75a0b56 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Installer for at finde <xliff:g id="COUNT_1">%1$s</xliff:g> printer</item>
+      <item quantity="other">Installer for at finde <xliff:g id="COUNT_1">%1$s</xliff:g> printere</item>
+    </plurals>
     <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 cb7aeee..8c6181d 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Installieren, um <xliff:g id="COUNT_1">%1$s</xliff:g> Drucker zu erkennen</item>
+      <item quantity="one">Installieren, um <xliff:g id="COUNT_0">%1$s</xliff:g> Drucker zu erkennen</item>
+    </plurals>
     <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 4441ea2..31d3f83 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Προτεινόμενες υπηρεσίες"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Υπηρεσίες για άτομα με αναπηρία"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Όλες οι υπηρεσίες"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Κάντε εγκατάσταση για να ανακαλύψετε <xliff:g id="COUNT_1">%1$s</xliff:g> εκτυπωτές</item>
+      <item quantity="one">Κάντε εγκατάσταση για να ανακαλύψετε <xliff:g id="COUNT_0">%1$s</xliff:g> εκτυπωτή</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Εκτύπωση <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Ακύρωση <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Σφάλμα εκτυπωτή <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-en-rAU/strings.xml b/packages/PrintSpooler/res/values-en-rAU/strings.xml
index f8b6265..5e32ae4 100644
--- a/packages/PrintSpooler/res/values-en-rAU/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rAU/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
+      <item quantity="one">Install to discover <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+    </plurals>
     <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 f8b6265..5e32ae4 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
+      <item quantity="one">Install to discover <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+    </plurals>
     <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 f8b6265..5e32ae4 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
+      <item quantity="one">Install to discover <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+    </plurals>
     <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 8d55597..a6a9f07 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Instala para ver <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item>
+      <item quantity="one">Instala para ver <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item>
+    </plurals>
     <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 7d08a0e..4f6731d 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Instalar para descubrir <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item>
+      <item quantity="one">Instalar para descubrir <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item>
+    </plurals>
     <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-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index 09da3e0..3d0516c 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Installige <xliff:g id="COUNT_1">%1$s</xliff:g> printeri avastamiseks</item>
+      <item quantity="one">Installige <xliff:g id="COUNT_0">%1$s</xliff:g> printeri avastamiseks</item>
+    </plurals>
     <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 6b760b4..c56692f 100644
--- a/packages/PrintSpooler/res/values-eu-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-eu-rES/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Instalatu <xliff:g id="COUNT_1">%1$s</xliff:g> inprimagailu aurkitzeko</item>
+      <item quantity="one">Instalatu <xliff:g id="COUNT_0">%1$s</xliff:g> inprimagailu aurkitzeko</item>
+    </plurals>
     <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 fa105d5..8a6c0dd 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"خدمات توصیه‌شده"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"خدمات غیرفعال"</string>
     <string name="all_services_title" msgid="5578662754874906455">"همه خدمات"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">نصب کنید تا <xliff:g id="COUNT_1">%1$s</xliff:g> چاپگر را پیدا کنید</item>
+      <item quantity="other">نصب کنید تا <xliff:g id="COUNT_1">%1$s</xliff:g> چاپگر را پیدا کنید</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"در حال چاپ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"در حال لغو <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"خطای چاپگر <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index cf051f8..3d6897d 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Asentamalla voit löytää <xliff:g id="COUNT_1">%1$s</xliff:g> tulostinta.</item>
+      <item quantity="one">Asentamalla voit löytää <xliff:g id="COUNT_0">%1$s</xliff:g> tulostimen.</item>
+    </plurals>
     <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 11d2875..6c9539a 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
+      <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item>
+    </plurals>
     <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 6b89281..64add68 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
+      <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item>
+    </plurals>
     <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 7ddc9f8..099159d 100644
--- a/packages/PrintSpooler/res/values-gl-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-gl-rES/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Instala o servizo para atopar <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item>
+      <item quantity="one">Instala o servizo para atopar <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item>
+    </plurals>
     <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 6a7e0df..b42fdab 100644
--- a/packages/PrintSpooler/res/values-gu-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"ભલામણ કરેલી સેવાઓ"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"અક્ષમ કરેલી સેવાઓ"</string>
     <string name="all_services_title" msgid="5578662754874906455">"બધી સેવાઓ"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> પ્રિન્ટરની શોધ કરવા માટે ઇન્સ્ટૉલ કરો</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> પ્રિન્ટરની શોધ કરવા માટે ઇન્સ્ટૉલ કરો</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> છાપી રહ્યાં છે"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ને રદ કરી રહ્યું છે"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"પ્રિન્ટર ભૂલ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 377dc62..507754a0 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"सुझाई गई सेवाएं"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"अक्षम सेवाएं"</string>
     <string name="all_services_title" msgid="5578662754874906455">"सभी सेवाएं"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर खोजने के लिए इंस्टॉल करें</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर खोजने के लिए इंस्टॉल करें</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> प्रिंट हो रहा है"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द हो रहा है"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर त्रुटि <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 8550be4..92c97ea 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -73,6 +73,11 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Instalirajte da biste pronašli <xliff:g id="COUNT_1">%1$s</xliff:g> pisač</item>
+      <item quantity="few">Instalirajte da biste pronašli <xliff:g id="COUNT_1">%1$s</xliff:g> pisača</item>
+      <item quantity="other">Instalirajte da biste pronašli <xliff:g id="COUNT_1">%1$s</xliff:g> pisača</item>
+    </plurals>
     <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 20789a3..a2e53db 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Telepítés <xliff:g id="COUNT_1">%1$s</xliff:g> nyomtató felfedezéséhez</item>
+      <item quantity="one">Telepítés <xliff:g id="COUNT_0">%1$s</xliff:g> nyomtató felfedezéséhez</item>
+    </plurals>
     <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 8950338..e26c244 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Խորհուրդ տրվող ծառայությունները"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Կասեցված ծառայությունները"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Բոլոր ծառայությունները"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Տեղադրեք՝ <xliff:g id="COUNT_1">%1$s</xliff:g> տպիչ հայտնաբերելու համար</item>
+      <item quantity="other">Տեղադրեք՝ <xliff:g id="COUNT_1">%1$s</xliff:g> տպիչ հայտնաբերելու համար</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Տպվում է՝ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>-ը չեղարկվում է"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Տպիչի սխալ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index 9b72250..4ec0644 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Pasang untuk menemukan <xliff:g id="COUNT_1">%1$s</xliff:g> printer</item>
+      <item quantity="one">Pasang untuk menemukan <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+    </plurals>
     <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 37abb5a..e05f07f 100644
--- a/packages/PrintSpooler/res/values-is-rIS/strings.xml
+++ b/packages/PrintSpooler/res/values-is-rIS/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Settu upp til að finna <xliff:g id="COUNT_1">%1$s</xliff:g> prentara</item>
+      <item quantity="other">Settu upp til að finna <xliff:g id="COUNT_1">%1$s</xliff:g> prentara</item>
+    </plurals>
     <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 dd4a8cb..39a0a61 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Installa per rilevare <xliff:g id="COUNT_1">%1$s</xliff:g> stampanti</item>
+      <item quantity="one">Installa per rilevare <xliff:g id="COUNT_0">%1$s</xliff:g> stampante</item>
+    </plurals>
     <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 1d813bb..9aa4104 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -74,6 +74,12 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"שירותים מומלצים"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"שירותים מושבתים"</string>
     <string name="all_services_title" msgid="5578662754874906455">"כל השירותים"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="two">התקן כדי לגלות <xliff:g id="COUNT_1">%1$s</xliff:g> מדפסות</item>
+      <item quantity="many">התקן כדי לגלות <xliff:g id="COUNT_1">%1$s</xliff:g> מדפסות</item>
+      <item quantity="other">התקן כדי לגלות <xliff:g id="COUNT_1">%1$s</xliff:g> מדפסות</item>
+      <item quantity="one">התקן כדי לגלות מדפסת <xliff:g id="COUNT_0">%1$s</xliff:g></item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"מדפיס את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"מבטל את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"שגיאת מדפסת ב-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index 946052a..f97efc1 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"推奨されているサービス"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"無効になっているサービス"</string>
     <string name="all_services_title" msgid="5578662754874906455">"すべてのサービス"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> 台のプリンタを検索するにはインストールします</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> 台のプリンタを検索するにはインストールします</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>を印刷しています"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>をキャンセルしています"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"プリンタエラー: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index 94152b1..9cb8b39 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"რეკომენდებული სერვისები"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"გათიშული სერვისები"</string>
     <string name="all_services_title" msgid="5578662754874906455">"ყველა სერვისი"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">დააინსტალირეთ <xliff:g id="COUNT_1">%1$s</xliff:g> პრინტერის აღმოსაჩენად</item>
+      <item quantity="one">დააინსტალირეთ <xliff:g id="COUNT_0">%1$s</xliff:g> პრინტერის აღმოსაჩენად</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"იბეჭდება <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"მიმდინარეობს <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>-ის გაუქმება"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"ბეჭდვის შეცდომა <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
index c647dab..37b2cd3 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Ұсынылған қызметтер"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Өшірілген қызметтер"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Барлық қызметтер"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> принтерді табу үшін орнатыңыз</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> принтерді табу үшін орнатыңыз</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> басып шығарылуда"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> жұмысын тоқтатуда"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> принтер қателігі"</string>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index 330edf5..12d296d 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"សេវាកម្មដែលបានណែនាំ"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"សេវាកម្មដែលបិទដំណើរការ"</string>
     <string name="all_services_title" msgid="5578662754874906455">"សេវាកម្មទាំងអស់"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">ដំឡើងដើម្បីរកមើលម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT_1">%1$s</xliff:g></item>
+      <item quantity="one">ដំឡើងដើម្បីរកមើលម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT_0">%1$s</xliff:g></item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"កំពុង​​បោះពុម្ព <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"ការ​បោះបង់ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"កំហុស​ម៉ាស៊ីន​បោះពុម្ព <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
index f1cef86..8b1acdd 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"ಶಿಫಾರಸು ಮಾಡಲಾದ ಸೇವೆಗಳು"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾದ ಸೇವೆಗಳು"</string>
     <string name="all_services_title" msgid="5578662754874906455">"ಎಲ್ಲ ಸೇವೆಗಳು"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> ಪ್ರಿಂಟರ್‌ಗಳನ್ನು ಶೋಧಿಸಲು ಸ್ಥಾಪಿಸಿ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ಪ್ರಿಂಟರ್‌ಗಳನ್ನು ಶೋಧಿಸಲು ಸ್ಥಾಪಿಸಿ</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ಮುದ್ರಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ರದ್ದು ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"ಮುದ್ರಕ ದೋಷ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index d3cc967..e6ca240 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"권장 서비스"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"사용 중지된 서비스"</string>
     <string name="all_services_title" msgid="5578662754874906455">"모든 서비스"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g>개 프린터를 표시하려면 설치하세요.</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g>개 프린터를 표시하려면 설치하세요.</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> 인쇄 중"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> 취소 중"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"프린터 오류: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ky-rKG/strings.xml b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
index d84e5d8..ae0b05e 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Сунушталган кызматтар"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Өчүрүлгөн кызматтар"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Бардык кызматтар"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Орнотсоңуз <xliff:g id="COUNT_1">%1$s</xliff:g> принтер таап аласыз</item>
+      <item quantity="one">Орнотсоңуз <xliff:g id="COUNT_0">%1$s</xliff:g> принтер таап аласыз</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> басылууда"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> токтотулууда"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Принтерде ката кетти: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index 6a69053..2392e4a 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"ບໍລິການທີ່ແນະນຳ"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"ບໍລິການທີ່ຖືກປິດການນຳໃຊ້"</string>
     <string name="all_services_title" msgid="5578662754874906455">"ບໍລິການທັງໝົດ"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">ຕິດຕັ້ງເພື່ອຄົ້ນພົບເຄື່ອງພິມ <xliff:g id="COUNT_1">%1$s</xliff:g> ເຄື່ອງ</item>
+      <item quantity="one">ຕິດຕັ້ງເພື່ອຄົ້ນພົບເຄື່ອງພິມ <xliff:g id="COUNT_0">%1$s</xliff:g> ເຄື່ອງ</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"ກຳລັງພິມ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"ກຳລັງຍົກເລີກ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"ເຄື່ອງພິມເກີດຂໍ້ຜິດພາດ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index ddcaba7..65ccc2b 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -74,6 +74,12 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Įdiekite, kad būtų rastas <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvas</item>
+      <item quantity="few">Įdiekite, kad būtų rasti <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvai</item>
+      <item quantity="many">Įdiekite, kad būtų rasta <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvo</item>
+      <item quantity="other">Įdiekite, kad būtų rasta <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvų</item>
+    </plurals>
     <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 50ba32d..1bcfe78 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -73,6 +73,11 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="zero">Instalējiet, lai atklātu <xliff:g id="COUNT_1">%1$s</xliff:g> printerus</item>
+      <item quantity="one">Instalējiet, lai atklātu <xliff:g id="COUNT_1">%1$s</xliff:g> printeri</item>
+      <item quantity="other">Instalējiet, lai atklātu <xliff:g id="COUNT_1">%1$s</xliff:g> printerus</item>
+    </plurals>
     <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 a189042..d29566bc 100644
--- a/packages/PrintSpooler/res/values-mk-rMK/strings.xml
+++ b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Препорачани услуги"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Оневозможени услуги"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Сите услуги"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Инсталирајте за да пронајдете <xliff:g id="COUNT_1">%1$s</xliff:g> печатач</item>
+      <item quantity="other">Инсталирајте за да пронајдете <xliff:g id="COUNT_1">%1$s</xliff:g> печатачи</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> се печати"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> се откажува"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка при печатење <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ml-rIN/strings.xml b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
index 5625632..16d654c 100644
--- a/packages/PrintSpooler/res/values-ml-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"ശുപാർശ ചെയ്യപ്പെടുന്ന സേവനങ്ങൾ"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"പ്രവർത്തനരഹിതമാക്കിയ സേവനങ്ങൾ"</string>
     <string name="all_services_title" msgid="5578662754874906455">"എല്ലാ സേവനങ്ങളും"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> പ്രിന്ററുകൾ കണ്ടെത്തുന്നതിന് ഇൻസ്റ്റാൾ ചെയ്യുക</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> പ്രിന്റർ കണ്ടെത്തുന്നതിന് ഇൻസ്റ്റാൾ ചെയ്യുക</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> പ്രിന്റുചെയ്യുന്നു"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> റദ്ദാക്കുന്നു"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"പ്രിന്റർ പിശക് <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index 7797944..ded0665 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Санал болгосон үйлчилгээ"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Идэвхгүй болгосон үйлчилгээ"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Бүх үйлчилгээ"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"> <xliff:g id="COUNT_1">%1$s</xliff:g> хэвлэгч олохын тулд суулгах</item>
+      <item quantity="one"> <xliff:g id="COUNT_0">%1$s</xliff:g> хэвлэгч олохын тулд суулгах</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Хэвлэж байна <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Цуцлаж байна <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Принтерийн алдаа <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-mr-rIN/strings.xml b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
index ee09db2..5436635 100644
--- a/packages/PrintSpooler/res/values-mr-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"शिफारस केलेल्या सेवा"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"अक्षम केलल्या सेवा"</string>
     <string name="all_services_title" msgid="5578662754874906455">"सर्व सेवा"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी स्थापित करा</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी स्थापित करा</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> मुद्रण करीत आहे"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द करीत आहे"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर त्रुटी <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index 4042c71..8af5232 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Pasang untuk menemui <xliff:g id="COUNT_1">%1$s</xliff:g> pencetak</item>
+      <item quantity="one">Pasang untuk menemui <xliff:g id="COUNT_0">%1$s</xliff:g> pencetak</item>
+    </plurals>
     <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 f34ca67..9b5f46a 100644
--- a/packages/PrintSpooler/res/values-my-rMM/strings.xml
+++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"အကြံပြုထားသည့် ဝန်ဆောင်မှုများ"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"ပိတ်ထားသည့် ဝန်ဆောင်မှုများ"</string>
     <string name="all_services_title" msgid="5578662754874906455">"ဝန်ဆောင်မှုများ အားလုံး"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">ပုံနှိပ်စက် <xliff:g id="COUNT_1">%1$s</xliff:g> ခုကို ရှာဖွေရန် စနစ်ထည့်သွင်းပါ</item>
+      <item quantity="one">ပုံနှိပ်စက် <xliff:g id="COUNT_0">%1$s</xliff:g> ခုကို ရှာဖွေရန် စနစ်ထည့်သွင်းပါ</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ကို စာထုတ်နေပါသည်"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ကို ပယ်ဖျက်နေပါသည်"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"စာထုတ်စက်မှ အမှား <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index 6b74765..82282ba 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Installer for å finne <xliff:g id="COUNT_1">%1$s</xliff:g> printere</item>
+      <item quantity="one">Installer for å finne <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+    </plurals>
     <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 8e8bf15..4cf2f51 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"सिफारिस गरिएका सेवाहरू"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"असक्षम गरिएका सेवाहरू"</string>
     <string name="all_services_title" msgid="5578662754874906455">"सबै सेवाहरू"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिन्टरहरू पत्ता लगाउनका लागि स्थापना गर्नुहोस्</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> प्रिन्टर पत्ता लगाउनका लागि स्थापना गर्नुहोस्</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"प्रिन्ट गरिँदै <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"रद्द गरिँदै <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिन्टर त्रुटि <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 3c65d8a..83b9a22 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Installeren om <xliff:g id="COUNT_1">%1$s</xliff:g> printers te vinden</item>
+      <item quantity="one">Installeren om <xliff:g id="COUNT_0">%1$s</xliff:g> printer te vinden</item>
+    </plurals>
     <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 934123b..5f3366f 100644
--- a/packages/PrintSpooler/res/values-pa-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀਆਂ ਸੇਵਾਵਾਂ"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"ਅਯੋਗ ਬਣਾਈਆਂ ਗਈਆਂ ਸੇਵਾਵਾਂ"</string>
     <string name="all_services_title" msgid="5578662754874906455">"ਸਾਰੀਆਂ ਸੇਵਾਵਾਂ"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> ਪ੍ਰਿੰਟਰ ਖੋਜਣ ਲਈ ਸਥਾਪਤ ਕਰੋ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ਪ੍ਰਿੰਟਰ ਖੋਜਣ ਲਈ ਸਥਾਪਤ ਕਰੋ</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ਨੂੰ ਪ੍ਰਿੰਟ ਕਰ ਰਿਹਾ ਹੈ"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ਨੂੰ ਰੱਦ ਕਰ ਰਿਹਾ ਹੈ"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"ਪ੍ਰਿੰਟਰ ਅਸ਼ੁੱਧੀ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index 80b6070..e7fb7b6 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -74,6 +74,12 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="few">Zainstaluj, by wykryć <xliff:g id="COUNT_1">%1$s</xliff:g> drukarki</item>
+      <item quantity="many">Zainstaluj, by wykryć <xliff:g id="COUNT_1">%1$s</xliff:g> drukarek</item>
+      <item quantity="other">Zainstaluj, by wykryć <xliff:g id="COUNT_1">%1$s</xliff:g> drukarki</item>
+      <item quantity="one">Zainstaluj, by wykryć <xliff:g id="COUNT_0">%1$s</xliff:g> drukarkę</item>
+    </plurals>
     <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 4bd1161..dd8cdb2 100644
--- a/packages/PrintSpooler/res/values-pt-rBR/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+      <item quantity="other">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+    </plurals>
     <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 7660c5c..c1fe7bf 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Instale para detetar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+      <item quantity="one">Instale para detetar <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item>
+    </plurals>
     <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 4bd1161..dd8cdb2 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+      <item quantity="other">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item>
+    </plurals>
     <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 dd38c31..b326e09 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -73,6 +73,11 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="few">Instalați pentru a descoperi <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
+      <item quantity="other">Instalați pentru a descoperi <xliff:g id="COUNT_1">%1$s</xliff:g> de imprimante</item>
+      <item quantity="one">Instalați pentru a descoperi <xliff:g id="COUNT_0">%1$s</xliff:g> imprimantă</item>
+    </plurals>
     <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 6c074ed..5acadbc 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -74,6 +74,12 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Рекомендуемые службы"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Отключенные службы"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Все службы печати"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Установите, чтобы найти <xliff:g id="COUNT_1">%1$s</xliff:g> принтер</item>
+      <item quantity="few">Установите, чтобы найти <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+      <item quantity="many">Установите, чтобы найти <xliff:g id="COUNT_1">%1$s</xliff:g> принтеров</item>
+      <item quantity="other">Установите, чтобы найти <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Печать задания \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\"…"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Отмена задания <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>…"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Ошибка задания \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
diff --git a/packages/PrintSpooler/res/values-si-rLK/strings.xml b/packages/PrintSpooler/res/values-si-rLK/strings.xml
index 8278aee..db4c5fd 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"නිර්දේශිත සේවා"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"අබල කළ සේවා"</string>
     <string name="all_services_title" msgid="5578662754874906455">"සියලු සේවා"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">මුද්‍රණ යන්ත්‍ර <xliff:g id="COUNT_1">%1$s</xliff:g>ක් සොයා ගැනීමට ස්ථාපනය කරන්න</item>
+      <item quantity="other">මුද්‍රණ යන්ත්‍ර <xliff:g id="COUNT_1">%1$s</xliff:g>ක් සොයා ගැනීමට ස්ථාපනය කරන්න</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> මුද්‍රණය වේ"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"අවලංගු කෙරේ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"මුද්‍රණ දෝෂය <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 610fe99..63ee5e2 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -74,6 +74,12 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="few">Nainštalujte a objavte <xliff:g id="COUNT_1">%1$s</xliff:g> tlačiarne</item>
+      <item quantity="many">Nainštalujte a objavte <xliff:g id="COUNT_1">%1$s</xliff:g> tlačiarne</item>
+      <item quantity="other">Nainštalujte a objavte <xliff:g id="COUNT_1">%1$s</xliff:g> tlačiarní</item>
+      <item quantity="one">Nainštalujte a objavte <xliff:g id="COUNT_0">%1$s</xliff:g> tlačiareň</item>
+    </plurals>
     <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 b5124b4..f7616db 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -74,6 +74,12 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Namestite za odkrivanje <xliff:g id="COUNT_1">%1$s</xliff:g> tiskalnika</item>
+      <item quantity="two">Namestite za odkrivanje <xliff:g id="COUNT_1">%1$s</xliff:g> tiskalnikov</item>
+      <item quantity="few">Namestite za odkrivanje <xliff:g id="COUNT_1">%1$s</xliff:g> tiskalnikov</item>
+      <item quantity="other">Namestite za odkrivanje <xliff:g id="COUNT_1">%1$s</xliff:g> tiskalnikov</item>
+    </plurals>
     <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 27bbbf9..f4d2817 100644
--- a/packages/PrintSpooler/res/values-sq-rAL/strings.xml
+++ b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Instaloje për të zbuluar <xliff:g id="COUNT_1">%1$s</xliff:g> printera</item>
+      <item quantity="one">Instaloje për të zbuluar <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+    </plurals>
     <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 ea6fcb7..b285044 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -73,6 +73,11 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Препоручене услуге"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Онемогућене услуге"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Све услуге"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Инсталирајте да бисте открили <xliff:g id="COUNT_1">%1$s</xliff:g> штампач</item>
+      <item quantity="few">Инсталирајте да бисте открили <xliff:g id="COUNT_1">%1$s</xliff:g> штампача</item>
+      <item quantity="other">Инсталирајте да бисте открили <xliff:g id="COUNT_1">%1$s</xliff:g> штампача</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Штампа се <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Отказује се <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка штампача <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index c909e19..4a72800 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Installera och hitta <xliff:g id="COUNT_1">%1$s</xliff:g> skrivare</item>
+      <item quantity="one">Installera och hitta <xliff:g id="COUNT_0">%1$s</xliff:g> skrivare</item>
+    </plurals>
     <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 bd14117..34b935d 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Sakinisha ili ugundue printa <xliff:g id="COUNT_1">%1$s</xliff:g></item>
+      <item quantity="one">Sakinisha ili ugundue printa <xliff:g id="COUNT_0">%1$s</xliff:g></item>
+    </plurals>
     <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 782ebf2..22f41bf 100644
--- a/packages/PrintSpooler/res/values-ta-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"பரிந்துரைக்கப்படும் அச்சுப் பொறிகள்"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"முடக்கப்பட்ட அச்சுப் பொறிகள்"</string>
     <string name="all_services_title" msgid="5578662754874906455">"எல்லா அச்சுப் பொறிகளும்"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> பிரிண்டர்களைக் கண்டறிய, நிறுவவும்</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> பிரிண்டரைக் கண்டறிய, நிறுவவும்</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ஐ அச்சிடுகிறது"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ஐ ரத்துசெய்கிறது"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"பிரிண்டர் பிழை <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-te-rIN/strings.xml b/packages/PrintSpooler/res/values-te-rIN/strings.xml
index ca393c839..1211cfd 100644
--- a/packages/PrintSpooler/res/values-te-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-te-rIN/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"సిఫార్సు చేయబడిన సేవలు"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"నిలిపివేసిన సేవలు"</string>
     <string name="all_services_title" msgid="5578662754874906455">"అన్ని సేవలు"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ప్రింటర్‌లను కనుగొనడానికి ఇన్‌స్టాల్ చేయండి</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> ప్రింటర్‌ను కనుగొనడానికి ఇన్‌స్టాల్ చేయండి</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను ముద్రిస్తోంది"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను రద్దు చేస్తోంది"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"ప్రింటర్ లోపం <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index 92b960e..7f99288 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"บริการที่แนะนำ"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"บริการที่ปิดใช้"</string>
     <string name="all_services_title" msgid="5578662754874906455">"บริการทั้งหมด"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">ติดตั้งเพื่อค้นหาเครื่องพิมพ์ <xliff:g id="COUNT_1">%1$s</xliff:g> เครื่อง</item>
+      <item quantity="one">ติดตั้งเพื่อค้นหาเครื่องพิมพ์ <xliff:g id="COUNT_0">%1$s</xliff:g> เครื่อง</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"กำลังพิมพ์ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"กำลังยกเลิก <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"ข้อผิดพลาดเครื่องพิมพ์ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index 5a73659..7b50815 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">I-install upang tumuklas ng <xliff:g id="COUNT_1">%1$s</xliff:g> printer</item>
+      <item quantity="other">I-install upang tumuklas ng <xliff:g id="COUNT_1">%1$s</xliff:g> na printer</item>
+    </plurals>
     <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 f17bc9d..1ca722b 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> yazıcıyı keşfetmek için yükleyin</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> yazıcıyı keşfetmek için yükleyin</item>
+    </plurals>
     <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 9629ad3..8004639 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -74,6 +74,12 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Рекомендовані служби"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Вимкнені служби"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Усі служби"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Установіть, щоб знайти <xliff:g id="COUNT_1">%1$s</xliff:g> принтер</item>
+      <item quantity="few">Установіть, щоб знайти <xliff:g id="COUNT_1">%1$s</xliff:g> принтери</item>
+      <item quantity="many">Установіть, щоб знайти <xliff:g id="COUNT_1">%1$s</xliff:g> принтерів</item>
+      <item quantity="other">Установіть, щоб знайти <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" друкується"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"Завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" скасовується"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Помилка завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
diff --git a/packages/PrintSpooler/res/values-ur-rPK/strings.xml b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
index 0d01ee2..19e759cb 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"تجویز کردہ سروسز"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"غیر فعال کردہ سروسز"</string>
     <string name="all_services_title" msgid="5578662754874906455">"تمام سروسز"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> پرنٹرز دریافت کرنے کیلئے انسٹال کریں</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> پرنٹر دریافت کرنے کیلئے انسٹال کریں</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> پرنٹ کررہا ہے"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> کو منسوخ کر رہا ہے"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"پرنٹر کی خرابی <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index 1f379d9..cf87a74 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"Tavsiya etilgan xizmatlar"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"O‘chirib qo‘yilgan xizmatlar"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Barcha xizmatlar"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ta printerni topish uchun o‘rnating</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> ta printerni topish uchun o‘rnating</item>
+    </plurals>
     <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 b931557..2c1fa27 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">Cài đặt để phát hiện <xliff:g id="COUNT_1">%1$s</xliff:g> máy in</item>
+      <item quantity="one">Cài đặt để phát hiện <xliff:g id="COUNT_0">%1$s</xliff:g> máy in</item>
+    </plurals>
     <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 ffc9f85..b350051 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"推荐的服务"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"已停用的服务"</string>
     <string name="all_services_title" msgid="5578662754874906455">"所有服务"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">安装即可找到 <xliff:g id="COUNT_1">%1$s</xliff:g> 台打印机</item>
+      <item quantity="one">安装即可找到 <xliff:g id="COUNT_0">%1$s</xliff:g> 台打印机</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"正在打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"打印机在打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”时出错"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 4411a23..192b41b 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"推薦服務"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"已停用的服務"</string>
     <string name="all_services_title" msgid="5578662754874906455">"所有服務"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">安裝即可使用 <xliff:g id="COUNT_1">%1$s</xliff:g> 部印表機</item>
+      <item quantity="one">安裝即可使用 <xliff:g id="COUNT_0">%1$s</xliff:g> 部印表機</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"正在列印 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"打印機錯誤:<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 98126a7..4aa5681 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -72,6 +72,10 @@
     <string name="recommended_services_title" msgid="3799434882937956924">"建議的列印服務"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"已停用的列印服務"</string>
     <string name="all_services_title" msgid="5578662754874906455">"所有列印服務"</string>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="other">安裝即可使用 <xliff:g id="COUNT_1">%1$s</xliff:g> 個印表機</item>
+      <item quantity="one">安裝即可使用 <xliff:g id="COUNT_0">%1$s</xliff:g> 個印表機</item>
+    </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"正在列印 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"印表機發生錯誤:<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index f2b4990..121022b 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -72,6 +72,10 @@
     <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>
+    <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
+      <item quantity="one">Faka ukuze uthole amaphrinta we-<xliff:g id="COUNT_1">%1$s</xliff:g></item>
+      <item quantity="other">Faka ukuze uthole amaphrinta we-<xliff:g id="COUNT_1">%1$s</xliff:g></item>
+    </plurals>
     <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/src/com/android/printspooler/renderer/PdfManipulationService.java b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
index af4c347..0feda92 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
@@ -244,9 +244,20 @@
 
                 ranges = PageRangeUtils.normalize(ranges);
 
+                int lastPageIdx = mEditor.getPageCount() - 1;
+
                 final int rangeCount = ranges.length;
                 for (int i = rangeCount - 1; i >= 0; i--) {
                     PageRange range = ranges[i];
+
+                    // Ignore removal of pages that are outside the document
+                    if (range.getEnd() > lastPageIdx) {
+                        if (range.getStart() > lastPageIdx) {
+                            continue;
+                        }
+                        range = new PageRange(range.getStart(), lastPageIdx);
+                    }
+
                     for (int j = range.getEnd(); j >= range.getStart(); j--) {
                         mEditor.removePage(j);
                     }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index dba6a8b..e7aebdd 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -62,7 +62,6 @@
 import android.provider.DocumentsContract;
 import android.text.Editable;
 import android.text.TextUtils;
-import android.text.TextUtils.SimpleStringSplitter;
 import android.text.TextWatcher;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -117,8 +116,6 @@
 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,
@@ -165,22 +162,11 @@
     private static final int MIN_COPIES = 1;
     private static final String MIN_COPIES_STRING = String.valueOf(MIN_COPIES);
 
-    private static final Pattern PATTERN_DIGITS = Pattern.compile("[\\d]+");
-
-    private static final Pattern PATTERN_ESCAPE_SPECIAL_CHARS = Pattern.compile(
-            "(?=[]\\[+&|!(){}^\"~*?:\\\\])");
-
-    private static final Pattern PATTERN_PAGE_RANGE = Pattern.compile(
-            "[\\s]*[0-9]+[\\-]?[\\s]*[0-9]*[\\s]*?(([,])"
-                    + "[\\s]*[0-9]+[\\s]*[\\-]?[\\s]*[0-9]*[\\s]*|[\\s]*)+");
-
     private boolean mIsOptionsUiBound = false;
 
     private final PrinterAvailabilityDetector mPrinterAvailabilityDetector =
             new PrinterAvailabilityDetector();
 
-    private final SimpleStringSplitter mStringCommaSplitter = new SimpleStringSplitter(',');
-
     private final OnFocusChangeListener mSelectAllOnFocusListener = new SelectAllOnFocusListener();
 
     private PrintSpoolerProvider mSpoolerProvider;
@@ -476,7 +462,7 @@
     }
 
     private void onPrintDocumentError(String message) {
-        mProgressMessageController.cancel();
+        setState(mProgressMessageController.cancel());
         ensureErrorUiShown(null, PrintErrorFragment.ACTION_RETRY);
 
         setState(STATE_UPDATE_FAILED);
@@ -502,7 +488,7 @@
             Log.i(LOG_TAG, "onUpdateCanceled()");
         }
 
-        mProgressMessageController.cancel();
+        setState(mProgressMessageController.cancel());
         ensurePreviewUiShown();
 
         switch (mState) {
@@ -524,7 +510,7 @@
             Log.i(LOG_TAG, "onUpdateCompleted()");
         }
 
-        mProgressMessageController.cancel();
+        setState(mProgressMessageController.cancel());
         ensurePreviewUiShown();
 
         // Update the print job with the info for the written document. The page
@@ -572,7 +558,7 @@
             Log.i(LOG_TAG, "onUpdateFailed()");
         }
 
-        mProgressMessageController.cancel();
+        setState(mProgressMessageController.cancel());
         ensureErrorUiShown(error, PrintErrorFragment.ACTION_RETRY);
 
         if (mState == STATE_CREATE_FILE_FAILED
@@ -1169,6 +1155,18 @@
         doFinish();
     }
 
+    /**
+     * Update the selected pages from the text field.
+     */
+    private void updateSelectedPagesFromTextField() {
+        PageRange[] selectedPages = computeSelectedPages();
+        if (!Arrays.equals(mSelectedPages, selectedPages)) {
+            mSelectedPages = selectedPages;
+            // Update preview.
+            updatePrintPreviewController(false);
+        }
+    }
+
     private void confirmPrint() {
         setState(STATE_PRINT_CONFIRMED);
 
@@ -1178,14 +1176,10 @@
         addCurrentPrinterToHistory();
         setUserPrinted();
 
-        PageRange[] selectedPages = computeSelectedPages();
-        if (!Arrays.equals(mSelectedPages, selectedPages)) {
-            mSelectedPages = selectedPages;
-            // Update preview.
-            updatePrintPreviewController(false);
-        }
-
+        // updateSelectedPagesFromTextField migth update the preview, hence apply the preview first
         updateSelectedPagesFromPreview();
+        updateSelectedPagesFromTextField();
+
         mPrintPreviewController.closeOptions();
 
         if (canUpdateDocument()) {
@@ -1485,6 +1479,12 @@
                     cancelPrint();
                 }
             } else if (view == mMoreOptionsButton) {
+                if (mPageRangeEditText.getError() == null) {
+                    // The selected pages is only applied once the user leaves the text field. A click
+                    // on this button, does not count as leaving.
+                    updateSelectedPagesFromTextField();
+                }
+
                 if (mCurrentPrinter != null) {
                     startAdvancedPrintOptionsActivity(mCurrentPrinter);
                 }
@@ -1906,42 +1906,10 @@
         }
 
         if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
-            List<PageRange> pageRanges = new ArrayList<>();
-            mStringCommaSplitter.setString(mPageRangeEditText.getText().toString());
+            PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
+            final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
 
-            while (mStringCommaSplitter.hasNext()) {
-                String range = mStringCommaSplitter.next().trim();
-                if (TextUtils.isEmpty(range)) {
-                    continue;
-                }
-                final int dashIndex = range.indexOf('-');
-                final int fromIndex;
-                final int toIndex;
-
-                if (dashIndex > 0) {
-                    fromIndex = Integer.parseInt(range.substring(0, dashIndex).trim()) - 1;
-                    // It is possible that the dash is at the end since the input
-                    // verification can has to allow the user to keep entering if
-                    // this would lead to a valid input. So we handle this.
-                    if (dashIndex < range.length() - 1) {
-                        String fromString = range.substring(dashIndex + 1, range.length()).trim();
-                        toIndex = Integer.parseInt(fromString) - 1;
-                    } else {
-                        toIndex = fromIndex;
-                    }
-                } else {
-                    fromIndex = toIndex = Integer.parseInt(range) - 1;
-                }
-
-                PageRange pageRange = new PageRange(Math.min(fromIndex, toIndex),
-                        Math.max(fromIndex, toIndex));
-                pageRanges.add(pageRange);
-            }
-
-            PageRange[] pageRangesArray = new PageRange[pageRanges.size()];
-            pageRanges.toArray(pageRangesArray);
-
-            return PageRangeUtils.normalize(pageRangesArray);
+            return PageRangeUtils.parsePageRanges(mPageRangeEditText.getText(), pageCount);
         }
 
         return PageRange.ALL_PAGES_ARRAY;
@@ -2066,8 +2034,9 @@
             mSpoolerProvider.destroy();
         }
 
+        setState(mProgressMessageController.cancel());
+
         if (mState != STATE_INITIALIZING) {
-            mProgressMessageController.cancel();
             mPrintedDocument.finish();
             mPrintedDocument.destroy();
             mPrintPreviewController.destroy(new Runnable() {
@@ -2772,14 +2741,8 @@
                 editText.setSelection(editText.getText().length());
             }
 
-            if (view == mPageRangeEditText && !hasFocus) {
-                PageRange[] selectedPages = computeSelectedPages();
-                if (selectedPages != null && !Arrays.equals(mSelectedPages, selectedPages)) {
-                    mSelectedPages = selectedPages;
-
-                    // Update preview.
-                    updatePrintPreviewController(false);
-                }
+            if (view == mPageRangeEditText && !hasFocus && mPageRangeEditText.getError() == null) {
+                updateSelectedPagesFromTextField();
             }
         }
     }
@@ -2798,49 +2761,19 @@
         @Override
         public void afterTextChanged(Editable editable) {
             final boolean hadErrors = hasErrors();
-            String text = editable.toString();
-
-            if (TextUtils.isEmpty(text)) {
-                if (mPageRangeEditText.getError() == null) {
-                    mPageRangeEditText.setError("");
-                    updateOptionsUi();
-                }
-                return;
-            }
-
-            String escapedText = PATTERN_ESCAPE_SPECIAL_CHARS.matcher(text).replaceAll("////");
-            if (!PATTERN_PAGE_RANGE.matcher(escapedText).matches()) {
-                if (mPageRangeEditText.getError() == null) {
-                    mPageRangeEditText.setError("");
-                    updateOptionsUi();
-                }
-                return;
-            }
 
             PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
             final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
+            PageRange[] ranges = PageRangeUtils.parsePageRanges(editable, pageCount);
 
-            // The range
-            Matcher matcher = PATTERN_DIGITS.matcher(text);
-            while (matcher.find()) {
-                String numericString = text.substring(matcher.start(), matcher.end()).trim();
-                if (TextUtils.isEmpty(numericString)) {
-                    continue;
+            if (ranges.length == 0) {
+                if (mPageRangeEditText.getError() == null) {
+                    mPageRangeEditText.setError("");
+                    updateOptionsUi();
                 }
-                final int pageIndex = Integer.parseInt(numericString);
-                if (pageIndex < 1 || pageIndex > pageCount) {
-                    if (mPageRangeEditText.getError() == null) {
-                        mPageRangeEditText.setError("");
-                        updateOptionsUi();
-                    }
-                    return;
-                }
+                return;
             }
 
-            // We intentionally do not catch the case of the from page being
-            // greater than the to page. When computing the requested pages
-            // we just swap them if necessary.
-
             if (mPageRangeEditText.getError() != null) {
                 mPageRangeEditText.setError(null);
                 updateOptionsUi();
@@ -2910,29 +2843,50 @@
 
         private boolean mPosted;
 
+        /** State before run was executed */
+        private int mPreviousState = -1;
+
         public ProgressMessageController(Context context) {
             mHandler = new Handler(context.getMainLooper(), null, false);
         }
 
         public void post() {
-            if (mPosted) {
+            if (mState == STATE_UPDATE_SLOW) {
+                setState(STATE_UPDATE_SLOW);
+                ensureProgressUiShown();
+                updateOptionsUi();
+
+                return;
+            } else if (mPosted) {
                 return;
             }
+            mPreviousState = -1;
             mPosted = true;
             mHandler.postDelayed(this, PROGRESS_TIMEOUT_MILLIS);
         }
 
-        public void cancel() {
+        private int getStateAfterCancel() {
+            if (mPreviousState == -1) {
+                return mState;
+            } else {
+                return mPreviousState;
+            }
+        }
+
+        public int cancel() {
             if (!mPosted) {
-                return;
+                return getStateAfterCancel();
             }
             mPosted = false;
             mHandler.removeCallbacks(this);
+
+            return getStateAfterCancel();
         }
 
         @Override
         public void run() {
             mPosted = false;
+            mPreviousState = mState;
             setState(STATE_UPDATE_SLOW);
             ensureProgressUiShown();
             updateOptionsUi();
@@ -3081,12 +3035,10 @@
             List<PageRange> rangesToShred = new ArrayList<>();
             PageRange previousRange = null;
 
-            final int pageCount = printJob.getDocumentInfo().getPageCount();
-
             PageRange[] printedPages = printJob.getPages();
             final int rangeCount = printedPages.length;
             for (int i = 0; i < rangeCount; i++) {
-                PageRange range = PageRangeUtils.asAbsoluteRange(printedPages[i], pageCount);
+                PageRange range = printedPages[i];
 
                 if (previousRange == null) {
                     final int startPageIdx = 0;
@@ -3105,11 +3057,8 @@
                 }
 
                 if (i == rangeCount - 1) {
-                    final int startPageIdx = range.getEnd() + 1;
-                    final int endPageIdx = printJob.getDocumentInfo().getPageCount() - 1;
-                    if (startPageIdx <= endPageIdx) {
-                        PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
-                        rangesToShred.add(removedRange);
+                    if (range.getEnd() != Integer.MAX_VALUE) {
+                        rangesToShred.add(new PageRange(range.getEnd() + 1, Integer.MAX_VALUE));
                     }
                 }
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index cee16c8..fcc9f6a 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -18,12 +18,11 @@
 
 import android.app.Activity;
 import android.app.LoaderManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender.SendIntentException;
 import android.content.Loader;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.DataSetObserver;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -34,6 +33,7 @@
 import android.printservice.PrintServiceInfo;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.ContextMenu;
@@ -80,8 +80,8 @@
 
     private static final String KEY_NOT_FIRST_CREATE = "KEY_NOT_FIRST_CREATE";
 
-    /** If there are any enabled print services */
-    private boolean mHasEnabledPrintServices;
+    /** The currently enabled print services by their ComponentName */
+    private ArrayMap<ComponentName, PrintServiceInfo> mEnabledPrintServices;
 
     private PrinterRegistry mPrinterRegistry;
 
@@ -100,6 +100,8 @@
 
         setContentView(R.layout.select_printer_activity);
 
+        mEnabledPrintServices = new ArrayMap<>();
+
         mPrinterRegistry = new PrinterRegistry(this, null, LOADER_ID_PRINT_REGISTRY,
                 LOADER_ID_PRINT_REGISTRY_INT);
 
@@ -317,7 +319,7 @@
         }
         TextView titleView = (TextView) findViewById(R.id.title);
         View progressBar = findViewById(R.id.progress_bar);
-        if (!mHasEnabledPrintServices) {
+        if (mEnabledPrintServices.size() > 0) {
             titleView.setText(R.string.print_no_print_services);
             progressBar.setVisibility(View.GONE);
         } else if (adapter.getUnfilteredCount() <= 0) {
@@ -346,11 +348,16 @@
 
     @Override
     public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
-            List<PrintServiceInfo> data) {
-        if (data == null || data.isEmpty()) {
-            mHasEnabledPrintServices = false;
-        } else {
-            mHasEnabledPrintServices = true;
+            List<PrintServiceInfo> services) {
+        mEnabledPrintServices.clear();
+
+        if (services != null && !services.isEmpty()) {
+            final int numServices = services.size();
+            for (int i = 0; i < numServices; i++) {
+                PrintServiceInfo service = services.get(i);
+
+                mEnabledPrintServices.put(service.getComponentName(), service);
+            }
         }
 
         onPrintServicesUpdate();
@@ -533,14 +540,12 @@
             CharSequence title = printer.getName();
             Drawable icon = printer.loadIcon(SelectPrinterActivity.this);
 
-            CharSequence printServiceLabel;
-            try {
-                PackageInfo packageInfo = getPackageManager().getPackageInfo(
-                        printer.getId().getServiceName().getPackageName(), 0);
+            PrintServiceInfo service = mEnabledPrintServices.get(printer.getId().getServiceName());
 
-                printServiceLabel = packageInfo.applicationInfo.loadLabel(getPackageManager());
-            } catch (NameNotFoundException e) {
-                printServiceLabel = null;
+            CharSequence printServiceLabel = null;
+            if (service != null) {
+                printServiceLabel = service.getResolveInfo().loadLabel(getPackageManager())
+                        .toString();
             }
 
             CharSequence description = printer.getDescription();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java
index 2b317b3..7425c03 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java
@@ -18,7 +18,9 @@
 
 import android.print.PageRange;
 import android.print.PrintDocumentInfo;
+import android.util.Pair;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
 
@@ -155,6 +157,167 @@
     }
 
     /**
+     * Return the next position after {@code pos} that is not a space character.
+     *
+     * @param s   The string to parse
+     * @param pos The starting position
+     *
+     * @return The position of the first space character
+     */
+    private static int readWhiteSpace(CharSequence s, int pos) {
+        while (pos < s.length() && s.charAt(pos) == ' ') {
+            pos++;
+        }
+
+        return pos;
+    }
+
+    /**
+     * Read a number from a string at a certain position.
+     *
+     * @param s   The string to parse
+     * @param pos The starting position
+     *
+     * @return The position after the number + the number read or null if the number was not found
+     */
+    private static Pair<Integer, Integer> readNumber(CharSequence s, int pos) {
+        Integer result = 0;
+        while (pos < s.length() && s.charAt(pos) >= '0' && s.charAt(pos) <= '9') {
+            // Number cannot start with 0
+            if (result == 0 && s.charAt(pos) == '0') {
+                break;
+            }
+            result = result * 10 + (s.charAt(pos) - '0');
+            // Abort on overflow
+            if (result < 0) {
+                break;
+            }
+            pos++;
+        }
+
+        // 0 is not a valid page number
+        if (result == 0) {
+            return new Pair<>(pos, null);
+        } else {
+            return new Pair<>(pos, result);
+        }
+    }
+
+    /**
+     * Read a single character from a string at a certain position.
+     *
+     * @param s            The string to parse
+     * @param pos          The starting position
+     * @param expectedChar The character to read
+     *
+     * @return The position after the character + the character read or null if the character was
+     *         not found
+     */
+    private static Pair<Integer, Character> readChar(CharSequence s, int pos, char expectedChar) {
+        if (pos < s.length() && s.charAt(pos) == expectedChar) {
+            return new Pair<>(pos + 1, expectedChar);
+        } else {
+            return new Pair<>(pos, null);
+        }
+    }
+
+    /**
+     * Read a page range character from a string at a certain position.
+     *
+     * @param s             The string to parse
+     * @param pos           The starting position
+     * @param maxPageNumber The highest page number to accept.
+     *
+     * @return The position after the page range + the page range read or null if the page range was
+     *         not found
+     */
+    private static Pair<Integer, PageRange> readRange(CharSequence s, int pos, int maxPageNumber) {
+        Pair<Integer, Integer> retInt;
+        Pair<Integer, Character> retChar;
+
+        Character comma;
+        if (pos == 0) {
+            // When we reading the first range, we do not want to have a comma
+            comma = ',';
+        } else {
+            retChar = readChar(s, pos, ',');
+            pos = retChar.first;
+            comma = retChar.second;
+        }
+
+        pos = readWhiteSpace(s, pos);
+
+        retInt = readNumber(s, pos);
+        pos = retInt.first;
+        Integer start = retInt.second;
+
+        pos = readWhiteSpace(s, pos);
+
+        retChar = readChar(s, pos, '-');
+        pos = retChar.first;
+        Character separator = retChar.second;
+
+        pos = readWhiteSpace(s, pos);
+
+        retInt = readNumber(s, pos);
+        pos = retInt.first;
+        Integer end = retInt.second;
+
+        pos = readWhiteSpace(s, pos);
+
+        if (comma != null &&
+                // range, maybe unbounded
+                ((separator != null && (start != null || end != null)) ||
+                        // single page
+                        (separator == null && start != null && end == null))) {
+            if (start == null) {
+                start = 1;
+            }
+
+            if (end == null) {
+                if (separator == null) {
+                    end = start;
+                } else {
+                    end = maxPageNumber;
+                }
+            }
+
+            if (start <= end && start >= 1 && end <= maxPageNumber) {
+                return new Pair<>(pos, new PageRange(start - 1, end - 1));
+            }
+        }
+
+        return new Pair<>(pos, null);
+    }
+
+    /**
+     * Parse a string into an array of page ranges.
+     *
+     * @param s             The string to parse
+     * @param maxPageNumber The highest page number to accept.
+     *
+     * @return The parsed ranges or null if the string could not be parsed.
+     */
+    public static PageRange[] parsePageRanges(CharSequence s, int maxPageNumber) {
+        ArrayList<PageRange> ranges = new ArrayList<>();
+
+        int pos = 0;
+        while (pos < s.length()) {
+            Pair<Integer, PageRange> retRange = readRange(s, pos, maxPageNumber);
+
+            if (retRange.second == null) {
+                ranges.clear();
+                break;
+            }
+
+            ranges.add(retRange.second);
+            pos = retRange.first;
+        }
+
+        return PageRangeUtils.normalize(ranges.toArray(new PageRange[ranges.size()]));
+    }
+
+    /**
      * Offsets a the start and end of page ranges with the given value.
      *
      * @param pageRanges The page ranges to offset.
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 9cf9dc9..c44f0d0 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierdie kenmerk is eksperimenteel en kan werkverrigting beïnvloed."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ongeveer <xliff:g id="TIME">%1$s</xliff:g> oor"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – sowat <xliff:g id="TIME">%2$s</xliff:g> oor"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol op WS"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol oor USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol vanaf draadloos"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laai"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laai tans op WS"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laai tans oor USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laai tans draadloos"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Laai nie"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laai nie"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Vol"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 40e5a31..cd05135 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ይህ ባህሪ የሙከራ ነውና አፈጻጸም ላይ ተጽዕኖ ሊኖረው ይችላል።"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> ገደማ ቀርቷል"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ገደማ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> እስከሚሞላ ድረስ"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በኤሲ ላይ እስከሚሞላ ድረስ"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በዩኤስቢ ላይ እስከሚሞላ ድረስ"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በገመድ አልባ ላይ እስከሚሞላ ድረስ"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ያልታወቀ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ኃይል በመሙላት ላይ"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"በኤሲ ሃይል በመሙላት ላይ"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"በዩኤስቢ ሃይል በመሙላት ላይ"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"በገመድ አልባ ሃይል በመሙላት ላይ"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index e21b02c..b3f55eb 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"هذه الميزة تجريبية وقد تؤثر في الأداء."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"يتبقى <xliff:g id="TIME">%1$s</xliff:g> تقريبًا"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تبقى <xliff:g id="TIME">%2$s</xliff:g> تقريبًا"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال باستخدام التيار المتردد"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"‏<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال عبر USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال بالشحن اللاسلكي"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"غير معروف"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"شحن"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"جارٍ الشحن بتيار متردد"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"‏جارٍ الشحن عبر USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"جارٍ الشحن لاسلكيًا"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index ca06e664..9a099af 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya eksperimentaldır və performansa təsir edə bilər."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> dolana qədər"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC üzərindən dolana qədər"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB üzərindən dolana qədər"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> naqilsiz üzərindən dolana qədər"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Naməlum"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Enerji doldurma"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Dəyişən cərəyanda qidalanır"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB üzərindən qidalanır"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Naqilsiz qidalanır"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Doldurulmur"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Enerji doldurulmur"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Tam"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 4bd9b03..85b6ac2 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na performanse."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo oko <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni punjačem"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni preko USB-a"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni bežično"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Punjenje preko punjača"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string>
diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml
index ebb5a59..c8098ec 100644
--- a/packages/SettingsLib/res/values-be-rBY/strings.xml
+++ b/packages/SettingsLib/res/values-be-rBY/strings.xml
@@ -278,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_toast_text" msgid="5466970498308266359">"Гэты элемент больш не даступны для выбару. Паспрабуйце яшчэ раз."</string>
+    <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Гэты варыянт больш не даступны. Паспрабуйце яшчэ раз."</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>
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Гэтая функцыя з\'яўляецца эксперыментальнай і можа паўплываць на прадукцыйнасць."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Засталося прыблізна <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося прыблізна <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі ад сеткі пер. току"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі па USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўн. зарадкі бесправадным шляхам"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Невядома"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарадка"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зар. ад сеткі пер. току"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарадка па USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бесправадная зарадка"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index e0641b1..35b24bf 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Тази функция е експериментална и може да се отрази на ефективността."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Прибл. оставащо време: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – приблизително оставащо време: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане при променлив ток"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> ˜– <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане през USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно безжично зареждане"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарежда се"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зареждане при AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зареждане през USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично зареждане"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 5ca7d03..14c2c95 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -296,17 +296,26 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"এই বৈশিষ্ট্যটি পরীক্ষামূলক এবং এটি কার্য-সম্পাদনা প্রভাবিত করতে পারে।"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"প্রায় <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - আনুমানিক <xliff:g id="TIME">%2$s</xliff:g> বাকি আছে"</string>
+    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
+    <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - ACতে সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
+    <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB এর মাধ্যমে সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
+    <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> -  বেতার যোগে সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string>
+    <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"অজানা"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"চার্জ হচ্ছে"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC তে চার্জ হচ্ছে"</string>
+    <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"চার্জ হচ্ছে"</string>
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB এর মাধ্যমে চার্জ হচ্ছে"</string>
+    <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"চার্জ হচ্ছে"</string>
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"তারবিহীনভাবে চার্জ হচ্ছে"</string>
+    <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"চার্জ হচ্ছে"</string>
     <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>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index ce0f409..f9c7fcad 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna te može utjecati na performanse."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo vreme je otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja na el. napajanju"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije preko USB-a"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije bežičnim punjenjem"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Puni se"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Puni se na punjaču"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5106f5b..a070740 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -296,17 +296,26 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Aquesta funció és experimental i pot afectar el rendiment."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Temps restant aproximat: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: falten aproximadament <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g>; temps restant: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
+    <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega per CA"</string>
+    <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega per USB"</string>
+    <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega sense fil"</string>
+    <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconegut"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"S\'està carregant"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Càrrega: corr. alt."</string>
+    <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"S\'està carregant"</string>
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Càrrega per USB"</string>
+    <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"S\'està carregant"</string>
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Càrrega sense fils"</string>
+    <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"S\'està carregant"</string>
     <string name="battery_info_status_discharging" msgid="310932812698268588">"No s\'està carregant"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"No s\'està carregant"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 3d3dd6f..040c9f0 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkce je experimentální a může mít vliv na výkon."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zbývající čas: <xliff:g id="TIME">%1$s</xliff:g> (přibližně)"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá přibližně <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití ze zásuvky"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití přes USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití bezdrátově"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznámé"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjí se"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nabíjení z adaptéru"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjení přes USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrátové nabíjení"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíjí se"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíjí se"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 1f354b7..ddad673 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -296,17 +296,26 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funktion er eksperimentel og kan påvirke ydeevnen."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> tilbage"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> tilbage"</string>
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string>
+    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet"</string>
+    <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet med adapter"</string>
+    <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet med USB"</string>
+    <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet med trådløs"</string>
+    <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukendt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Oplader"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Opladning med AC"</string>
+    <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Oplader"</string>
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Opladning via USB"</string>
+    <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Oplader"</string>
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Trådløs opladning"</string>
+    <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Oplader"</string>
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Oplader ikke"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Oplader ikke"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Fuld"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 404b72b..514228f 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierbei handelt es sich um eine experimentelle Funktion. Dies kann sich auf die Leistung auswirken."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Noch ca. <xliff:g id="TIME">%1$s</xliff:g> verbleibend"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noch etwa <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – bei Stromanschluss voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – über USB voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – bei kabellosem Laden voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unbekannt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Wird aufgeladen"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laden über Netzteil"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laden über USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kabelloses Laden"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Wird nicht geladen"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wird nicht geladen"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Voll"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 52988f6..8df693a 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Αυτή η λειτουργία είναι πειραματική και ενδεχομένως να επηρεάσει τις επιδόσεις."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Απομένουν περίπου <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - απομένουν περίπου <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση με φορτιστή AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση μέσω USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη ασύρματη φόρτιση"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Άγνωστο"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Φόρτιση"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Φόρτιση με AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Φόρτιση μέσω USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ασύρματη φόρτιση"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index b2df062..466291a 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index b2df062..466291a 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index b2df062..466291a 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index dd7ee4d..9bc2cf4 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar el rendimiento."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Falta <xliff:g id="TIME">%1$s</xliff:g> aproximadamente"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: alrededor de <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga por CA"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga por USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga inalámbrica"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carga en CA"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carga con USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carga inalámbrica"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando."</string>
     <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>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 0cc6cb6..ec0cafe 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -34,7 +34,7 @@
     <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string>
     <string name="available_via_passpoint" msgid="1617440946846329613">"Disponible a través de %1$s"</string>
     <string name="wifi_connected_no_internet" msgid="3149853966840874992">"Conexión sin Internet"</string>
-    <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectada"</string>
+    <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Estableciendo conexión…"</string>
     <string name="bluetooth_connected" msgid="6038755206916626419">"Conectado"</string>
@@ -296,17 +296,26 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar al rendimiento."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Tiempo restante (aproximado): <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quedan <xliff:g id="TIME">%2$s</xliff:g> aproximadamente"</string>
+    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tiempo restante: <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería"</string>
+    <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería con CA"</string>
+    <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería por USB"</string>
+    <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería con Wi-Fi"</string>
+    <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Cargando en CA"</string>
+    <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Cargando"</string>
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Cargando por USB"</string>
+    <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Cargando"</string>
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Cargando de forma inalámbrica"</string>
+    <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Cargando"</string>
     <string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"No se está cargando"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index a275b1a..29a1aea 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"See funktsioon on katseline ja võib mõjutada toimivust."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Umbes <xliff:g id="TIME">%1$s</xliff:g> on jäänud"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – jäänud on umbes <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (vahelduvvool)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (USB)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (juhtmeta laad.)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tundmatu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laadimine"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laad. vahelduvv.-v."</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laadimine USB kaudu"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Juhtmevaba laadimine"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Ei lae"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei lae"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Täis"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index 2556224..4f55e35 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> inguru guztiz kargatu arte"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> inguru. <xliff:g id="TIME">%2$s</xliff:g> geratzen d(ir)a"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> korrontearen bidez guztiz kargatu arte"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB bidez guztiz kargatu arte"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> haririk gabe guztiz kargatu arte"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ezezaguna"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Kargatzea"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"KA bidez kargatzen"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB bidez kargatzen"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hari gabe kargatzen"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Ez da kargatzen ari"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ez da kargatzen ari"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Beteta"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 1e67182..e9d63fd 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"این قابلیت آزمایشی است و ممکن است عملکرد را تحت تأثیر قرار دهد."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> باقی مانده است"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریباً ‏<xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل با جریان متناوب"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"‏<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل از طریق USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل به‌طور بی‌سیم"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ناشناس"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"در حال شارژ شدن"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"شارژ با جریان متناوب"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"‏شارژ از طریق USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"شارژ به صورت بی‌سیم"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 3d8ac98..5531d27 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tämä ominaisuus on kokeellinen ja voi vaikuttaa suorituskykyyn."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (laturilataus)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (USB-lataus)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (WiFi-lataus)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tuntematon"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Ladataan"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laturilataus"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-lataus"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Langaton lataus"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Ei laturissa"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei laturissa"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Täynnä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 4eb3a427..df6bdc6 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut toucher les performances."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> %% – Temps restant : environ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (charge complète sur c.a. dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% par USB dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% avec chargeur sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"En charge (c.a.)"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge par USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"N\'est pas en charge"</string>
     <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>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index efb10ec..ee40b2a 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>."</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Temps restant : <xliff:g id="TIME">%2$s</xliff:g> environ"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% sur secteur dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% via USB dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"En charge sur secteur"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge via USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Pas en charge"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Débranchée"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"pleine"</string>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 3d61e21..4a0451e 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función é experimental e pode afectar ao rendemento."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Duración aproximada de <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - faltan aproximadamente <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga con CA"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga con USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga co modo sen fíos"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Descoñecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Cargando con CA"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Cargando por USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Cargando sen fíos"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Non se está cargando"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non está cargando"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 628b4be..becda28 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"આ સુવિધા પ્રાયોગિક છે અને કામગીરી પર અસર કરી શકે છે."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"અંદાજે. <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - આશરે <xliff:g id="TIME">%2$s</xliff:g> બાકી"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"સંપૂર્ણ થવામાં <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>, AC પર પૂર્ણ ચાર્જ થયાંને <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>, USB પર પૂર્ણ ચાર્જ થયાંને <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> વાયરલેસ દ્વારા પૂર્ણ થાય ત્યાં સુધી"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"અજાણ્યું"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ચાર્જ થઈ રહ્યું છે"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC પર ચાર્જિંગ"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB થી ચાર્જિંગ"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"વાયરલેસથી ચાર્જિંગ"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 047c7db..6dffdd9 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यह सुविधा प्रायोगिक है और निष्पादन को प्रभावित कर सकती है."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> शेष"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग <xliff:g id="TIME">%2$s</xliff:g> शेष"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूरी होने तक"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC पर पूरी होने तक"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB पर पूरी होने तक"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेस से पूरी होने तक"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हो रही है"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC से चार्ज हो रही"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB पर चार्ज हो रही"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस रूप से चार्ज हो रही"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index f5ad6d2..1edb015 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -296,17 +296,26 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova je značajka eksperimentalna i može utjecati na performanse."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Još <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – još približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – još <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string>
+    <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti strujnim napajanjem"</string>
+    <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti putem USB-a"</string>
+    <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti bežičnim putem"</string>
+    <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Punjenje punjačem"</string>
+    <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Punjenje"</string>
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje putem USB-a"</string>
+    <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Punjenje"</string>
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string>
+    <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Punjenje"</string>
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 7279c9c..060599c 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -296,17 +296,26 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ez egy kísérleti funkció, és hatással lehet a teljesítményre."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kb. <xliff:g id="TIME">%1$s</xliff:g> van hátra"</string>
+    <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> van hátra"</string>
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – kb. <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string>
+    <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string>
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttség eléréséig"</string>
+    <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes feltöltésig hálózatról"</string>
+    <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes feltöltésig USB-ről"</string>
+    <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig vezeték nélkül"</string>
+    <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ismeretlen"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Töltés"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Hálózati töltés"</string>
+    <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Töltés"</string>
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-s töltés"</string>
+    <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Töltés"</string>
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Nem vezetékes töltés"</string>
+    <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Töltés"</string>
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Nem tölt"</string>
     <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>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 23d83a2..63c4336 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Սա փորձնական գործառույթ է և կարող է ազդել աշխատանքի վրա:"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Մնացել է մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - մնաց մոտավորապես <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը հոսանքից"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը USB-ով"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը անլար ցանցից"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Անհայտ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Լիցքավորում"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Լիցքավորում AC-ով"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Լիցքավորում USB-ով"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Անլար լիցքավորում"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 24fd0f1..c86c768 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Fitur ini bersifat eksperimental dan dapat memengaruhi kinerja."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira tersisa <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira tersisa. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh pada AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh melalui USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh dari nirkabel"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengisi daya"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Mengisi daya pada AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Isi daya lewat USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Isi daya nirkabel"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengisi daya"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengisi daya"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index e22dbe0..1fc0dc0 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Þessi eiginleiki er á tilraunastigi og getur haft áhrif á frammistöðu."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Um það bil <xliff:g id="TIME">%1$s</xliff:g> eftir"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – u.þ.b. <xliff:g id="TIME">%2$s</xliff:g> eftir"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu með hleðslutæki"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu í gegnum USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu þráðlaust"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Óþekkt"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Í hleðslu"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Hleðslutæki tengt"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Hleður um USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hleður þráðlaust"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Ekki í hleðslu"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ekki í hleðslu"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Fullhlaðin"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 84ff78a..78cd29b 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Circa <xliff:g id="TIME">%1$s</xliff:g> rimanenti"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Tempo rimanente: <xliff:g id="TIME">%2$s</xliff:g> circa"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa tramite CA"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa tramite USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lla carica completa con wireless"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Sconosciuta"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"In carica"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"In carica tramite CA"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"In carica tramite USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"In carica, wireless"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Non in carica"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non in carica"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Carica"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 74ea372..16e0f44 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"תכונה זו היא ניסיונית ועשויה להשפיע על הביצועים."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"נשארו <xliff:g id="TIME">%1$s</xliff:g> בערך"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="TIME">%2$s</xliff:g> בקירוב עד לסיום"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>‏ - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> ‏- <xliff:g id="TIME">%2$s</xliff:g> עד למילוי"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> ‏- <xliff:g id="TIME">%2$s</xliff:g> עד למילוי בזרם חילופין"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"‏<xliff:g id="LEVEL">%1$s</xliff:g> ‏- <xliff:g id="TIME">%2$s</xliff:g> עד למילוי ב-USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> ‏- <xliff:g id="TIME">%2$s</xliff:g> עד למילוי בטעינה אלחוטית"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"לא ידוע"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"טוען"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"טוען בזרם חילופין"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"‏טוען ב-USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"טוען באופן אלחוטי"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 2556d99..ce405df 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"この機能は試験運用機能であり、パフォーマンスに影響することがあります。"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"あと約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 残り約<xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(AC)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(USB)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(ワイヤレス)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ACで充電しています"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USBで充電しています"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"無線で充電しています"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"充電していません"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"充電していません"</string>
     <!-- String.format failed for translation -->
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 29e9459..20a1d2a 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ეს ფუნქცია საცდელია და შეიძლება გავლენა იქონიოს შესრულებაზე."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"დარჩენილია დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"დაახლ. <xliff:g id="LEVEL">%1$s</xliff:g> დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> სრულ დატენვამდე"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ელკვებით სრულ დატენვამდე"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB-თი სრულ დატენვამდე"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> უსადენოდან სრულ დატენვამდე"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"უცნობი"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"იტენება"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"დატენვა ელკვებაზე"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"დატენვა USB-ზე"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"დატენვა უსადენოდ"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index fdd3f95..e71c8d0 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бұл мүмкіндік эксперименттік болып табылады және өнімділікке әсер етуі мүмкін."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - айнымалы токпен толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB арқылы толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - сымсыз толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгісіз"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядталуда"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Айнымалы токпен зар."</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB арқылы зарядтау"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Сымсыз зарядтау"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 2cafa29..687b71b 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"លក្ខណៈ​នេះ​គឺ​ជា​ការ​ពិសោធន៍ ហើយ​អាច​ប៉ះពាល់​ការ​អនុវត្ត។"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"បដិសេធ​ដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"នៅសល់ប្រហែល <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅ​សល់​ប្រហែល <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូត​ដល់​ពេញ"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូត​ដល់ពេញ​រចន្ត​ឆ្លាស់"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូត​ដល់​ពេញ​តាមយូអេសប៊ី"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូត​ដល់​ពេញ​ពី​ឥតខ្សែ"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"មិន​ស្គាល់"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"កំពុងបញ្ចូល​ថ្ម"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"បញ្ចូលថ្មតាម AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"បញ្ចូលថ្មតាមយូអេសប៊ី"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"បញ្ចូលថ្មដោយ​​ឥតខ្សែ"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 6d13b35..713d9b3 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ಇದು ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ. ಕಾರ್ಯಕ್ಷಮತೆ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"ಸುಮಾರು <xliff:g id="TIME">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"ಸುಮಾರು <xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> ಉಳಿದಿದೆ"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ನಲ್ಲಿ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ಮೂಲಕ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ವೈರ್‌‌ಲೆಸ್‌ನಿಂದ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ಅಜ್ಞಾತ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ನಲ್ಲಿ ಚಾರ್ಜ್‌"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ಮೂಲಕ ಚಾರ್ಜ್‌"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ನಿಸ್ತಂತುವಾಗಿ ಚಾರ್ಜ್‌"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 035793e..348141e 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"실험실 기능이며 성능에 영향을 줄 수 있습니다."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"약 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 대략 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(AC 전원)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(USB)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(무선)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"알 수 없음"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"충전 중"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"충전 중(AC 전원)"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"충전 중(USB)"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"충전 중(무선)"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 8c43312..2016f04 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бул сынамык мүмкүнчүлүк болгондуктан, иштин майнаптуулугуна таасир этиши мүмкүн."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Болжол менен <xliff:g id="TIME">%1$s</xliff:g> калды"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - болжол менен <xliff:g id="TIME">%2$s</xliff:g> саат калды"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> толгончо"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC аркылуу толгончо"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB аркылуу толгончо"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> зымсыз кубаттоо аркылуу толгончо"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгисиз"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Кубатталууда"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ӨА кубатталууда"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB\'ден кубатталууда"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Зымсыз кубатталууда"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index f158d44..7e6db5e 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"​ຄຸນ​ສົມ​ບັດ​ນີ້​ກຳ​ລັງ​ຢູ່​ໃນ​ການ​ທົດ​ລອງ​ແລະ​ອາດ​ມີ​ຜົນ​ຕໍ່​ປະ​ສິດ​ທິ​ພາບ."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"ຍັງເຫຼືອປະມານ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ​ເຫຼືອປະ​ມານ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງ​ຈະ​ເຕັມ"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ​ຈຶ່ງ​ຈະ​ເຕັມ​ໂດຍສາກ​ດ້ວຍ​ໄຟ AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງ​ຈະ​ເຕັມ​ໂດຍສາກ​ດ້ວຍ USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ​ຈຶ່ງ​ຈະ​ເຕັມ​ໂດຍ​ສາກ​ແບບ​ໄຮ້​ສາຍ"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ບໍ່ຮູ້ຈັກ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ກຳລັງສາກໄຟ"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ກຳ​​ລັງ​ສາກ​ຜ່ານ​ໝໍ້​ໄຟ"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"ກຳ​ລັງ​ສາກ​ຜ່ານ USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ກຳ​ລັງ​ສາກ​ໄຮ້​ສາຍ"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index d5cea8e..d49876e 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ši funkcija yra eksperimentinė ir ji gali turėti įtakos našumui."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo naud. kint. sr."</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo naudojant USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo belaid. ryš."</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nežinomas"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Kraunasi..."</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Įkr. naud. kint. sr."</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Įkraunama naud. USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Įkraunama be laidų"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Nekraunama"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nekraunama"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Visiškai įkrautas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index ea6f4f9..6cd9cfd5 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Šī funkcija ir eksperimentāla un var ietekmēt veiktspēju."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> — aptuvenais atlikušais laiks: <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai maiņstrāvas uzlādei"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai USB uzlādei"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai bezvadu uzlādei"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nezināms"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Uzlāde"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Maiņstrāvas uzlāde"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB uzlāde"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezvadu uzlāde"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Nenotiek uzlāde"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenotiek uzlāde"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Pilns"</string>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index e954cdf..f8f65ec 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Функцијата е експериментална и може да влијае на изведбата."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Преостанаа прибл. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостанува приближно <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна на AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна преку USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна, безжично"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Се полни"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Полнење на струја"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Полнење преку УСБ"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично полнење"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index a4b3877..7350b7f 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ഈ ഫീച്ചർ പരീക്ഷണാത്മകമായതിനാൽ പ്രകടനത്തെ ബാധിച്ചേക്കാം."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - AC-യിൽ പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB വഴി പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - വയർലെസ് വഴി പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"അജ്ഞാതം"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ചാർജ്ജുചെയ്യുന്നു"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC-യിൽ ചാർജ്ജുചെയ്യുന്നു"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-യിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"വയർലെസ്സ് കണക്ഷനിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index d989ef8..7eeae06 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Энэ функц туршилтынх бөгөөд ажиллагаанд нөлөөлж болзошгүй."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ойролцоогоор <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"АС-р дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"USB-р дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"утасгүй цэнэглэгчээр дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Тодорхойгүй"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Цэнэглэж байна"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC-р цэнэглэж байна"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-р цэнэглэж байна"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Кабльгүйгээр цэнэглэж байна"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index d363874..0521ba1 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"हे वैशिष्‍ट्य प्रायोगिक आहे आणि कदाचित कार्यप्रदर्शन प्रभावित करू शकते."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"अंदाजे. <xliff:g id="TIME">%1$s</xliff:g> शिल्लक"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - अंदाजे. <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण होण्यात"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC वरून पूर्ण होण्यात"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB वरून पूर्ण होण्यात"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेसवरून पूर्ण होण्यात"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज होत आहे"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC वर चार्ज करीत आहे"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB वरून चार्ज करीत आहे"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस वरून चार्ज करीत आहे"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index ea79a46..a8be0e5 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ciri ini adalah percubaan dan boleh menjejaskan prestasi."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira. <xliff:g id="TIME">%2$s</xliff:g> yang tinggal"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh di AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh melalui USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh dari wayarles"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengecas"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Mengecas pada AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Mengecas melalui USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Mengecas tanpa wayar"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengecas"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengecas"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 74e0f29..220deff 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ဒီအင်္ဂါရပ်မှာ စမ်းသပ်မှု ဖြစ်၍ လုပ်ကိုင်မှုကို အကျိုးသက်ရောက်နိုင်သည်။"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"ခန့်မှန်းခြေ <xliff:g id="TIME">%1$s</xliff:g> ကျန်ပါသည်"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ခန့်မှန်းခြေ။ <xliff:g id="TIME">%2$s</xliff:g> ကျန်ရှိနေ"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> အပြည့်အထိ"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> လျှပ်စစ်ဖြင့် အပြည့်အထိ"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ဖြင့် အပြည့်အထိ"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ကြိုးမဲ့ဖြင့် အပြည့်အထိ"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"အကြောင်းအရာ မသိရှိ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"အားသွင်းနေပါသည်"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"လျှပ်စစ်ဖြင့် အားသွင်းနေ"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USBဖြင့် အားသွင်းနေ"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ကြိုးမဲ့ အားသွင်းနေ"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 1a0b468..a1407ac 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funksjonen er eksperimentell og kan påvirke ytelsen."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> igjen"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> –  fulladet om <xliff:g id="TIME">%2$s</xliff:g> med vekselstrøm"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> via USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> via trådløs lading"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukjent"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Lader"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Lader via strømuttak"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Lader via USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Lader trådløst"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Lader ikke"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Lader ikke"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index a001cab..83e2e74 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यो सुविधा प्रयोगात्मक छ र प्रदर्शनमा असर गर्न सक्छ।"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> बाँकी छ"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग। <xliff:g id="TIME">%2$s</xliff:g> बायाँ"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण नभए सम्म"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC मा पूर्ण नभए सम्म"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB मा पूर्ण नभए सम्म"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेसबाट पूर्ण नभए सम्म"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हुँदै"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC मा चार्ज गर्दै"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB मा चार्ज गर्दै"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"बिना तार चार्ज गर्दै"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 301e327..55017d8 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Deze functie is experimenteel en kan invloed hebben op de prestaties."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> resterend"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ca. <xliff:g id="TIME">%2$s</xliff:g> resterend"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via wisselstroom"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via draadloos"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Opladen"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Opladen via netvoeding"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Opladen via USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Draadloos opladen"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Wordt niet opgeladen"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wordt niet opgeladen"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Volledig"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index c792ec9..eb1eaac 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਾਤਮਿਕ ਹੈ ਅਤੇ ਪ੍ਰਦਰਸ਼ਨ ਤੇ ਅਸਰ ਪਾ ਸਕਦੀ ਹੈ।"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਪੂਰੀ ਹੋਣ ਤੱਕ"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਵਾਇਰਲੈਸ ਤੋਂ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ਅਗਿਆਤ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ਚਾਰਜਿੰਗ"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ਤੇ ਚਾਰਜਿੰਗ"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ਤੇ ਚਾਰਜਿੰਗ"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ਵਾਇਰਲੈਸ ਤੌਰ ਤੇ ਚਾਰਜਿੰਗ"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 8aad98b1..1e56cfd 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To jest funkcja eksperymentalna i może wpływać na działanie urządzenia."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Pozostało około <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostało ok. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania z gniazdka"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania przez USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania bezprzewodowo"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Nieznane"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Ładowanie"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Ładowanie zasilaczem"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Ładowanie przez USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ład. bezprzewodowe"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Nie podłączony"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nie podłączony"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Naładowana"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index c05458b..93f333a 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir em CA"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir via USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir sem fio"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carregamento CA"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 402bc86..dda00fe 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta funcionalidade é experimental e pode afetar o desempenho."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Resta(m) aproximadamente <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – resta(m) aprox. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa através de CA"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa através de USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até ficar compl. por rede s/ fios"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"A carregar"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"A carregar por CA"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"A carregar por USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"A carregar sem fios"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Não está a carregar"</string>
     <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>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index c05458b..93f333a 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir em CA"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir via USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir sem fio"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carregamento CA"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index d5e0769..3c46d41 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Această funcție este experimentală și poate afecta performanțele."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Timp rămas: aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – timp rămas: aproximativ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă la c.a."</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă prin USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă wireless"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Necunoscut"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Încarcă"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Se încarcă la C.A."</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Se încarcă prin USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Se încarcă fără fir"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Nu se încarcă"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nu încarcă"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Complet"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 7ad9f16..f4929de 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Это экспериментальная функция, она может снизить производительность устройства."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Осталось примерно <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – осталось около <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (от сети)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (через USB)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (беспроводная)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Идет зарядка"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зарядка от сети"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарядка через USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Беспроводная зарядка"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index 4c73219..99f018b 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"මෙම විශේෂාංගය පරීක්ෂණාත්මක සහ ඇතැම් විට ක්‍රියාකාරිත්වයට බලපෑ හැක."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"දළ වශයෙන් <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරිය"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආසන්න <xliff:g id="TIME">%2$s</xliff:g> වම"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"AC හි <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"USB හරහ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"රේඩියෝව වෙතින් <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පූර්ණ වන තෙක්"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"නොදනී"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ආරෝපණය වෙමින්"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC හි ආරෝපණය වෙමින්"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB හරහා ආරෝපණය වෙමින්"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"රැහැන් රහිතව ආරෝපණය වෙමින්"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index e5c9805..4dffdef 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkcia je experimentálna a môže mať vplyv na výkonnosť."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zostáva cca. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva približne <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia zo zásuvky"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia cez USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia bezdrôtovo"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznáme"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjanie"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nabíjanie zo zásuvky"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjanie cez USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrôtové nabíjanie"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíja sa"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíja sa"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 8257e3c..676a3ab 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To je preskusna funkcija in lahko vpliva na učinkovitost delovanja."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Še približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek napajalnika"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek USB-ja"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek brezž. pol."</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznano"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Polnjenje"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Polnj. prek iz. toka"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Polnj. prek USB-ja"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Brezžično polnjenje"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Se ne polni"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Se ne polni"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Poln"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 4a67348..c18e639 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ky funksion është eksperimental dhe mund të ndikojë në veprimtari."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Afërsisht <xliff:g id="TIME">%1$s</xliff:g> të mbetura"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - afërsisht <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të jetë e plotë"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet në AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet me USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet nga lidhja pa tel"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"I panjohur"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Po ngarkohet"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Po ngarkohet në AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Po ngarkohet me USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Po ngarkohet me valë"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Nuk po ngarkohet"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nuk po ngarkohet"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"E mbushur"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index eaf7ac5..c0791fc 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ова функција је експериментална и може да утиче на перформансе."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Још отприлике <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостало око <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни пуњачем"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни преко USB-а"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни бежично"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Пуњење"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Пуњење преко пуњача"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Пуњење преко USB-а"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бежично пуњење"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index b019672..60c42a5 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Den här funktionen är experimentell och kan påverka prestandan."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca <xliff:g id="TIME">%1$s</xliff:g> kvar"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca <xliff:g id="TIME">%2$s</xliff:g> kvar"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via laddare"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via trådlös laddning"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Okänd"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Laddar"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laddas via adapter"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laddas via USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laddas trådlöst"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Laddar inte"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laddar inte"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 3daa90f..5de7686 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Kipengele hiki ni cha majaribio na huenda kikaathiri utendaji."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zimesalia takribani <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia takriban <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa kutumia AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>%% - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa kutumia USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa isiyotumia waya"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Haijulikani"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Inachaji"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Inachaji kupitia AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Inachaji kupitia USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Inachaji bila kutumia waya"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Haichaji"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Haichaji"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Imejaa"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 574d105..a5f04d0 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"இது சோதனை முறையிலான அம்சம், இது செயல்திறனைப் பாதிக்கலாம்."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"தோராயமாக <xliff:g id="TIME">%1$s</xliff:g> உள்ளது"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"தோராயம்: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> உள்ளது"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"முழு சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"முழு AC சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"முழு USB சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"முழு வயர்லெஸ் சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"அறியப்படாத"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"சார்ஜ் ஏற்றப்படுகிறது"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC மூலம் சார்ஜாகிறது"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB மூலம் சார்ஜாகிறது"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"வயர்லெஸில் சார்ஜாகிறது"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 2389112..fe40766 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"సుమారు <xliff:g id="TIME">%1$s</xliff:g> మిగిలి ఉంది"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - సుమారు <xliff:g id="TIME">%2$s</xliff:g> మిగిలి ఉంది"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - ACలో పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB ద్వారా పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - వైర్‌లెస్ నుండి పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"తెలియదు"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"ఛార్జ్ అవుతోంది"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ACలో ఛార్జ్ అవుతోంది"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ద్వారా ఛార్జ్ అవుతోంది"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"వైర్‌లెస్‌ ద్వారా ఛార్జ్ అవుతోంది"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 0f6f78c..c58692f 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"คุณลักษณะนี้เป็นแบบทดลองและอาจส่งผลต่อประสิทธิภาพการทำงาน"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"เหลืออีกประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลือประมาณ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็ม"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่าน AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่าน USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่านระบบไร้สาย"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"ไม่ทราบ"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"กำลังชาร์จ"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"กำลังชาร์จไฟ AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"กำลังชาร์จผ่าน USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"กำลังชาร์จแบบไร้สาย"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index ef3dde7..093256c 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ang feature na ito ay pinag-eeksperimentuhan at maaaring makaapekto sa pagganap."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> na lang ang natitira"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - humigit kumulang <xliff:g id="TIME">%2$s</xliff:g> ang natitira"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno sa AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno sa USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno mula sa wireless"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Hindi Kilala"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Nagcha-charge"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nagcha-charge sa AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nagcha-charge sa USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Wireless nag-charge"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Hindi nagcha-charge"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Hindi nagkakarga"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 4b7490d..1947d39 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu özellik deneyseldir ve performansı etkileyebilir."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - prize takılı, tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB üzerinden şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - kablosuzdan tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Bilinmiyor"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Şarj oluyor"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ile şarj oluyor"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ile şarj oluyor"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kablosuz şarj oluyor"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Şarj olmuyor"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Şarj etmiyor"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Dolu"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 5e044c3..0ed6cc0 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Це експериментальна функція. Вона може вплинути на продуктивність."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Залишилося приблизно <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – залишилось близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження з розетки"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження через USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного з бездротового зарядження"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Невідомо"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядж-ся"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Заряджання з розетки"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Заряджання через USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Заряджання без дроту"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 6d3c6c4..99a0f2b 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"یہ خصوصیت تجرباتی ہے اور اس کی وجہ سے کاکردگی متاثر ہو سکتی ہے۔"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریبا <xliff:g id="TIME">%1$s</xliff:g> باقی ہیں"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎ - تقریبا <xliff:g id="TIME">%2$s</xliff:g> باقی"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>‎"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>‎ پورا ہونے تک"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC‎ پر پورا ہونے تک"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB‎ پر پورا ہونے تک"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"‏‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>‎ وائرلیس سے پورا ہونے تک"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"نامعلوم"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"چارج ہو رہا ہے"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"‏AC پر چارج ہو رہی ہے"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"‏‫USB پر چارج ہورہی ہے"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"وائرلیس چارجنگ"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index ec04120..b9c0243 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya tajribaviy bo‘lib, u qurilma unumdorligiga ta’sir qilishi mumkin."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, to‘lguncha"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, o‘zgaruvchan tok orqali to‘lguncha"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, USB orqali to‘lguncha"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, simsiz quvvatlash orqali to‘lguncha"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Noma’lum"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Quvvat olmoqda"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Quvvat olmoqda (AC)"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Quvvat olmoqda (USB)"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Simsiz quvvat olmoqda"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Quvvat olmayapti"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Quvvatlanmayapti"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"To‘la"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index dd1d482..0c3dc89 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tính năng này là tính năng thử nghiệm và có thể ảnh hưởng đến hoạt động."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - còn khoảng <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy khi cắm vào nguồn AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy qua USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy từ không dây"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Không xác định"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Đang sạc"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Sạc trên AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Sạc qua USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Sạc không dây"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Hiện không sạc"</string>
     <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>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 4117ae1..2b8ce65 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"此功能为实验性功能,可能会影响性能。"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"还剩大约 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还可用大约<xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(交流电充电)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(USB充电)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(无线充电)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"正在充电"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在通过交流电源充电"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在通过USB充电"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在无线充电"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 1fb4c5e..8dd0417 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會影響效能。"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"尚餘大約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 尚餘大約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (透過插頭充電)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (透過 USB 充電)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (無線充電)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在透過 AC 充電"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 9c85f0e..dd59954 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會對效能造成影響。"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"還剩大約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 大約還剩 <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (AC)"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (USB)"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (無線充電)"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在透過 AC 變壓器充電"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 6017d68..610cac4 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -296,17 +296,35 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Lesi sici esesilingo futhi singathinta ukusebenza."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="4400068916452346544">"Cishe ngu-<xliff:g id="TIME">%1$s</xliff:g> osele"</string>
+    <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
+    <skip />
     <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - isilinganiso esingu-<xliff:g id="TIME">%2$s</xliff:g> esisele"</string>
+    <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
+    <skip />
     <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale"</string>
+    <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
+    <skip />
     <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale ku-AC"</string>
+    <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
+    <skip />
     <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale ngaphezulu kwe-USB"</string>
+    <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
+    <skip />
     <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale kusukela kokungenantambo"</string>
+    <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
+    <skip />
     <string name="battery_info_status_unknown" msgid="196130600938058547">"Akwaziwa"</string>
     <string name="battery_info_status_charging" msgid="1705179948350365604">"Iyashaja"</string>
     <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Iyashaja ku-AC"</string>
+    <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
+    <skip />
     <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Iyashaja ngaphezulu kwe-USB"</string>
+    <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
+    <skip />
     <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Iyashaja ngaphandle kwentambo"</string>
+    <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
+    <skip />
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Ayishaji"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ayishaji"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Kugcwele"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index fe3ef1a..a560e3c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -733,25 +733,44 @@
     <!-- [CHAR_LIMIT=40] Label for estimated remaining duration of battery charging/discharging -->
     <string name="power_remaining_duration_only">Approx. <xliff:g id="time">%1$s</xliff:g> left</string>
 
+    <!-- [CHAR_LIMIT=40] Short label for estimated remaining duration of battery charging/discharging -->
+    <string name="power_remaining_duration_only_short"><xliff:g id="time">%1$s</xliff:g> left</string>
+
     <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration -->
     <string name="power_discharging_duration"><xliff:g id="level">%1$s</xliff:g>
         - approx. <xliff:g id="time">%2$s</xliff:g> left</string>
 
+    <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration -->
+    <string name="power_discharging_duration_short"><xliff:g id="level">%1$s</xliff:g>
+        - <xliff:g id="time">%2$s</xliff:g> left</string>
+
     <!-- [CHAR_LIMIT=40] Label for battery level chart when charging -->
     <string name="power_charging"><xliff:g id="level">%1$s</xliff:g> -
             <xliff:g id="state">%2$s</xliff:g></string>
     <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
     <string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> -
             <xliff:g id="time">%2$s</xliff:g> until full</string>
+    <!-- [CHAR_LIMIT=40] Short label for battery level chart when charging with duration -->
+    <string name="power_charging_duration_short"><xliff:g id="level">%1$s</xliff:g> -
+        <xliff:g id="time">%2$s</xliff:g></string>
     <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
     <string name="power_charging_duration_ac"><xliff:g id="level">%1$s</xliff:g> -
             <xliff:g id="time">%2$s</xliff:g> until full on AC</string>
+    <!-- [CHAR_LIMIT=40] Short label for battery level chart when charging with duration -->
+    <string name="power_charging_duration_ac_short"><xliff:g id="level">%1$s</xliff:g> -
+        <xliff:g id="time">%2$s</xliff:g></string>
     <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
     <string name="power_charging_duration_usb"><xliff:g id="level">%1$s</xliff:g> -
             <xliff:g id="time">%2$s</xliff:g> until full over USB</string>
+    <!-- [CHAR_LIMIT=40] Short label for battery level chart when charging with duration -->
+    <string name="power_charging_duration_usb_short"><xliff:g id="level">%1$s</xliff:g> -
+        <xliff:g id="time">%2$s</xliff:g></string>
     <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
     <string name="power_charging_duration_wireless"><xliff:g id="level">%1$s</xliff:g> -
             <xliff:g id="time">%2$s</xliff:g> until full from wireless</string>
+    <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
+    <string name="power_charging_duration_wireless_short"><xliff:g id="level">%1$s</xliff:g> -
+        <xliff:g id="time">%2$s</xliff:g></string>
 
     <!-- Battery Info screen. Value for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="battery_info_status_unknown">Unknown</string>
@@ -759,10 +778,16 @@
     <string name="battery_info_status_charging">Charging</string>
     <!-- [CHAR_LIMIT=20] Battery use screen.  Battery status shown in chart label when charging on AC.  -->
     <string name="battery_info_status_charging_ac">Charging on AC</string>
+    <!-- [CHAR_LIMIT=20] Battery short status label when charing on AC -->
+    <string name="battery_info_status_charging_ac_short">Charging</string>
     <!-- [CHAR_LIMIT=20] Battery use screen.  Battery status shown in chart label when charging over USB.  -->
     <string name="battery_info_status_charging_usb">Charging over USB</string>
+    <!-- [CHAR_LIMIT=20] Battery short status label when charging over USB. -->
+    <string name="battery_info_status_charging_usb_short">Charging</string>
     <!-- [CHAR_LIMIT=20] Battery use screen.  Battery status shown in chart label when charging over a wireless connection.  -->
     <string name="battery_info_status_charging_wireless">Charging wirelessly</string>
+    <!-- [CHAR_LIMIT=20] Battery short status label when charging wirelessly. -->
+    <string name="battery_info_status_charging_wireless_short">Charging</string>
     <!-- Battery Info screen. Value for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="battery_info_status_discharging">Not charging</string>
     <!-- Battery Info screen. Value for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
index 6b29e21..fa1f91f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
@@ -25,6 +25,7 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.text.format.Formatter;
+import android.util.Log;
 import android.util.SparseIntArray;
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.settingslib.graph.UsageView;
@@ -95,6 +96,11 @@
     }
 
     public static void getBatteryInfo(final Context context, final Callback callback) {
+        BatteryInfo.getBatteryInfo(context, callback, false);
+    }
+
+    public static void getBatteryInfo(final Context context, final Callback callback,
+            boolean shortString) {
         new AsyncTask<Void, Void, BatteryStats>() {
             @Override
             protected BatteryStats doInBackground(Void... params) {
@@ -109,14 +115,20 @@
                 Intent batteryBroadcast = context.registerReceiver(null,
                         new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
                 BatteryInfo batteryInfo = BatteryInfo.getBatteryInfo(context,
-                        batteryBroadcast, batteryStats, elapsedRealtimeUs);
+                        batteryBroadcast, batteryStats, elapsedRealtimeUs, shortString);
                 callback.onBatteryInfoLoaded(batteryInfo);
             }
         }.execute();
     }
 
     public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
-            BatteryStats stats, long elapsedRealtimeUs) {
+                                             BatteryStats stats, long elapsedRealtimeUs) {
+        return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats, elapsedRealtimeUs,
+                false);
+    }
+
+    public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
+            BatteryStats stats, long elapsedRealtimeUs, boolean shortString) {
         BatteryInfo info = new BatteryInfo();
         info.mStats = stats;
         info.mBatteryLevel = Utils.getBatteryLevel(batteryBroadcast);
@@ -129,9 +141,13 @@
                 info.remainingTimeUs = drainTime;
                 String timeString = Formatter.formatShortElapsedTime(context,
                         drainTime / 1000);
-                info.remainingLabel = resources.getString(R.string.power_remaining_duration_only,
+                info.remainingLabel = resources.getString(
+                        shortString ? R.string.power_remaining_duration_only_short
+                                : R.string.power_remaining_duration_only,
                         timeString);
-                info.mChargeLabelString = resources.getString(R.string.power_discharging_duration,
+                info.mChargeLabelString = resources.getString(
+                        shortString ? R.string.power_discharging_duration_short
+                                : R.string.power_discharging_duration,
                         info.batteryPercentString, timeString);
             } else {
                 info.remainingLabel = null;
@@ -140,7 +156,7 @@
         } else {
             final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
             final String statusLabel = Utils.getBatteryStatus(
-                    resources, batteryBroadcast);
+                    resources, batteryBroadcast, shortString);
             final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
                     BatteryManager.BATTERY_STATUS_UNKNOWN);
             if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
@@ -151,13 +167,17 @@
                 int plugType = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
                 int resId;
                 if (plugType == BatteryManager.BATTERY_PLUGGED_AC) {
-                    resId = R.string.power_charging_duration_ac;
+                    resId = shortString ? R.string.power_charging_duration_ac_short
+                            : R.string.power_charging_duration_ac;
                 } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) {
-                    resId = R.string.power_charging_duration_usb;
+                    resId = shortString ? R.string.power_charging_duration_usb_short
+                            : R.string.power_charging_duration_usb;
                 } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
-                    resId = R.string.power_charging_duration_wireless;
+                    resId = shortString ? R.string.power_charging_duration_wireless_short
+                            : R.string.power_charging_duration_wireless;
                 } else {
-                    resId = R.string.power_charging_duration;
+                    resId = shortString ? R.string.power_charging_duration_short
+                            : R.string.power_charging_duration;
                 }
                 info.remainingLabel = resources.getString(R.string.power_remaining_duration_only,
                         timeString);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index e86ca82..59637be 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -459,58 +459,40 @@
         LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
         EnforcedAdmin enforcedAdmin = null;
         final int userId = UserHandle.myUserId();
-        if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
-            // userId is managed profile and has a separate challenge, only consider
-            // the admins in that user.
-            final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
+        final UserManager um = UserManager.get(context);
+        final List<UserInfo> profiles = um.getProfiles(userId);
+        final int profilesSize = profiles.size();
+        // As we do not have a separate screen lock timeout settings for work challenge,
+        // we need to combine all profiles maximum time to lock even work challenge is
+        // enabled.
+        for (int i = 0; i < profilesSize; i++) {
+            final UserInfo userInfo = profiles.get(i);
+            final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
             if (admins == null) {
-                return null;
+                continue;
             }
             for (ComponentName admin : admins) {
-                if (dpm.getMaximumTimeToLock(admin, userId) > 0) {
+                if (dpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
                     if (enforcedAdmin == null) {
-                        enforcedAdmin = new EnforcedAdmin(admin, userId);
+                        enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
                     } else {
                         return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                     }
-                }
-            }
-        } else {
-            // Return all admins for this user and the profiles that are visible from this
-            // user that do not use a separate work challenge.
-            final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
-            for (UserInfo userInfo : um.getProfiles(userId)) {
-                final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
-                if (admins == null) {
+                    // This same admins could have set policies both on the managed profile
+                    // and on the parent. So, if the admin has set the policy on the
+                    // managed profile here, we don't need to further check if that admin
+                    // has set policy on the parent admin.
                     continue;
                 }
-                final boolean isSeparateProfileChallengeEnabled =
-                        lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
-                for (ComponentName admin : admins) {
-                    if (!isSeparateProfileChallengeEnabled) {
-                        if (dpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
-                            if (enforcedAdmin == null) {
-                                enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
-                            } else {
-                                return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
-                            }
-                            // This same admins could have set policies both on the managed profile
-                            // and on the parent. So, if the admin has set the policy on the
-                            // managed profile here, we don't need to further check if that admin
-                            // has set policy on the parent admin.
-                            continue;
-                        }
-                    }
-                    if (userInfo.isManagedProfile()) {
-                        // If userInfo.id is a managed profile, we also need to look at
-                        // the policies set on the parent.
-                        DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
-                        if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
-                            if (enforcedAdmin == null) {
-                                enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
-                            } else {
-                                return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
-                            }
+                if (userInfo.isManagedProfile()) {
+                    // If userInfo.id is a managed profile, we also need to look at
+                    // the policies set on the parent.
+                    final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+                    if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
+                        if (enforcedAdmin == null) {
+                            enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
+                        } else {
+                            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                         }
                     }
                 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 74c1ebd..586f269 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -112,20 +112,26 @@
     }
 
     public static String getBatteryStatus(Resources res, Intent batteryChangedIntent) {
-        final Intent intent = batteryChangedIntent;
+        return Utils.getBatteryStatus(res, batteryChangedIntent, false);
+    }
 
-        int plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
-        int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
+    public static String getBatteryStatus(Resources res, Intent batteryChangedIntent,
+            boolean shortString) {
+        int plugType = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
+        int status = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_STATUS,
                 BatteryManager.BATTERY_STATUS_UNKNOWN);
         String statusString;
         if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
             int resId;
             if (plugType == BatteryManager.BATTERY_PLUGGED_AC) {
-                resId = R.string.battery_info_status_charging_ac;
+                resId = shortString ? R.string.battery_info_status_charging_ac_short
+                        : R.string.battery_info_status_charging_ac;
             } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) {
-                resId = R.string.battery_info_status_charging_usb;
+                resId = shortString ? R.string.battery_info_status_charging_usb_short
+                        : R.string.battery_info_status_charging_usb;
             } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
-                resId = R.string.battery_info_status_charging_wireless;
+                resId = shortString ? R.string.battery_info_status_charging_wireless_short
+                        : R.string.battery_info_status_charging_wireless;
             } else {
                 resId = R.string.battery_info_status_charging;
             }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index aa95be2..d7c9eab 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -144,7 +144,9 @@
                     return true;
                 }
             }
-            mService.disconnect(device);
+            for (BluetoothDevice src : srcs) {
+                mService.disconnect(device);
+            }
         }
         Log.d(TAG,"PBAPClientProfile attempting to connect to " + device.getAddress());
 
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index c131fa5..7ca7614 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -463,7 +463,6 @@
                 .setContentTitle(title)
                 .setTicker(title)
                 .setContentText(name)
-                .setContentInfo(percentageText)
                 .setProgress(info.max, info.progress, false)
                 .setOngoing(true)
                 .setContentIntent(infoPendingIntent)
@@ -958,7 +957,7 @@
                 .setDeleteIntent(newCancelIntent(context, info));
 
         if (!TextUtils.isEmpty(info.name)) {
-            builder.setContentInfo(info.name);
+            builder.setSubText(info.name);
         }
 
         Log.v(TAG, "Sending 'Share' notification for ID " + info.id + ": " + title);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 9839446..9e2442c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -184,6 +184,14 @@
             android:exported="true"
             />
 
+        <!-- Recents depends on every user having their own SystemUI process, so on user switch,
+             ensure that the process is created by starting this service.
+             -->
+        <service android:name="SystemUISecondaryUserService"
+            android:exported="true"
+            android:permission="com.android.systemui.permission.SELF" />
+
+
         <!-- started from PhoneWindowManager
              TODO: Should have an android:permission attribute -->
         <service android:name=".screenshot.TakeScreenshotService"
@@ -366,7 +374,6 @@
             android:name="com.android.systemui.tv.pip.PipOverlayActivity"
             android:exported="true"
             android:theme="@style/PipTheme"
-            android:launchMode="singleTop"
             android:taskAffinity=""
             android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
             android:resizeableActivity="true"
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_fade_in.xml b/packages/SystemUI/res/anim/tv_pip_controls_buttons_in_recents_focus_gain_animation.xml
similarity index 78%
rename from packages/SystemUI/res/anim/tv_pip_controls_fade_in.xml
rename to packages/SystemUI/res/anim/tv_pip_controls_buttons_in_recents_focus_gain_animation.xml
index 89e4aac..ebc6a4a7 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_fade_in.xml
+++ b/packages/SystemUI/res/anim/tv_pip_controls_buttons_in_recents_focus_gain_animation.xml
@@ -17,13 +17,13 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android">
 
     <objectAnimator
-        android:propertyName="translationY"
-        android:valueTo="10dp"
-        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:propertyName="scaleX"
+        android:valueTo="1.0"
+        android:interpolator="@android:interpolator/fast_out_slow_in"
         android:duration="@integer/recents_tv_pip_focus_anim_duration" />
     <objectAnimator
-        android:propertyName="alpha"
+        android:propertyName="scaleY"
         android:valueTo="1.0"
-        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:interpolator="@android:interpolator/fast_out_slow_in"
         android:duration="@integer/recents_tv_pip_focus_anim_duration" />
 </set>
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_fade_out.xml b/packages/SystemUI/res/anim/tv_pip_controls_buttons_in_recents_focus_lose_animation.xml
similarity index 76%
rename from packages/SystemUI/res/anim/tv_pip_controls_fade_out.xml
rename to packages/SystemUI/res/anim/tv_pip_controls_buttons_in_recents_focus_lose_animation.xml
index c73fed6..95499bd 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_fade_out.xml
+++ b/packages/SystemUI/res/anim/tv_pip_controls_buttons_in_recents_focus_lose_animation.xml
@@ -17,13 +17,13 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android">
 
     <objectAnimator
-        android:propertyName="translationY"
-        android:valueTo="0dp"
-        android:interpolator="@android:interpolator/fast_out_linear_in"
+        android:propertyName="scaleX"
+        android:valueTo="0.7"
+        android:interpolator="@android:interpolator/fast_out_slow_in"
         android:duration="@integer/recents_tv_pip_focus_anim_duration" />
     <objectAnimator
-        android:propertyName="alpha"
-        android:valueTo="0.0"
-        android:interpolator="@android:interpolator/fast_out_linear_in"
+        android:propertyName="scaleY"
+        android:valueTo="0.7"
+        android:interpolator="@android:interpolator/fast_out_slow_in"
         android:duration="@integer/recents_tv_pip_focus_anim_duration" />
 </set>
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_gain_animation.xml
new file mode 100644
index 0000000..7555bdd
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_gain_animation.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:propertyName="translationY"
+    android:valueTo="0dp"
+    android:interpolator="@android:interpolator/fast_out_slow_in"
+    android:duration="@integer/recents_tv_pip_focus_anim_duration" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_lose_animation.xml
new file mode 100644
index 0000000..b40ccd4
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_lose_animation.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:propertyName="translationY"
+    android:valueTo="-57dp"
+    android:interpolator="@android:interpolator/fast_out_slow_in"
+    android:duration="@integer/recents_tv_pip_focus_anim_duration" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
new file mode 100644
index 0000000..681ff91
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:propertyName="alpha"
+    android:valueTo="1"
+    android:interpolator="@android:interpolator/fast_out_slow_in"
+    android:duration="@integer/recents_tv_pip_focus_anim_duration" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
new file mode 100644
index 0000000..e6deb0f
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:propertyName="alpha"
+    android:valueTo="0"
+    android:interpolator="@android:interpolator/fast_out_slow_in"
+    android:duration="@integer/recents_tv_pip_focus_anim_duration" />
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_image.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_image.png
deleted file mode 100644
index 7b0fcc7..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_image.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_image_error.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_image_error.png
deleted file mode 100644
index 73e9c96..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_image_error.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_image.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_image.png
deleted file mode 100644
index a02e21c..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_image.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_image_error.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_image_error.png
deleted file mode 100644
index 4af2617..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_image_error.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_notify_image.png b/packages/SystemUI/res/drawable-xhdpi/stat_notify_image.png
deleted file mode 100644
index 24bdbb6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_notify_image.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_notify_image_error.png b/packages/SystemUI/res/drawable-xhdpi/stat_notify_image_error.png
deleted file mode 100644
index 6ecd2d3..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_notify_image_error.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image.png b/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image.png
deleted file mode 100644
index 5e733ef..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image_error.png b/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image_error.png
deleted file mode 100644
index ecc2c83..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_image_error.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml
new file mode 100644
index 0000000..6519673
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path android:pathData="M0 0h24v24H0z" />
+    <path android:fillColor="@color/ksh_key_item_color"
+            android:pathData="M22 3H7c-.69 0-1.23 .35 -1.59 .88 L0 12l5.41 8.11c.36 .53 .9 .89
+1.59 .89 h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59
+12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_down.xml b/packages/SystemUI/res/drawable/ic_ksh_key_down.xml
new file mode 100644
index 0000000..25a2560
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_down.xml
@@ -0,0 +1,25 @@
+<?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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path android:fillColor="@color/ksh_key_item_color"
+            android:pathData="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
+    <path android:pathData="M0-.75h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml b/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml
new file mode 100644
index 0000000..599f350
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml
@@ -0,0 +1,25 @@
+<?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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path android:pathData="M0 0h24v24H0z" />
+   <path android:fillColor="@color/ksh_key_item_color"
+            android:pathData="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_left.xml b/packages/SystemUI/res/drawable/ic_ksh_key_left.xml
new file mode 100644
index 0000000..038187e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_left.xml
@@ -0,0 +1,25 @@
+<?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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path android:fillColor="@color/ksh_key_item_color"
+            android:pathData="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
+    <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml b/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml
new file mode 100644
index 0000000..1e2195e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_meta.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
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path android:fillColor="@color/ksh_key_item_color"
+            android:pathData="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91
+3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27 .28 v.79l5 4.99L20.49
+19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5
+14z" />
+    <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_right.xml b/packages/SystemUI/res/drawable/ic_ksh_key_right.xml
new file mode 100644
index 0000000..f2d7315
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_right.xml
@@ -0,0 +1,25 @@
+<?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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path android:fillColor="@color/ksh_key_item_color"
+            android:pathData="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
+    <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_up.xml b/packages/SystemUI/res/drawable/ic_ksh_key_up.xml
new file mode 100644
index 0000000..36a83b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_up.xml
@@ -0,0 +1,25 @@
+<?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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path android:fillColor="@color/ksh_key_item_color"
+            android:pathData="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" />
+    <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_notify_image.xml b/packages/SystemUI/res/drawable/stat_notify_image.xml
new file mode 100644
index 0000000..c8745d7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_notify_image.xml
@@ -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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z
+M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5 L8.5,13.5z" />
+    <path
+        android:pathData="M0,0h24v24H0V0z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_notify_image_error.xml b/packages/SystemUI/res/drawable/stat_notify_image_error.xml
new file mode 100644
index 0000000..b929005
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_notify_image_error.xml
@@ -0,0 +1,30 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:pathData="M0,0h24v24H0V0z" />
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M17,18H5l3.5-4.5l2.5,3l3.3-4.5l2.7,3.8V8h4V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h12V18z" />
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.2,21H21v-1.8h-1.8V21z M19.2,9.9v7.4H21V9.9H19.2z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_button_focused.xml b/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
index 5cabb77..405ea0c 100644
--- a/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
@@ -17,8 +17,8 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="oval">
     <size
-        android:width="36dp"
-        android:height="36dp" />
+        android:width="34dp"
+        android:height="34dp" />
     <solid
         android:color="#4DFFFFFF" />
 </shape>
diff --git a/packages/SystemUI/res/drawable/tv_pip_close_button.xml b/packages/SystemUI/res/drawable/tv_pip_close_button.xml
index 86fda0d..186a4ba 100644
--- a/packages/SystemUI/res/drawable/tv_pip_close_button.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_close_button.xml
@@ -19,8 +19,20 @@
     <item android:state_focused="true">
         <layer-list>
             <item android:drawable="@drawable/tv_pip_button_focused" />
-            <item android:drawable="@drawable/ic_close_white" />
+            <item android:drawable="@drawable/ic_close_white"
+                android:top="@dimen/tv_pip_button_icon_padding"
+                android:bottom="@dimen/tv_pip_button_icon_padding"
+                android:left="@dimen/tv_pip_button_icon_padding"
+                android:right="@dimen/tv_pip_button_icon_padding" />
         </layer-list>
     </item>
-    <item android:drawable="@drawable/ic_close_white" />
+    <item>
+        <layer-list>
+            <item android:drawable="@drawable/ic_close_white"
+                android:top="@dimen/tv_pip_button_icon_padding"
+                android:bottom="@dimen/tv_pip_button_icon_padding"
+                android:left="@dimen/tv_pip_button_icon_padding"
+                android:right="@dimen/tv_pip_button_icon_padding" />
+        </layer-list>
+    </item>
 </selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_full_button.xml b/packages/SystemUI/res/drawable/tv_pip_full_button.xml
index 332c669..c48dc828 100644
--- a/packages/SystemUI/res/drawable/tv_pip_full_button.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_full_button.xml
@@ -19,8 +19,20 @@
     <item android:state_focused="true">
         <layer-list>
             <item android:drawable="@drawable/tv_pip_button_focused" />
-            <item android:drawable="@drawable/ic_fullscreen_white_24dp" />
+            <item android:drawable="@drawable/ic_fullscreen_white_24dp"
+                android:top="@dimen/tv_pip_button_icon_padding"
+                android:bottom="@dimen/tv_pip_button_icon_padding"
+                android:left="@dimen/tv_pip_button_icon_padding"
+                android:right="@dimen/tv_pip_button_icon_padding" />
         </layer-list>
     </item>
-    <item android:drawable="@drawable/ic_fullscreen_white_24dp" />
+    <item>
+        <layer-list>
+            <item android:drawable="@drawable/ic_fullscreen_white_24dp"
+                android:top="@dimen/tv_pip_button_icon_padding"
+                android:bottom="@dimen/tv_pip_button_icon_padding"
+                android:left="@dimen/tv_pip_button_icon_padding"
+                android:right="@dimen/tv_pip_button_icon_padding" />
+        </layer-list>
+    </item>
 </selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_pause_button.xml b/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
index d277b07..bcc8973 100644
--- a/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
@@ -19,8 +19,20 @@
     <item android:state_focused="true">
         <layer-list>
             <item android:drawable="@drawable/tv_pip_button_focused" />
-            <item android:drawable="@drawable/ic_pause_white_24dp" />
+            <item android:drawable="@drawable/ic_pause_white_24dp"
+                android:top="@dimen/tv_pip_button_icon_padding"
+                android:bottom="@dimen/tv_pip_button_icon_padding"
+                android:left="@dimen/tv_pip_button_icon_padding"
+                android:right="@dimen/tv_pip_button_icon_padding" />
         </layer-list>
     </item>
-    <item android:drawable="@drawable/ic_pause_white_24dp" />
+    <item>
+        <layer-list>
+            <item android:drawable="@drawable/ic_pause_white_24dp"
+                android:top="@dimen/tv_pip_button_icon_padding"
+                android:bottom="@dimen/tv_pip_button_icon_padding"
+                android:left="@dimen/tv_pip_button_icon_padding"
+                android:right="@dimen/tv_pip_button_icon_padding" />
+        </layer-list>
+    </item>
 </selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_play_button.xml b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
index fecdc09..f77ea1d 100644
--- a/packages/SystemUI/res/drawable/tv_pip_play_button.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
@@ -19,8 +19,20 @@
     <item android:state_focused="true">
         <layer-list>
             <item android:drawable="@drawable/tv_pip_button_focused" />
-            <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
+            <item android:drawable="@drawable/ic_play_arrow_white_24dp"
+                android:top="@dimen/tv_pip_button_icon_padding"
+                android:bottom="@dimen/tv_pip_button_icon_padding"
+                android:left="@dimen/tv_pip_button_icon_padding"
+                android:right="@dimen/tv_pip_button_icon_padding" />
         </layer-list>
     </item>
-    <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
+    <item>
+        <layer-list>
+            <item android:drawable="@drawable/ic_play_arrow_white_24dp"
+                android:top="@dimen/tv_pip_button_icon_padding"
+                android:bottom="@dimen/tv_pip_button_icon_padding"
+                android:left="@dimen/tv_pip_button_icon_padding"
+                android:right="@dimen/tv_pip_button_icon_padding" />
+        </layer-list>
+    </item>
 </selector>
diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml
index af3e379..8e7feec94 100644
--- a/packages/SystemUI/res/layout/battery_detail.xml
+++ b/packages/SystemUI/res/layout/battery_detail.xml
@@ -26,10 +26,13 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:paddingStart="72dp"
-        android:paddingBottom="@dimen/battery_detail_graph_space_top"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textColor="?android:attr/colorAccent" />
 
+    <com.android.systemui.ResizingSpace
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/battery_detail_graph_space_top" />
+
     <com.android.settingslib.graph.UsageView
         android:id="@+id/battery_usage"
         android:layout_width="match_parent"
@@ -40,11 +43,14 @@
         android:colorAccent="?android:attr/colorAccent"
         systemui:textColor="#66FFFFFF" />
 
+    <com.android.systemui.ResizingSpace
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/battery_detail_graph_space_bottom" />
+
     <View
         android:layout_width="match_parent"
         android:layout_height="1dp"
         android:background="?android:attr/listDivider"
-        android:layout_marginTop="@dimen/battery_detail_graph_space_bottom"
         android:layout_marginBottom="8dp" />
 
     <RelativeLayout
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
new file mode 100644
index 0000000..0cecb96
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="@dimen/ksh_item_padding"
+        android:layout_marginStart="@dimen/ksh_item_margin_start"
+        android:scaleType="fitXY"
+        android:background="@color/ksh_key_item_background"/>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
index 5002c12..1215029 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
@@ -17,9 +17,9 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
-          android:layout_marginStart="4dp"
-          android:padding="4dp"
-          android:background="#EEEEEE"
-          android:textColor="#8C000000"
+          android:padding="@dimen/ksh_item_padding"
+          android:layout_marginStart="@dimen/ksh_item_margin_start"
+          android:background="@color/ksh_key_item_background"
+          android:textColor="@color/ksh_key_item_color"
           android:singleLine="true"
-          android:textSize="14sp"/>
+          android:textSize="@dimen/ksh_item_text_size"/>
diff --git a/core/res/res/layout/notification_action_list.xml b/packages/SystemUI/res/layout/qs_customize_tile_divider.xml
similarity index 65%
rename from core/res/res/layout/notification_action_list.xml
rename to packages/SystemUI/res/layout/qs_customize_tile_divider.xml
index 400decc..0d932ac 100644
--- a/core/res/res/layout/notification_action_list.xml
+++ b/packages/SystemUI/res/layout/qs_customize_tile_divider.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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,17 +15,11 @@
      limitations under the License.
 -->
 
-<LinearLayout
+<View
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/actions"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="horizontal"
-    android:visibility="gone"
-    android:layout_marginBottom="8dp"
-    android:showDividers="middle"
-    android:divider="?android:attr/listDivider"
-    android:dividerPadding="12dp"
-    >
-    <!-- actions will be added here -->
-</LinearLayout>
+    android:layout_marginStart="16dp"
+    android:layout_marginEnd="16dp"
+    android:background="?android:attr/listDivider"
+    android:importantForAccessibility="no" />
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 3358a18..af2a285 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -25,13 +25,15 @@
     android:visibility="invisible"
     android:orientation="vertical">
 
+    <com.android.systemui.ResizingSpace
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/qs_detail_margin_top" />
+
     <include
         android:id="@+id/qs_detail_header"
         layout="@layout/qs_detail_header"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="28dp"
-        />
+        android:layout_height="wrap_content" />
 
     <com.android.systemui.statusbar.AlphaOptimizedImageView
         android:id="@+id/qs_detail_header_progress"
diff --git a/packages/SystemUI/res/layout/qs_detail_items.xml b/packages/SystemUI/res/layout/qs_detail_items.xml
index c22e42c..f1a8d63 100644
--- a/packages/SystemUI/res/layout/qs_detail_items.xml
+++ b/packages/SystemUI/res/layout/qs_detail_items.xml
@@ -16,17 +16,19 @@
 -->
 <!-- extends FrameLayout -->
 <com.android.systemui.qs.QSDetailItems xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:sysui="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:paddingTop="16dp"
+    android:paddingTop="@dimen/qs_detail_items_padding_top"
     android:paddingStart="16dp"
     android:paddingEnd="16dp">
 
-    <LinearLayout
+    <com.android.systemui.qs.AutoSizingList
         android:id="@android:id/list"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical" />
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        sysui:itemHeight="@dimen/qs_detail_item_height" />
 
     <LinearLayout
         android:id="@android:id/empty"
@@ -48,9 +50,4 @@
             android:layout_marginTop="20dp"
             android:textAppearance="@style/TextAppearance.QS.DetailEmpty" />
     </LinearLayout>
-
-    <View
-        android:id="@+id/min_height_spacer"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"/>
-</com.android.systemui.qs.QSDetailItems>
\ No newline at end of file
+</com.android.systemui.qs.QSDetailItems>
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index b0dca9a..cce9c0f 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -26,9 +26,7 @@
             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:textAppearance="@style/TextAppearance.QS.TileLabel"
             android:clickable="false" />
      <ImageView android:id="@+id/restricted_padlock"
             android:layout_width="@dimen/qs_tile_text_size"
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml
index 0f8c77c..28ea66d 100644
--- a/packages/SystemUI/res/layout/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout/recents_on_tv.xml
@@ -31,18 +31,12 @@
         android:focusable="true"
         android:layoutDirection="rtl" />
 
+    <!-- Placeholder view to give focus to the PIP menus. -->
     <View
-        android:id="@+id/pip_shade"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="gone"
-        android:background="#76000000" />
-
-    <include
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="top|center_horizontal"
-        android:layout_marginTop="132dp"
-        layout="@layout/tv_pip_controls" />
+        android:id="@+id/pip"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:focusable="true"
+        android:visibility="gone" />
 
 </com.android.systemui.recents.tv.views.RecentsTvView>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
index 224a0a0..60112be 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
@@ -112,21 +112,6 @@
         <ImageView
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:scaleType="matrix"
-            android:src="@drawable/screen_pinning_light_bg_circ" />
-
-        <ImageView
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:paddingEnd="@dimen/screen_pinning_request_inner_padding"
-            android:paddingStart="@dimen/screen_pinning_request_inner_padding"
-            android:paddingTop="@dimen/screen_pinning_request_inner_padding"
-            android:scaleType="matrix"
-            android:src="@drawable/screen_pinning_bg_circ" />
-
-        <ImageView
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
             android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
             android:paddingStart="@dimen/screen_pinning_request_nav_side_padding"
             android:paddingTop="@dimen/screen_pinning_request_nav_icon_padding"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
index 1e5193f..ebad7a4 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
@@ -43,21 +43,6 @@
         <ImageView
             android:layout_height="match_parent"
             android:layout_width="match_parent"
-            android:scaleType="matrix"
-            android:src="@drawable/screen_pinning_light_bg_circ" />
-
-        <ImageView
-            android:layout_height="match_parent"
-            android:layout_width="match_parent"
-            android:scaleType="matrix"
-            android:paddingLeft="@dimen/screen_pinning_request_inner_padding"
-            android:paddingTop="@dimen/screen_pinning_request_inner_padding"
-            android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
-            android:src="@drawable/screen_pinning_bg_circ" />
-
-        <ImageView
-            android:layout_height="match_parent"
-            android:layout_width="match_parent"
             android:scaleType="center"
             android:paddingLeft="@dimen/screen_pinning_request_nav_icon_padding"
             android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
diff --git a/packages/SystemUI/res/layout/tv_pip_controls.xml b/packages/SystemUI/res/layout/tv_pip_controls.xml
index 2e0c9e7..563441f 100644
--- a/packages/SystemUI/res/layout/tv_pip_controls.xml
+++ b/packages/SystemUI/res/layout/tv_pip_controls.xml
@@ -17,13 +17,8 @@
 */
 -->
 
-<com.android.systemui.tv.pip.PipControlsView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/pip_controls"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:gravity="center"
-    android:orientation="horizontal">
+<!-- Layout for {@link com.android.systemui.tv.pip.PipControlsView}. -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
 
     <LinearLayout
         android:layout_width="100dp"
@@ -98,4 +93,4 @@
             android:textSize="12sp"
             android:textColor="#EEEEEE" />
     </LinearLayout>
-</com.android.systemui.tv.pip.PipControlsView>
+</merge>
diff --git a/packages/SystemUI/res/layout/tv_pip_menu.xml b/packages/SystemUI/res/layout/tv_pip_menu.xml
index c2c83ff..2647a99 100644
--- a/packages/SystemUI/res/layout/tv_pip_menu.xml
+++ b/packages/SystemUI/res/layout/tv_pip_menu.xml
@@ -26,7 +26,8 @@
     android:gravity="top|center_horizontal"
     android:clipChildren="false">
 
-    <include
-        layout="@layout/tv_pip_controls"
-        android:clipChildren="false" />
+    <com.android.systemui.tv.pip.PipControlsView
+        android:id="@+id/pip_controls"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml
index c5c7e84..64bf3b5 100644
--- a/packages/SystemUI/res/layout/tv_pip_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_overlay.xml
@@ -38,25 +38,4 @@
         android:gravity="center"
         android:maxLines="2"
         android:text="@string/pip_hold_home" />
-    <LinearLayout
-        android:id="@+id/guide_buttons"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:layout_centerHorizontal="true"
-        android:orientation="horizontal">
-        <ImageView
-            android:layout_width="19dp"
-            android:layout_height="19dp"
-            android:src="@drawable/ic_fullscreen_white_24dp" />
-        <ImageView
-            android:layout_width="19dp"
-            android:layout_height="19dp"
-            android:src="@drawable/ic_close_white" />
-        <ImageView
-            android:id="@+id/guide_button_play_pause"
-            android:layout_width="19dp"
-            android:layout_height="19dp"
-            android:src="@drawable/ic_pause_white_24dp" />
-    </LinearLayout>
 </RelativeLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml b/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
new file mode 100644
index 0000000..1e464d8
--- /dev/null
+++ b/packages/SystemUI/res/layout/tv_pip_recents_overlay.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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:gravity="top|center_horizontal">
+
+    <com.android.systemui.tv.pip.PipRecentsControlsView
+        android:id="@+id/pip_controls"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent" />
+
+    <View
+        android:id="@+id/recents"
+        android:layout_width="1dp"
+        android:layout_height="1dp"
+        android:focusable="true" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 47d3bff..3fa6245 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Maak <xliff:g id="APP">%s</xliff:g> toe."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwerp."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle onlangse programme is toegemaak."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Begin tans <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Kennisgewing is toegemaak."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Tuis"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Onlangs"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Terug"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Kennisgewings"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Kortpadsleutels"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Wissel invoermetode"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Programme"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Bystand"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Blaaier"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakte"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pos"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Kitsboodskappe"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiek"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Wys saam met volumekontroles"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Moenie steur nie"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Volumeknoppieskortpad"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f2afb8f..eb5d256 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> አስወግድ።"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ተሰናብቷል::"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ሁሉም የቅርብ ጊዜ ማመልከቻዎች ተሰናብተዋል።"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> በመጀመር ላይ።"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ማሳወቂያ ተወግዷል።"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ማሳወቂያዎች"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"የቁልፍ ሰሌዳ አቋራጮች"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"የግቤት ስልት ቀይር"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"መተግበሪያዎች"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ረዳት"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"አሳሽ"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"እውቂያዎች"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ኢሜይል"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"ፈጣን መልዕክት"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ሙዚቃ"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"የቀን መቁጠሪያ"</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>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f949eaf..82a772c 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -172,6 +172,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"إزالة <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"تمت إزالة <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"تم تجاهل كل التطبيقات المستخدمة مؤخرًا."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"جارٍ بدء <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"تم تجاهل الإشعار."</string>
@@ -532,6 +534,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"الإشعارات"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"اختصارات لوحة المفاتيح"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"تبديل أسلوب الإدخال"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"التطبيقات"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"التطبيق المساعد"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"المتصفح"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"جهات الاتصال"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"البريد الإلكتروني"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"الرسائل الفورية"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"الموسيقى"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"التقويم"</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>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 3aa911f..59b3141 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> kənarlaşdırın."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> çıxarıldı."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Bütün son tətbiqlər kənarlaşdırıldı."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> başlanır."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildiriş uzaqlaşdırıldı."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Əsas səhifə"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Sonuncular"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Geri"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Bildirişlər"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klaviatura qısa yolları"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Daxiletmə metoduna keçin"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Tətbiqlər"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Yardım"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brauzer"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktlar"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-poçt"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiqi"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Təqvim"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Həcm nəzarəti ilə göstərin"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Narahat etməyin"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Səs düymələri qısayolu"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index cc091f6..0945885 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -169,6 +169,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacite <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je odbačena."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Sve nedavno korišćene aplikacije su odbačene."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokrećemo <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obaveštenje je odbačeno."</string>
@@ -529,6 +531,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početni"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni sadržaj"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazad"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obaveštenja"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tasterske prečice"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Promeni metod unosa"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Aplikacija za pomoć"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Pregledač"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Imejl"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Razmena trenutnih poruka"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikaži sa kontrolama jačine zvuka"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne uznemiravaj"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Prečica za dugmad za jačinu zvuka"</string>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index a496330..726a0e7 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -172,6 +172,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Выдаліць <xliff:g id="APP">%s</xliff:g> са спіса апошніх."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> выдалены."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усе апошнія праграмы адхілены."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запускаецца <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Апавяшчэнне прапушчана."</string>
@@ -532,6 +534,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Апавяшчэнні"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Спалучэнні клавіш для хуткага доступу"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Пераключэнне рэжыму ўводу"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Праграмы"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Памочнік"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браўзер"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Кантакты"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Электронная пошта"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Iмгненныя паведамленнi"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Каляндар"</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>
@@ -588,12 +602,12 @@
     <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"Перамясціць управа"</string>
     <string name="forced_resizable_info_text" msgid="7591061837558867999">"Праграма можа не працаваць у рэжыме некалькіх вокнаў"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Краніце двойчы, каб рэдагаваць."</string>
-    <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>, краніце двойчы, каб дадаць."</string>
+    <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Краніце двойчы, каб дадаць."</string>
     <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>. Краніце двойчы, каб выбраць."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Перамясціць <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Выдаліць <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> дададзена ў наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> выдалена"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Плітка <xliff:g id="TILE_NAME">%1$s</xliff:g> дададзена ў наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Плітка <xliff:g id="TILE_NAME">%1$s</xliff:g> выдалена"</string>
     <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> перамешчана ў наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Рэдактар хуткіх налад."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 1479bea..479087a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отхвърляне на <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложението <xliff:g id="APP">%s</xliff:g> е отхвърлено."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Всички скорошни приложения са отхвърлени."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> се стартира."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известието е отхвърлено."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Известия"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Клавишни комбинации"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Превключване на метода на въвеждане"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Приложения"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Помощно приложение"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузър"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Електронна поща"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Незабавни съобщения"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</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>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index ed8b066..ccbcb6e 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> খারিজ করুন।"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> খারিজ করা হয়েছে৷"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"সমস্ত সাম্প্রতিক অ্যাপ্লিকেশন খারিজ করা হয়েছে।"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> তারাঙ্কিত করা হচ্ছে।"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"বিজ্ঞপ্তি খারিজ করা হয়েছে৷"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"বিজ্ঞপ্তিগুলি"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"কীবোর্ড শর্টকাট"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ইনপুট পদ্ধতি পাল্টান"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"অ্যাপ্লিকেশানগুলি"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"সহযোগিতা"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ব্রাউজার"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"পরিচিতি"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ইমেল"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"সংগীত"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ক্যালেন্ডার"</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>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index c620178..c5398a2 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -169,6 +169,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbaci aplikaciju <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> uklonjena."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Sve nedavno korištene aplikacije su odbačene."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokrećem aplikaciju <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavještenje je uklonjeno."</string>
@@ -529,6 +531,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početak"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni ekrani"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazad"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obavještenja"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Skracenice tastature"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Promijeni način unosa"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoć"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Preglednik"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikazati sa kontrolama jačine zvuka"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne ometaj"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Prečica za dugmad za Jačinu zvuka"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0145c2a..b7fffb7 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignora <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"S\'ha omès <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"S\'han descartat totes les aplicacions recents."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"S\'està iniciant <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificació omesa."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inici"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recents"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Enrere"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificacions"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tecles de drecera"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Canvia el mètode d\'introducció"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicacions"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistència"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactes"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correu electrònic"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendari"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostra amb els controls de volum"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"No molesteu"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Drecera per als botons de volum"</string>
@@ -583,13 +597,13 @@
     <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>
     <string name="forced_resizable_info_text" msgid="7591061837558867999">"És possible que l\'aplicació no funcioni amb el Mode multifinestra"</string>
-    <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posició <xliff:g id="POSITION">%1$d</xliff:g>, mosaic <xliff:g id="TILE_NAME">%2$s</xliff:g>. Fes doble toc per editar-la."</string>
-    <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"Mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g>. Fes doble toc per afegir-lo."</string>
+    <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posició <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Fes doble toc per editar-la."</string>
+    <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Fes doble toc per afegir-ho."</string>
     <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posició <xliff:g id="POSITION">%1$d</xliff:g>. Fes doble toc per seleccionar-la."</string>
-    <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mou el mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Suprimeix el mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"El mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha afegit a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"El mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha suprimit"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"El mosaic <xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha mogut a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Mou <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
+    <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Suprimeix <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha afegit a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
+    <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha suprimit"</string>
+    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha mogut a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de la configuració ràpida."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index ec2011f..b707ece 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -170,6 +170,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zavřít aplikaci <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikace <xliff:g id="APP">%s</xliff:g> byla odebrána."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všechny naposledy použité aplikace byly odstraněny."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spouštění aplikace <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Oznámení je zavřeno."</string>
@@ -530,6 +532,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Plocha"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Poslední"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Zpět"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Oznámení"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klávesové zkratky"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Přepnout metodu zadávání"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikace"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistence"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Prohlížeč"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakty"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Hudba"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendář"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Zobrazit včetně ovládacích prvků hlasitosti"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nerušit"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Zkratka tlačítek hlasitosti"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 8711100..7a25141 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Afvis <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> er annulleret."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle de seneste applikationer er lukket."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> startes."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Underretningen er annulleret."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Start"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Seneste"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tilbage"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Underretninger"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tastaturgenveje"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Skift indtastningsmetode"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applikationer"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistance"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktpersoner"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Vis med lydstyrkeregulering"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Forstyr ikke"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Genvej til lydstyrkeknapper"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 2daa00f..e10eb64 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> beenden"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> entfernt"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle kürzlich verwendeten Apps wurden entfernt."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> wird gestartet."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Benachrichtigung geschlossen"</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startseite"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Letzte"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Zurück"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Benachrichtigungen"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tastenkombinationen"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Eingabemethode wechseln"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Apps"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistent"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakte"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-Mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Einschließlich Lautstärkeregler anzeigen"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Bitte nicht stören"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Tastenkombination für Lautstärketasten"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 34385f3..5ec3133 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Παράβλεψη <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Απορρίφθηκαν <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Έγινε παράβλεψη όλων των πρόσφατων εφαρμογών."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Έναρξη <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Η ειδοποίηση έχει απορριφθεί."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Ειδοποιήσεις"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Συντομεύσεις πληκτρολογίου"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Εναλλαγή μεθόδου εισαγωγής"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Εφαρμογές"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Υποβοήθηση"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Πρόγραμμα περιήγησης"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Επαφές"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Ηλεκτρονικό ταχυδρομείο"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Άμεσα μηνύματα (ΙΜ)"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Μουσική"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Ημερολόγιο"</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>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 71a8ad7..f08894f 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starting <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Back"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Keyboard Shortcuts"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Switch input method"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assist"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Show with volume controls"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Do not disturb"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Volume buttons shortcut"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 71a8ad7..f08894f 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starting <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Back"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Keyboard Shortcuts"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Switch input method"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assist"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Show with volume controls"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Do not disturb"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Volume buttons shortcut"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 71a8ad7..f08894f 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starting <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Back"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Keyboard Shortcuts"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Switch input method"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assist"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Show with volume controls"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Do not disturb"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Volume buttons shortcut"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 35d0f47..b5a10e1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rechazar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartada."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se descartaron todas las aplicaciones recientes."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Pantalla principal"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recientes"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atrás"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificaciones"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Combinación de teclas"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambiar método de entrada"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicaciones"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistencia"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar con controles de volumen"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"No interrumpir"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Combinación de teclas de botones de volumen"</string>
@@ -582,7 +596,7 @@
     <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>
-    <string name="forced_resizable_info_text" msgid="7591061837558867999">"Es posible que la app no funcione con la función Multiventana"</string>
+    <string name="forced_resizable_info_text" msgid="7591061837558867999">"Es posible que la app no se ejecute con la función Multiventana"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Presiona dos veces para editarla."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Presiona dos veces para agregarlo."</string>
     <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posición <xliff:g id="POSITION">%1$d</xliff:g>. Presiona dos veces para seleccionarla."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a976a9c..d8affc9 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Se ha eliminado <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se han ignorado todas las aplicaciones recientes."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inicio"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recientes"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atrás"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificaciones"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Combinaciones de teclas"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambiar método de introducción"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicaciones"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistencia"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar con controles de volumen"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"No molestar"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Combinación de teclas para los botones de volumen"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index e7bfdff..f18bf05 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rakendusest <xliff:g id="APP">%s</xliff:g> loobumine."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Loobusite rakendusest <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kõikidest hiljutistest rakendustest on loobutud"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Rakenduse <xliff:g id="APP">%s</xliff:g> käivitamine."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g>, <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Märguandest on loobutud."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Avaekraan"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Hiljutised"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tagasi"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Märguanded"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klaviatuuri otseteed"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Sisestusmeetodi vahetamine"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Rakendused"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Abi"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brauser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktid"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-post"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM (kiirsuhtlus)"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muusika"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Kuva koos helitugevuse juhtnuppudega"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Mitte segada"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Helitugevuse nuppude otsetee"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index b9cb78e..575f8749 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Baztertu <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> baztertu da."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Azken aplikazio guztiak baztertu da."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> hasten."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Jakinarazpena baztertu da."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Hasierako pantaila"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Azkenak"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atzera"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Jakinarazpenak"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Lasterbideak"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Aldatu idazketa-metodoa"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikazioak"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Laguntzailea"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Arakatzailea"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktuak"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Helbide elektronikoa"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Istanteko mezularitza"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musika"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Egutegia"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Erakutsi bolumena kontrolatzeko aukerekin"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ez molestatu"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Bolumen-botoietarako lasterbidea"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index af74435..322197e 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"رد کردن <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> نادیده گرفته شد."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"همه برنامه‌های اخیر رد شدند."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> در حال شروع به کار است."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"اعلان ردشد."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"اعلان‌ها"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"میان‌برهای صفحه‌کلید"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"تغییر روش ورودی"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"برنامه‌ها"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"دستیار"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"مرورگر"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"مخاطبین"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"رایانامه"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"پیام فوری"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"موسیقی"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"تقویم"</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>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 3b28199..6db0a3e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hylätään <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> hylättiin."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kaikki viimeisimmät sovellukset on hylätty."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Käynnistetään <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ilmoitus hylätty."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Aloitusnäyttö"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Viimeaikaiset"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Takaisin"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Ilmoitukset"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Pikanäppäimet"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Vaihda syöttötapaa"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Sovellukset"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Apusovellus"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Selain"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Yhteystiedot"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Sähköposti"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Pikaviesti"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiikki"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalenteri"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Näytä äänenvoimakkuuden säätimien yhteydessä"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Älä häiritse"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Äänenvoimakkuuspainikkeiden pikanäppäin"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 2ef24db..89c6826 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Accueil"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Récents"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Précédent"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Raccourcis clavier"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Changer de méthode d\'entrée"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistance"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navigateur"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Courriel"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musique"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Afficher avec les commandes de volume"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne pas déranger"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Raccourci des boutons de volume"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 93d9e14..2f99b94 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> : <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Accueil"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Récents"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Précédent"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifications"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Raccourcis clavier"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Changer le mode de saisie"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applications"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistance"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navigateur"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacts"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Messagerie"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Messagerie instantanée"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musique"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Afficher avec les commandes de volume"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne pas déranger"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Raccourci des boutons de volume"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 86a0bfa..45c3626 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rexeitar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Rexeitouse <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Rexeitáronse todas as aplicacións recentes."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación rexeitada"</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inicio"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Volver"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificacións"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atallos de teclado"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambiar de método de entrada"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicacións"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistente"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar cos controis de volume"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Non molestar"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Atallo dos botóns de volume"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index d52226d..ef6a49c 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> કાઢી નાખો."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> કાઢી નાખી."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"તમામ તાજેતરની એપ્લિકેશનો કાઢી નાખી."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> પ્રારંભ કરી રહ્યું છે."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"સૂચના કાઢી નાખી."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"સૂચનાઓ"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"કીબોર્ડ શૉર્ટકટ્સ"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ઇનપુટ પદ્ધતિ સ્વિચ કરો"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ઍપ્લિકેશનો"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"સહાય"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"બ્રાઉઝર"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"સંપર્કો"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ઇમેઇલ"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"સંગીત"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"કૅલેન્ડર"</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>
diff --git a/packages/SystemUI/res/values-h560dp/config.xml b/packages/SystemUI/res/values-h560dp/config.xml
deleted file mode 100644
index 8b576b9..0000000
--- a/packages/SystemUI/res/values-h560dp/config.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  ~ 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
-  -->
-
-<resources>
-    <!-- The maximum number of items to be displayed in quick settings -->
-    <integer name="quick_settings_detail_max_item_count">6</integer>
-</resources>
-
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 160d4a0..1ba0caf 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> को ख़ारिज करें."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खा़रिज कर दिया गया."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"हाल ही के सभी ऐप्लिकेशन ख़ारिज कर दिए गए."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ हो रहा है."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफिकेशन खारिज की गई."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"नोटिफ़िकेशन"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"कीबोर्ड शॉर्टकट"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"इनपुट पद्धति‍ बदलें"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ऐप्लिकेशन"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"सहायक"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउज़र"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"संपर्क"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ईमेल"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"कैलेंडर"</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>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index ddfcb55..81c6276 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -169,6 +169,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacivanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> odbačena je."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Odbačene su sve nedavne aplikacije."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokretanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavijest je odbačena."</string>
@@ -529,6 +531,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početni zaslon"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Najnovije"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Natrag"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obavijesti"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tipkovni prečaci"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Promjena načina unosa"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoć"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Preglednik"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Izravna poruka"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Glazba"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikaži s kontrolama glasnoće"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne uznemiravaj"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Prečac tipki za glasnoću"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index c026926..b7ac8a4 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"A(z) <xliff:g id="APP">%s</xliff:g> elvetése."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eltávolítva."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Az összes alkalmazás eltávolítva a nemrég használtak közül."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A(z) <xliff:g id="APP">%s</xliff:g> indítása."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Értesítés elvetve."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Otthon"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Legutóbbiak"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Vissza"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Értesítések"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Billentyűkódok"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Beviteli mód váltása"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Alkalmazások"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Segédalkalmazás"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Böngésző"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Névjegyek"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Azonnali üzenetküldés"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Zene"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Naptár"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Megjelenítés hangerőszabályzóval"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne zavarjanak"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"A hangerőgombok gyorsbillentyűk"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index a9d122a..7e4e01a 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Անտեսել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>-ը անտեսված է:"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Բոլոր վերջին հավելվածները հեռացվել են ցուցակից:"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Մեկնարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ծանուցումը անտեսվեց:"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Ծանուցումներ"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Ստեղնային դյուրանցումներ"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Փոխարկել մուտքագրման եղանակը"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Գործադիրներ"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Օգնություն"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Դիտարկիչ"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Կոնտակտներ"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Էլփոստ"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Երաժշտություն"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Օրացույց"</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>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 876034c..2b51426 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Menyingkirkan <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> disingkirkan."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaru telah ditutup."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulai <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifikasi disingkirkan."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Layar Utama"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Terbaru"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Kembali"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifikasi"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Pintasan Keyboard"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Beralih metode masukan"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikasi"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Bantuan"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontak"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Tampilkan dengan kontrol volume"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Jangan ganggu"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Pintasan tombol volume"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 4ce5f54..1dc37df 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hunsa <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> vísað frá."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Öll nýleg forrit fjarlægð."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Ræsir <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Tilkynningu lokað."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Heim"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nýlegt"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Til baka"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Tilkynningar"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Flýtilyklar"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Skipta um innsláttaraðferð"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Forrit"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Aðstoð"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Vafri"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Tengiliðir"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Tölvupóstur"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Spjall"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Tónlist"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Dagatal"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Sýna með hljóðstyrksstillingum"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ónáðið ekki"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Flýtihnappar fyrir hljóðstyrk"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 62c18f2..4a8ba99 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Elimina <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eliminata."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tutte le applicazioni recenti sono state rimosse."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Avvio di <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifica eliminata."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recenti"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Indietro"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notifiche"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Scorciatoie da tastiera"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambia metodo di immissione"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Applicazioni"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistenza"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contatti"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musica"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostra con controlli volume"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Non disturbare"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Pulsanti del volume come scorciatoia"</string>
@@ -585,7 +599,7 @@
     <string name="forced_resizable_info_text" msgid="7591061837558867999">"L\'app potrebbe non funzionare con la modalità multi-finestra"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tocca due volte per modificare."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tocca due volte per aggiungere."</string>
-    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Positione <xliff:g id="POSITION">%1$d</xliff:g>. Tocca due volte per selezionare."</string>
+    <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>. Tocca due volte per selezionare."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Sposta <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Rimuovi <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> è stato aggiunto alla posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 097b427..d41d50d 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -170,6 +170,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"סגור את <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> נדחה."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"כל האפליקציות האחרונות נסגרו."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"מפעיל את <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"הודעה נדחתה."</string>
@@ -530,6 +532,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"הודעות"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"מקשי קיצור במקלדת"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"החלפת שיטת קלט"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"אפליקציות"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"מסייע"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"דפדפן"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"אנשי קשר"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"אימייל"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"שליחת הודעות מיידיות"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"מוזיקה"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"‏YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"יומן"</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>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 61ff6d4..83a9888 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>を削除します。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>は削除されました。"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近のアプリケーションをすべて消去しました。"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>を開始しています。"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知が削除されました。"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"キーボード ショートカット"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"入力方法の切り替え"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"アプリ"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"アシスト"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ブラウザ"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"連絡先"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"メール"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音楽"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"カレンダー"</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>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 26f25293..5008fe0 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-ის უგულებელყოფა."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ამოშლილია სიიდან."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ყველა ბოლო აპლიკაცია გაუქმდა."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> იწყება."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"შეტყობინება წაიშალა."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"შეტყობინებები"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"კლავიატურის მალსახმობები"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"შეყვანის მეთოდის გადართვა"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"აპლიკაციები"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"დახმარება"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ბრაუზერი"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"კონტაქტები"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ელფოსტა"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"მუსიკა"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"კალენდარი"</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>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 737041e..ff33f05 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> қолданбасынан бас тарту."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> алынып тасталған."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Барлық жақындағы қабылданбаған қолданбалар."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> іске қосылуда."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Хабар алынып тасталды."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Хабарландырулар"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Пернелер тіркесімдері"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Енгізу әдісін ауыстыру"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Қолданбалар"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Көмекші"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузер"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контактілер"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Электрондық пошта"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Mузыка"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Күнтізбе"</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>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 1cec0b0..b69f893 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"បោះបង់ <xliff:g id="APP">%s</xliff:g> ។"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"កម្មវិធីថ្មីៗទាំងអស់ត្រូវបានបោះបង់។"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"ចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ។"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"បាន​បដិសេធ​ការ​ជូនដំណឹង"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ការជូនដំណឹង"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ផ្លូវកាត់ក្ដារចុច"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ប្ដូរវិធីសាស្ត្របញ្ចូល"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"កម្មវិធី"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ជំនួយ"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"កម្មវិធីរុករក"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ទំនាក់ទំនង"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"អ៊ីមែល"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"តន្ត្រី"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ប្រតិទិន"</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>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 2eb6141..1ce14dd5 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸು."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ಇತ್ತೀಚಿನ ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ಅಧಿಸೂಚನೆ ವಜಾಗೊಂಡಿದೆ."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ಅಧಿಸೂಚನೆಗಳು"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ಕೀಬೋರ್ಡ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ಇನ್‌ಪುಟ್‌‌ ವಿಧಾನ ಬದಲಿಸಿ"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ಸಹಾಯ ಮಾಡು"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ಬ್ರೌಸರ್"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ಸಂಪರ್ಕಗಳು"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ಇಮೇಲ್"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ಸಂಗೀತ"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ಕ್ಯಾಲೆಂಡರ್"</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>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ae60d0e..a8a2a0a 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>을(를) 숨깁니다."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>이(가) 제거되었습니다."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"최근 사용한 애플리케이션을 모두 닫았습니다."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>을(를) 시작하는 중입니다."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"알림이 제거되었습니다."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"알림"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"단축키"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"입력 방법 전환"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"애플리케이션"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"지원"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"브라우저"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"주소록"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"이메일"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"메신저"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"음악"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"캘린더"</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>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index b035bbb..6a2d77f 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> этибарга албоо."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> жок болду."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Акыркы колдонмолордун баары көз жаздымда калтырылды."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> иштеп баштоодо."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Эскертме жок кылынды."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Эскертмелер"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Баскычтоптун кыска жолдору"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Киргизүү ыкмасын которуштуруу"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Колдонмолор"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Көмөкчү"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Серепчи"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Байланыштар"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Электрондук почта"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Жылнаама"</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>
@@ -582,7 +596,7 @@
     <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>
-    <string name="forced_resizable_info_text" msgid="7591061837558867999">"Көп терезе режиминде колдонмо иштебей калышы мүмкүн"</string>
+    <string name="forced_resizable_info_text" msgid="7591061837558867999">"Бир нече терезе режиминде колдонмо иштебей калышы мүмкүн"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Түзөтүү үчүн эки жолу таптаңыз."</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Кошуу үчүн эки жолу таптаңыз."</string>
     <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>. Тандоо үчүн эки жолу таптаңыз."</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 26a81c8..c40797c 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -24,4 +24,14 @@
 
     <dimen name="docked_divider_handle_width">2dp</dimen>
     <dimen name="docked_divider_handle_height">16dp</dimen>
+
+    <dimen name="qs_tile_margin_top">2dp</dimen>
+    <dimen name="qs_brightness_padding_top">0dp</dimen>
+
+    <dimen name="battery_detail_graph_space_top">9dp</dimen>
+    <dimen name="battery_detail_graph_space_bottom">9dp</dimen>
+
+    <integer name="quick_settings_num_columns">4</integer>
+    <bool name="quick_settings_wide">true</bool>
+    <dimen name="qs_detail_margin_top">0dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 2355a84..601cc2a 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ປິດ <xliff:g id="APP">%s</xliff:g> ໄວ້."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"ປິດ <xliff:g id="APP">%s</xliff:g> ແລ້ວ."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ທຸກ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ບໍ່​ດົນ​ມາ​ນີ້​ຖືກ​ປ່ອຍ​ໄປ."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"ກຳ​ລັງ​ເປີດ <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ປິດການແຈ້ງເຕືອນແລ້ວ."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ການແຈ້ງເຕືອນ"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ປຸ່ມລັດແປ້ນພິມ"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ແອັບພລິເຄຊັນ"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ຕົວຊ່ວຍ"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ໂປຣແກຣມທ່ອງເວັບ"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ລາຍຊື່ຜູ້ຕິດຕໍ່"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ອີເມວ"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ດົນຕີ"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ປະຕິທິນ"</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>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 93c0b69..866abf3 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -170,6 +170,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Atsisakyti <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Atsisakyta programos „<xliff:g id="APP">%s</xliff:g>“."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Atsisakyta visų naujausių programų."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Paleidžiama <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"„<xliff:g id="APP">%1$s</xliff:g>“ <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pranešimo atsisakyta."</string>
@@ -530,6 +532,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Pagrindinis ekranas"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Naujausios veiklos ekranas"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atgal"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Pranešimai"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Spartieji klavišai"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Perjungti įvesties metodą"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Programos"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pagalbinė programa"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Naršyklė"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktai"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"El. paštas"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"TP"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendorius"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Rodyti su garsumo valdikliais"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Netrukdymo režimas"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Garsumo mygtukų spartusis klavišas"</string>
@@ -590,7 +604,7 @@
     <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> padėtis. Dukart palieskite, kad pasirinktumėte."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"Perkelti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Pašalinti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ pridėtas prie <xliff:g id="POSITION">%2$d</xliff:g> pozicijos"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ pridėtas prie <xliff:g id="POSITION">%2$d</xliff:g> padėties"</string>
     <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ pašalintas"</string>
     <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ perkeltas į <xliff:g id="POSITION">%2$d</xliff:g> padėtį"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Sparčiųjų nustatymų redagavimo priemonė."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 0ee306b..9c32b31 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -169,6 +169,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Nerādīt lietotni <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Lietotne <xliff:g id="APP">%s</xliff:g> vairs netiek rādīta."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Visas nesen izmantotās lietojumprogrammas tika noņemtas."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Notiek lietotnes <xliff:g id="APP">%s</xliff:g> palaišana."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Paziņojums netiek rādīts."</string>
@@ -529,6 +531,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Sākums"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Pēdējie"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Atpakaļ"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Paziņojumi"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Īsinājumtaustiņi"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Pārslēgt ievades metodi"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Lietojumprogrammas"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Palīgs"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Pārlūkprogramma"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktpersonas"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pasts"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Tūlītējā ziņojumapmaiņa"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Mūzika"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendārs"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Rādīt ar skaļuma vadīklām"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Netraucēt"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Skaļuma pogu saīsne"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index cfacc43..7f2fc15 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отфрли <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> е отфрлена."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Сите неодамнешни апликации се отфрлени."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Се стартува <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известувањето е отфрлено."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Известувања"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Кратенки на тастатурата"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Префрли метод за внесување"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Апликации"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Помош"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Прелистувач"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Е-пошта"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</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>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index deca898..dfe992c 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> നിരസിക്കുക."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> നിരസിച്ചു."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"അടുത്തിടെയുള്ള എല്ലാ അപ്ലിക്കേഷനും നിരസിച്ചു."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കുന്നു."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"അറിയിപ്പ് നിരസിച്ചു."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"അറിയിപ്പുകൾ"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"കീബോർഡ് കുറുക്കുവഴികൾ"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ടൈപ്പിംഗ് രീതി മാറുക"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"അപ്ലിക്കേഷനുകൾ"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"അസിസ്റ്റ്"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ബ്രൗസർ"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"കോൺടാക്റ്റുകൾ"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ഇമെയിൽ"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"സംഗീതം"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"കലണ്ടർ"</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>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index b701e21..80cb8f2 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -166,6 +166,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-г хаах."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> байхгүй."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Хамгийн сүүлийн бүх програмыг арилгасан байна."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж байна."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Мэдэгдэл хаагдсан."</string>
@@ -526,6 +528,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Мэдэгдэл"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Гарын товчлол"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Оролтын аргыг солих"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Апп"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Дэмжлэг"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Хөтөч"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Харилцагчид"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Имэйл"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Хөгжим"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Хуанли"</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>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 6c6e634..76dfcd5 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> डिसमिस करा."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> डिसमिस केला."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"अलीकडील सर्व अनुप्रयोग डिसमिस झाले."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करीत आहे."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना डिसमिस केल्या."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"सूचना"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"कीबोर्ड शॉर्टकट"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"इनपुट पद्धत स्विच करा"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"अनुप्रयोग"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"सहाय्य"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउझर"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"संपर्क"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ईमेल"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"कॅलेंडर"</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>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 335ff4c..9401198 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ketepikan <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ditolak."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaharu diketepikan."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulakan <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan diketepikan."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Skrin Utama"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Terbaharu"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Kembali"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Pemberitahuan"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Pintasan Papan Kekunci"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Tukar kaedah input"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikasi"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Bantu"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Penyemak imbas"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kenalan"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mel"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzik"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Tunjukkan dengan kawalan kelantangan"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Jangan ganggu"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Pintasan butang kelantangan"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index d309991..6964750 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ကို ပယ်လိုက်ရန်"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ထုတ်ထားသည်။"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"မကြာသေးမီက အပလီကေးရှင်းများအားလုံး ဖယ်ထုတ်ပြီးပါပြီ။"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ကို စတင်နေသည်။"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g><xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"အကြောင်းကြားချက်ကိုဖယ်ရှားပြီး"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"အကြောင်းကြားချက်များ"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ကီးဘုတ် ဖြတ်လမ်းများ"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ထည့်သွင်းမှုနည်းလမ်းကို ပြောင်းလဲပါ"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"အက်ပ်များ"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"အထောက်အကူ"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ဘရောင်ဇာ"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"အဆက်အသွယ်များ"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"အီးမေးလ်"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"အမြန်စာတိုစနစ်"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ပြက္ခဒိန်"</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>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 8a961fc..eed5f36 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Avvis <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> avvist."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle nylig brukte apper er avvist."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starter <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Varselet ble skjult."</string>
@@ -400,7 +402,7 @@
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheten forblir låst til du låser den opp manuelt"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Motta varsler raskere"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"Se dem før du låser opp"</string>
-    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nei, takk"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nei takk"</string>
     <string name="hidden_notifications_setup" msgid="41079514801976810">"Konfigurer"</string>
     <string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="volume_zen_end_now" msgid="3179845345429841822">"Avslutt nå"</string>
@@ -409,7 +411,7 @@
     <string name="screen_pinning_title" msgid="3273740381976175811">"Skjermen er låst"</string>
     <string name="screen_pinning_description" msgid="3577937698406151604">"På denne måten blir skjermen synlig frem til du låser den opp. Trykk og hold inne Tilbake for å låse opp."</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Skjønner"</string>
-    <string name="screen_pinning_negative" msgid="3741602308343880268">"Nei, takk"</string>
+    <string name="screen_pinning_negative" msgid="3741602308343880268">"Nei takk"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
     <string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den vises igjen neste gang du slår den på i innstillingene."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skjul"</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startside"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nylige"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tilbake"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Varsler"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Hurtigtaster"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Bytt inndatametode"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Apper"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assist"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Nettleser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakter"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-post"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musikk"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Vis med volumkontrollene"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ikke forstyrr"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Hurtigtast for volumknappene"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 7e91a53..836dc4b 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> खारेज गर्नुहोस्।"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खारेज गरिएको छ।"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"सबै हालका अनुप्रयोगहरू खारेज गरियो।"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>सुरु गर्दै।"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारेज।"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"सूचनाहरू"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"किबोर्ड सर्टकटहरू"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"इनपुट विधिलाई स्विच गर्नुहोस्"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"अनुप्रयोगहरू"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"सहायता"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउजर"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"सम्पर्कहरू"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"इमेल"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"पात्रो"</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>
@@ -582,7 +596,7 @@
     <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>
-    <string name="forced_resizable_info_text" msgid="7591061837558867999">"अनुप्रयोगले बहु-विन्डोमा काम नगर्न सक्छ"</string>
+    <string name="forced_resizable_info_text" msgid="7591061837558867999">"अनुप्रयोग बहु-विन्डोमा काम नगर्न सक्छ"</string>
     <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। सम्पादन गर्नका लागि डबल ट्याप गर्नुहोस्।"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। थप्नका लागि डबल ट्याप गर्नुहोस्।"</string>
     <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>। चयन गर्नका लागि डबल ट्याप गर्नुहोस्।"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 3cad1fa..41075e3 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> sluiten."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwijderd."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle recente apps gesloten."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> starten."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Melding verwijderd."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startpagina"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recent"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Terug"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Meldingen"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Sneltoetsen"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Invoermethode schakelen"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Apps"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistentie"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contacten"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Chat"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muziek"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Weergeven met volumeknoppen"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Niet storen"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Volumeknoppen als sneltoets"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 91baa9b..1703a2f 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਰੱਦ ਕਰੋ।"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ਰੱਦ ਕੀਤਾ।"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ਸਾਰੀਆਂ ਹਾਲੀਆ ਐਪਲੀਕੇਸ਼ਨਾਂ ਰੱਦ ਕੀਤੀਆਂ।"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ।"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ਸੂਚਨਾ ਰੱਦ ਕੀਤੀ।"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"ਸੂਚਨਾਵਾਂ"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ਵਾਪਸ ਇਨਪੁੱਟ ਵਿਧੀ \'ਤੇ ਬਦਲੋ"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ਐਪਲੀਕੇਸ਼ਨਾਂ"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"ਸਹਾਇਕ"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ਬ੍ਰਾਊਜ਼ਰ"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"ਸੰਪਰਕ"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ਈਮੇਲ"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"ਸੰਗੀਤ"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ਕੈਲੰਡਰ"</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>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3aed4b2..297b849 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -170,6 +170,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Usuń stąd <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>: zamknięto."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Wszystkie ostatnie aplikacje zostały zamknięte."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Uruchamiam <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Zamknięto powiadomienie."</string>
@@ -530,6 +532,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ekran główny"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Ostatnie"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Wstecz"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Powiadomienia"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Skróty klawiszowe"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Przełącz metodę wprowadzania"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacje"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoc"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Przeglądarka"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakty"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Komunikator"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzyka"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendarz"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Pokazuj z regulacją głośności"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nie przeszkadzać"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Wł./wył. przyciskami głośności"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 055a2981..eb08d99 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Início"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Voltar"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificações"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atalhos do teclado"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Alterar o método de entrada"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicativos"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistente"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contatos"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Mensagens instantâneas"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar com controles de volume"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Não perturbe"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Atalho de botões de volume"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index f40c7c7..bba2f3e 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ignorado."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todas as aplicações recentes foram ignoradas."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A iniciar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação ignorada."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Página inicial"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Anterior"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificações"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atalhos de teclado"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Alternar o método de introdução"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicações"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistência"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendário"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar com controlos de volume"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Não incomodar"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Atalho dos botões de volume"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 055a2981..eb08d99 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Início"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Voltar"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificações"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atalhos do teclado"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Alterar o método de entrada"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicativos"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Assistente"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contatos"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Mensagens instantâneas"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Agenda"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar com controles de volume"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Não perturbe"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Atalho de botões de volume"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index a307698..81d0456 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -169,6 +169,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Închideți <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> a fost eliminată."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toate aplicațiile recente au fost închise."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Se inițiază <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificarea a fost închisă."</string>
@@ -529,6 +531,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ecran de pornire"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recente"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Înapoi"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificări"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Comenzi rapide de la tastatură"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Comutați metoda de introducere a textului"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicații"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistent"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Agendă"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzică"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Afișează cu comenzile de volum"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nu deranja"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Comandă rapidă din butoanele de volum"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 5521664..86f0ec4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -170,6 +170,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Удаление приложения <xliff:g id="APP">%s</xliff:g> из списка."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" удалено из списка."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Все недавние приложения закрыты."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск приложения <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Уведомление закрыто"</string>
@@ -514,8 +516,8 @@
     <string name="keyboard_key_backspace" msgid="1559580097512385854">"Backspace"</string>
     <string name="keyboard_key_media_play_pause" msgid="3861975717393887428">"Воспроизведение/пауза"</string>
     <string name="keyboard_key_media_stop" msgid="2859963958595908962">"Стоп"</string>
-    <string name="keyboard_key_media_next" msgid="1894394911630345607">"Далее"</string>
-    <string name="keyboard_key_media_previous" msgid="4256072387192967261">"Назад"</string>
+    <string name="keyboard_key_media_next" msgid="1894394911630345607">"Следующий трек"</string>
+    <string name="keyboard_key_media_previous" msgid="4256072387192967261">"Предыдущий трек"</string>
     <string name="keyboard_key_media_rewind" msgid="2654808213360820186">"Перемотка назад"</string>
     <string name="keyboard_key_media_fast_forward" msgid="3849417047738200605">"Перемотка вперед"</string>
     <string name="keyboard_key_page_up" msgid="5654098530106845603">"Page Up"</string>
@@ -525,11 +527,23 @@
     <string name="keyboard_key_move_end" msgid="5901174332047975247">"End"</string>
     <string name="keyboard_key_insert" msgid="8530501581636082614">"Insert"</string>
     <string name="keyboard_key_num_lock" msgid="5052537581246772117">"Num Lock"</string>
-    <string name="keyboard_key_numpad_template" msgid="8729216555174634026">"Цифровая клавиатура <xliff:g id="NAME">%1$s</xliff:g>"</string>
+    <string name="keyboard_key_numpad_template" msgid="8729216555174634026">"<xliff:g id="NAME">%1$s</xliff:g> на цифровой панели"</string>
     <string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"Система"</string>
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Уведомления"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Быстрые клавиши"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Сменить способ ввода"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Приложения"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Помощник"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузер"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакты"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Эл. почта"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Чат"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка."</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календарь"</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>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 61411d6..5a2f849 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ඉවතලන්න."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> අස් කර ඇත."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"සියලුම මෑත යෙඳුම් අස් කරන ලදි."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කරමින්."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"දැනුම්දීම නිෂ්ප්‍රභා කරඇත."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"දැනුම්දීම්"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"යතුරු පුවරු කෙටිමං"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ආදාන ක්‍රමය මාරු කිරීම"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"යෙදුම්"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"සහාය"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"බ්‍රවුසරය"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"සම්බන්ධතා"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ඊ-තැපෑල"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"සංගීතය"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"දින දර්ශනය"</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>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f7967e3..9468fcf 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -170,6 +170,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zrušiť aplikáciu <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikácia <xliff:g id="APP">%s</xliff:g> bola zrušená."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všetky nedávne aplikácie boli odmietnuté."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spúšťa sa aplikácia <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Upozornenie bolo zrušené."</string>
@@ -530,6 +532,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Domovská stránka"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedávne"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Späť"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Upozornenia"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klávesové skratky"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Prepnúť metódu vstupu"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikácie"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomocná aplikácia"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Prehliadač"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakty"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Okamžité správy"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Hudba"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendár"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Zobrazovať s ovládacími prvkami hlasitosti"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nerušiť"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Skratka tlačidiel hlasitosti"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f0b7bc7..c5a43f9 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -170,6 +170,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Opusti aplikacijo <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je bila odstranjena."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Vse nedavne aplikacije so bile opuščene."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Zaganjanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obvestilo je bilo odstranjeno."</string>
@@ -530,6 +532,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Začetni zaslon"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazaj"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obvestila"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Bližnjične tipke"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Preklop načina vnosa"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoč"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brskalnik"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Stiki"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Neposredno sporočanje"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Glasba"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Koledar"</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_dnd_silent" msgid="4363882330723050727">"Bližnjica z gumboma za glasnost"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 893e471..0188e5b 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Largo <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> është hequr."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Të gjitha aplikacionet e fundit u larguan."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Po nis <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Njoftimi është hequr."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Kreu"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Të fundit"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Prapa"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Njoftimet"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Shkurtoret e tastierës"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Ndërro metodën e hyrjes"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacionet"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistenti"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Shfletuesi"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktet"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Mail-i"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Mesazh i çastit"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzikë"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendari"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Shfaq me kontrollet e volumit"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Mos shqetëso"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Shkurtorja e butonave të volumit"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 6cfd7b0..501a3e3 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -169,6 +169,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Одбаците <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Апликација <xliff:g id="APP">%s</xliff:g> је одбачена."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Све недавно коришћене апликације су одбачене."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Покрећемо <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Обавештење је одбачено."</string>
@@ -529,6 +531,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Обавештења"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Тастерске пречице"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Промени метод уноса"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Апликације"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Апликација за помоћ"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Прегледач"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Имејл"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Размена тренутних порука"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</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>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6b1e949..959128e 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ta bort <xliff:g id="APP">%s</xliff:g> från listan."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> togs bort permanent."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alla appar har tagits bort från listan Senaste."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Startar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Meddelandet ignorerades."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Startsida"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Senaste"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Tillbaka"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Aviseringar"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Kortkommandon"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Byt inmatningsmetod"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Appar"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Hjälp"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Webbläsare"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakter"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-post"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Snabbmeddelanden"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musik"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalender"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Visa med volymkontroller"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Stör ej"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Genväg till volymknappar"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 5acf6c0..4b936c9 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ondoa <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> imeondolewa."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Programu za hivi majuzi zimeondolewa."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Inaanzisha <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Arifa imetupwa."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Mwanzo"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Zilizotumika majuzi"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nyuma"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Arifa"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Mikato ya Kibodi"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Badilisha mbinu ya kuingiza data"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Programu"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Programu ya maagizo ya sauti"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Kivinjari"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Anwani"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Barua pepe"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Ujumbe wa papo kwa papo"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muziki"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalenda"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Onyesha katika vidhibiti vya sauti"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Usinisumbue"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Njia ya mkato ya vitufe vya sauti"</string>
diff --git a/packages/SystemUI/res/values-sw410dp/config.xml b/packages/SystemUI/res/values-sw410dp/config.xml
new file mode 100644
index 0000000..08b2f88
--- /dev/null
+++ b/packages/SystemUI/res/values-sw410dp/config.xml
@@ -0,0 +1,24 @@
+<?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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <integer name="quick_settings_num_rows">2</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-sw410dp/dimens.xml b/packages/SystemUI/res/values-sw410dp/dimens.xml
new file mode 100644
index 0000000..5ce6524
--- /dev/null
+++ b/packages/SystemUI/res/values-sw410dp/dimens.xml
@@ -0,0 +1,24 @@
+<?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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <dimen name="qs_detail_items_padding_top">16dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-sw540dp/config.xml b/packages/SystemUI/res/values-sw540dp/config.xml
new file mode 100644
index 0000000..e554fc6d
--- /dev/null
+++ b/packages/SystemUI/res/values-sw540dp/config.xml
@@ -0,0 +1,24 @@
+<?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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <integer name="quick_settings_num_rows">3</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index 4ed15d5..49a7a29 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -40,4 +40,8 @@
 
     <dimen name="battery_detail_graph_space_top">27dp</dimen>
     <dimen name="battery_detail_graph_space_bottom">27dp</dimen>
+
+    <dimen name="qs_tile_margin_top">16dp</dimen>
+    <dimen name="qs_brightness_padding_top">6dp</dimen>
+    <dimen name="qs_detail_margin_top">28dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 1c2f0de..5489be9 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ஐ நிராகரி."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> விலக்கப்பட்டது."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"எல்லா சமீபத்திய பயன்பாடுகளும் விலக்கப்பட்டன."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ஐத் தொடங்குகிறது."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"அறிவிப்பு நிராகரிக்கப்பட்டது."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"அறிவிப்புகள்"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"விசைப்பலகைக் குறுக்குவழிகள்"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"உள்ளீட்டு முறையை மாற்று"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"பயன்பாடுகள்"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"அசிஸ்ட்"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"உலாவி"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"தொடர்புகள்"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"மின்னஞ்சல்"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"மியூசிக்"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"கேலெண்டர்"</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>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index bbefad2..3a72809 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ని తీసివేయండి."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> తీసివేయబడింది."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"అన్ని ఇటీవలి అనువర్తనాలు తీసివేయబడ్డాయి."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభిస్తోంది."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"నోటిఫికేషన్ తీసివేయబడింది."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"నోటిఫికేషన్‌లు"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"కీబోర్డ్ సత్వరమార్గాలు"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"ఇన్‌పుట్ పద్ధతిని మార్చండి"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"అనువర్తనాలు"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"సహాయకం"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"బ్రౌజర్"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"పరిచయాలు"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ఇమెయిల్"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"సంగీతం"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"క్యాలెండర్"</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>
@@ -588,8 +602,8 @@
     <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>. ఎంచుకోవడానికి రెండుసార్లు నొక్కండి."</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ని తరలిస్తుంది"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ని తీసివేస్తుంది"</string>
-    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> స్థానం <xliff:g id="POSITION">%2$d</xliff:g>కి జోడించబడింది"</string>
+    <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>వ స్థానానికి జోడించబడింది"</string>
     <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> తీసివేయబడింది"</string>
-    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> స్థానం <xliff:g id="POSITION">%2$d</xliff:g>కి తరలించబడింది"</string>
+    <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>వ స్థానానికి తరలించబడింది"</string>
     <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"శీఘ్ర సెట్టింగ్‌ల ఎడిటర్."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 809d425..4844c84 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ยกเลิก <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ถูกลบไปแล้ว"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ปิดแอปพลิเคชันล่าสุดทั้งหมดแล้ว"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"กำลังเริ่มต้น <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ปิดการแจ้งเตือนแล้ว"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"การแจ้งเตือน"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"แป้นพิมพ์ลัด"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"สลับวิธีการป้อนข้อมูล"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"แอปพลิเคชัน"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"การสนับสนุน"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"เบราว์เซอร์"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"รายชื่อติดต่อ"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"อีเมล"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"เพลง"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ปฏิทิน"</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>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 7e6ff8a..0672959 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"I-dismiss ang <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Hindi pinansin ang <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Na-dismiss ang lahat ng kamakailang application."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Sinisimulan ang <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Na-dismiss ang notification."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Home"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Mga Kamakailang Ginamit"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Bumalik"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Mga Notification"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Mga Keyboard Shortcut"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Magpalit ng pamamaraan ng pag-input"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Mga Application"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Tulong"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Mga Contact"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendaryo"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Ipakita nang may mga kontrol ng volume"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Huwag istorbohin"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Shortcut ng mga button ng volume"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 05621a5..58d488c 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> uygulamasını kapat."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> kaldırıldı."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tüm son uygulamalar kapatıldı."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> başlatılıyor."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildirim kapatıldı."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ana ekran"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Son çağrılar"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Geri"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Bildirimler"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Klavye Kısayolları"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Giriş yöntemini değiştir"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Uygulamalar"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asist"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Tarayıcı"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kişiler"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-posta"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Müzik"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Takvim"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Ses seviyesi kontrolleriyle göster"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Rahatsız etmeyin"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Ses düğmeleri kısayolu"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index ac79649..c75891c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -170,6 +170,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Видалити додаток <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Програму <xliff:g id="APP">%s</xliff:g> закрито."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усі останні додатки закрито."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск додатка <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Сповіщення відхилено."</string>
@@ -530,6 +532,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Сповіщення"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Комбінації клавіш"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Змінити метод введення"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Додатки"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Помічник"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Веб-переглядач"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакти"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Електронна пошта"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Чат"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музика"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календар"</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>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index a4a664b..807a923 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> کو مسترد کریں۔"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> کو ہٹا دیا گیا۔"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"سبھی حالیہ ایپلیکیشنز کو برخاست کر دیا گیا۔"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> شروع ہو رہی ہے۔"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"اطلاع مسترد ہوگئی۔"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"اطلاعات"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"کی بورڈ شارٹ کٹس"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"اندراج کا طریقہ سوئچ کریں"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ایپلیکیشنز"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"اسسٹ"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"براؤزر"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"رابطے"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ای میل"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"موسیقی"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"کیلنڈر"</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>
@@ -591,5 +605,5 @@
     <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="POSITION">%2$d</xliff:g> پوزیشن پر <xliff:g id="TILE_NAME">%1$s</xliff:g> شامل ہو گیا ہے"</string>
     <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ہٹا دیا گیا"</string>
     <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="POSITION">%2$d</xliff:g> پوزیشن پر <xliff:g id="TILE_NAME">%1$s</xliff:g> منتقل ہو گیا ہے"</string>
-    <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"فوری ترتیبات ایڈیٹر۔"</string>
+    <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"فوری ترتیبات کا ایڈیٹر۔"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index f5bcc3d..fe67b52 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Olib tashlash: <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> olib tashlangan."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Yaqinda ishlatilgan barcha ilovalar olib tashlandi."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ishga tushirilmoqda."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Xabarnoma e‘tiborsiz qoldirildi."</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Bildirishnomalar"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Tezkor tugmalar"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Matn kiritish usulini o‘zgartirish"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Ilovalar"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Yordamchi"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Brauzer"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktlar"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pochta"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musiqa"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Taqvim"</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 tugmalari"</string>
@@ -563,7 +577,7 @@
     <string name="select_keycode" msgid="7413765103381924584">"Klaviatura tugmasini tanlang"</string>
     <string name="preview" msgid="9077832302472282938">"Oldindan ko‘rish"</string>
     <string name="drag_to_add_tiles" msgid="7058945779098711293">"Fragmentlar qo‘shish uchun torting"</string>
-    <string name="drag_to_remove_tiles" msgid="3361212377437088062">"O‘chirish uchun bu yerga sudrang"</string>
+    <string name="drag_to_remove_tiles" msgid="3361212377437088062">"O‘chirish uchun bu yerga torting"</string>
     <string name="qs_edit" msgid="2232596095725105230">"Tahrirlash"</string>
     <string name="tuner_time" msgid="6572217313285536011">"Vaqt"</string>
   <string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index ed3e8f3..ca7c59b 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Xóa bỏ <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> đã bị loại bỏ."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Đã bỏ qua tất cả các ứng dụng gần đây."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Bắt đầu <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Đã loại bỏ thông báo."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Màn hình chính"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Gần đây"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Quay lại"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Thông báo"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Phím tắt"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Chuyển phương thức nhập"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Ứng dụng"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Trợ lý"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Trình duyệt"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Danh bạ"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Email"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Nhắn tin nhanh"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Âm nhạc"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Lịch"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Hiển thị với các điều khiển âm lượng"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Không làm phiền"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Phím tắt các nút âm lượng"</string>
diff --git a/packages/SystemUI/res/values-w550dp-land/dimens.xml b/packages/SystemUI/res/values-w550dp-land/dimens.xml
index cd17bed..4160c83 100644
--- a/packages/SystemUI/res/values-w550dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-w550dp-land/dimens.xml
@@ -20,7 +20,4 @@
     <dimen name="notification_panel_width">544dp</dimen>
 
     <dimen name="qs_expand_margin">32dp</dimen>
-
-    <dimen name="battery_detail_graph_space_top">9dp</dimen>
-    <dimen name="battery_detail_graph_space_bottom">9dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 3b0c023..a25b9f1 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -34,14 +34,14 @@
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"电池电量偏低"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>。节电助手已开启。"</string>
+    <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>。省电模式已开启。"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"不支持USB充电功能。\n只能使用随附的充电器充电。"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"不支持USB充电。"</string>
     <string name="invalid_charger_text" msgid="5474997287953892710">"仅限使用设备随附的充电器。"</string>
     <string name="battery_low_why" msgid="4553600287639198111">"设置"</string>
-    <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"要开启节电助手吗?"</string>
+    <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"要开启省电模式吗?"</string>
     <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"开启"</string>
-    <string name="battery_saver_start_action" msgid="5576697451677486320">"开启节电助手"</string>
+    <string name="battery_saver_start_action" msgid="5576697451677486320">"开启省电模式"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"设置"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自动旋转屏幕"</string>
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"移除<xliff:g id="APP">%s</xliff:g>。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"已删除<xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"已关闭所有最近用过的应用。"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在启动<xliff:g id="APP">%s</xliff:g>。"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"已关闭通知。"</string>
@@ -371,9 +373,9 @@
     <string name="user_remove_user_title" msgid="4681256956076895559">"是否移除用户?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"此用户的所有应用和数据均将被删除。"</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"移除"</string>
-    <string name="battery_saver_notification_title" msgid="237918726750955859">"节电助手已开启"</string>
+    <string name="battery_saver_notification_title" msgid="237918726750955859">"省电模式已开启"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"降低性能并限制后台流量"</string>
-    <string name="battery_saver_notification_action_text" msgid="109158658238110382">"关闭节电助手"</string>
+    <string name="battery_saver_notification_action_text" msgid="109158658238110382">"关闭省电模式"</string>
     <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>将开始截取您的屏幕上显示的所有内容。"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"不再显示"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"全部清除"</string>
@@ -495,8 +497,8 @@
     <string name="color_revert_title" msgid="4746666545480534663">"确认设置"</string>
     <string name="color_revert_message" msgid="9116001069397996691">"部分颜色设置可能会导致此设备无法使用。请点击“确定”确认这些颜色设置,否则,系统将在 10 秒后重置这些设置。"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"电池使用情况"</string>
-    <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充电过程中无法使用节电助手"</string>
-    <string name="battery_detail_switch_title" msgid="6285872470260795421">"节电助手"</string>
+    <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充电过程中无法使用省电模式"</string>
+    <string name="battery_detail_switch_title" msgid="6285872470260795421">"省电模式"</string>
     <string name="battery_detail_switch_summary" msgid="9049111149407626804">"降低性能并限制后台流量"</string>
     <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g>按钮"</string>
     <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"键盘快捷键"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"切换输入法"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"应用"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"辅助应用"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"浏览器"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"通讯录"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"电子邮件"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即时通讯"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音乐"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日历"</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>
@@ -583,7 +597,7 @@
     <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"左移"</string>
     <string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"右移"</string>
     <string name="forced_resizable_info_text" msgid="7591061837558867999">"应用可能无法在多窗口模式下正常运行"</string>
-    <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。点按再次即可修改。"</string>
+    <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。点按两次即可修改。"</string>
     <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。点按两次即可添加。"</string>
     <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"位置 <xliff:g id="POSITION">%1$d</xliff:g>。点按两次即可选择。"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"移动<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
@@ -591,5 +605,5 @@
     <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"已将<xliff:g id="TILE_NAME">%1$s</xliff:g>添加到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"已移除<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"已将<xliff:g id="TILE_NAME">%1$s</xliff:g>移至位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快速设置编辑器。"</string>
+    <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快捷设置编辑器。"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index dc4a6dd..083cd5e 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"所有最近使用的應用程式均已關閉。"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g><xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知已關閉。"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"鍵盤快速鍵"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"切換輸入法"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"應用程式"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"輔助"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"瀏覽器"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"通訊錄"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"電郵"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即時通訊"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音樂"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日曆"</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>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 72ff27c8b..3c95a93 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近使用的應用程式已全部關閉。"</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"已關閉通知。"</string>
@@ -528,6 +530,18 @@
     <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="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"鍵盤快速鍵"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"切換輸入法"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"應用程式"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"小幫手"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"瀏覽器"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"聯絡人"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"電子郵件"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即時訊息"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音樂"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日曆"</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>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 2eb9681..e03e642 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -168,6 +168,8 @@
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Cashisa i-<xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ivaliwe."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Zonke izinhlelo zokusebenza zakamuva zicashisiwe."</string>
+    <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
+    <skip />
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iqala i-<xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Isaziso sichithiwe."</string>
@@ -528,6 +530,18 @@
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ekhaya"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Okwakamuva"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Emuva"</string>
+    <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Izaziso"</string>
+    <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Izinqamulelo Zekhibhodi"</string>
+    <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Shintsha indlela yokufaka"</string>
+    <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Izinhlelo zokusebenza"</string>
+    <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Siza"</string>
+    <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Isiphequluli"</string>
+    <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Oxhumana nabo"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"I-imeyili"</string>
+    <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"I-IM"</string>
+    <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Umculo"</string>
+    <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"I-YouTube"</string>
+    <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Ikhalenda"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Bonisa ngezilawuli zevolomu"</string>
     <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ungaphazamisi"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Izinqamuleli zezinkinobho zevolomu"</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 1e979fd..6dd8c52 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -97,5 +97,9 @@
     <declare-styleable name="DensityContainer">
         <attr name="android:layout" />
     </declare-styleable>
+
+    <declare-styleable name="AutoSizingList">
+        <attr name="itemHeight" format="dimension" />
+    </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index b9aa26b..b874e7c 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -169,6 +169,8 @@
     <color name="ksh_system_group_color">#ff00bcd4</color>
     <color name="ksh_application_group_color">#fff44336</color>
     <color name="ksh_keyword_color">#d9000000</color>
+    <color name="ksh_key_item_color">@color/material_grey_600</color>
+    <color name="ksh_key_item_background">#eeeeee</color>
 
     <!-- Background color of edit overflow -->
     <color name="qs_edit_overflow_bg">#455A64</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index fd051b1..42798a4 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -92,11 +92,8 @@
     <!-- The number of columns in the QuickSettings -->
     <integer name="quick_settings_num_columns">3</integer>
 
-    <!-- The maximum number of rows in the QuickSettings -->
-    <integer name="quick_settings_max_rows">4</integer>
-
-    <!-- The maximum number of rows in the QuickSettings when on the keyguard -->
-    <integer name="quick_settings_max_rows_keyguard">3</integer>
+    <!-- The number of rows in the QuickSettings -->
+    <integer name="quick_settings_num_rows">1</integer>
 
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">1</integer>
@@ -116,9 +113,6 @@
     <integer name="quick_settings_brightness_dialog_short_timeout">2000</integer>
     <integer name="quick_settings_brightness_dialog_long_timeout">4000</integer>
 
-    <!-- The maximum number of items to be displayed in quick settings -->
-    <integer name="quick_settings_detail_max_item_count">5</integer>
-
     <!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
     <bool name="config_show4GForLTE">true</bool>
 
@@ -178,7 +172,7 @@
     <!-- Recents: The relative range of visible tasks from the current scroll position
          while the stack is focused. -->
     <item name="recents_layout_focused_range_min" format="float" type="integer">-3</item>
-    <item name="recents_layout_focused_range_max" format="float" type="integer">3</item>
+    <item name="recents_layout_focused_range_max" format="float" type="integer">2</item>
 
     <!-- Recents: The relative range of visible tasks from the current scroll position
          while the stack is not focused. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c094da9..a4eadbf 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -172,6 +172,7 @@
 
     <dimen name="qs_tile_height">88dp</dimen>
     <dimen name="qs_tile_margin">16dp</dimen>
+    <dimen name="qs_tile_margin_top">16dp</dimen>
     <dimen name="qs_quick_tile_size">48dp</dimen>
     <dimen name="qs_quick_tile_padding">12dp</dimen>
     <dimen name="qs_date_anim_translation">32dp</dimen>
@@ -201,10 +202,12 @@
     <dimen name="qs_detail_item_primary_text_size">16sp</dimen>
     <dimen name="qs_detail_item_secondary_text_size">14sp</dimen>
     <dimen name="qs_detail_empty_text_size">14sp</dimen>
+    <dimen name="qs_detail_margin_top">28dp</dimen>
     <dimen name="qs_data_usage_text_size">14sp</dimen>
     <dimen name="qs_data_usage_usage_text_size">36sp</dimen>
     <dimen name="qs_expand_margin">0dp</dimen>
     <dimen name="qs_battery_padding">2dp</dimen>
+    <dimen name="qs_detail_items_padding_top">4dp</dimen>
 
     <dimen name="segmented_button_spacing">0dp</dimen>
     <dimen name="borderless_button_radius">2dp</dimen>
@@ -561,6 +564,9 @@
 
     <!-- Keyboard shortcuts helper -->
     <dimen name="ksh_layout_width">@dimen/match_parent</dimen>
+    <dimen name="ksh_item_text_size">14sp</dimen>
+    <dimen name="ksh_item_padding">4dp</dimen>
+    <dimen name="ksh_item_margin_start">4dp</dimen>
 
 <!-- Recents Layout -->
 
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index 953dd65..f536f86 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -38,9 +38,6 @@
     <dimen name="recents_tv_unselected_item_z">6dp</dimen>
     <dimen name="recents_tv_selected_item_z_delta">10dp</dimen>
 
-    <!-- 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>
 
@@ -52,4 +49,14 @@
     <dimen name="recents_tv_dismiss_icon_bottom_margin">1dip</dimen>
     <dimen name="recents_tv_dismiss_text_size">12sp</dimen>
 
+    <!-- Values for PIP in recents -->
+    <dimen name="recents_tv_pip_controls_margin_top">10dp</dimen>
+
+    <!-- Extra space around the PIP and its outline in PIP onboarding activity  -->
+    <dimen name="tv_pip_bounds_space">3dp</dimen>
+    <!-- Extra space around the PIP control button icon to match with the focused circle -->
+    <dimen name="tv_pip_button_icon_padding">5dp</dimen>
+
+    <!-- Values for entering Recents and exiting Recents -->
+    <dimen name="recents_tv_home_recents_shift">125dip</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/integers_tv.xml b/packages/SystemUI/res/values/integers_tv.xml
index 20cd330..6984d5a 100644
--- a/packages/SystemUI/res/values/integers_tv.xml
+++ b/packages/SystemUI/res/values/integers_tv.xml
@@ -17,5 +17,11 @@
     <integer name="item_scale_anim_duration">150</integer>
     <integer name="dismiss_short_duration">200</integer>
     <integer name="dismiss_long_duration">400</integer>
+
     <integer name="recents_tv_pip_focus_anim_duration">200</integer>
+
+    <!-- Duration for how long it takes cards to slide in or out when going to and from recents. -->
+    <integer name="recents_home_duration">400</integer>
+    <!-- Delay between the start of slide in animation for each card. -->
+    <integer name="recents_home_delay">40</integer>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a523a41..060e050 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -417,6 +417,8 @@
     <string name="accessibility_recents_item_dismissed"><xliff:g id="app" example="Calendar">%s</xliff:g> dismissed.</string>
     <!-- Content description to tell the user all applications has been removed from recents -->
     <string name="accessibility_recents_all_items_dismissed">All recent applications dismissed.</string>
+    <!-- Content description to tell the user that this button will open application info for an application in recents -->
+    <string name="accessibility_recents_item_open_app_info">Open <xliff:g id="app" example="Calendar">%s</xliff:g> application info.</string>
     <!-- Content description to tell the user an application has been launched from recents -->
     <string name="accessibility_recents_item_launched">Starting <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
     <!-- Content description of individual recents task. -->
@@ -1388,6 +1390,31 @@
     <string name="keyboard_shortcut_group_system_recents">Recents</string>
     <!-- User visible title for the the keyboard shortcut that triggers the back action. -->
     <string name="keyboard_shortcut_group_system_back">Back</string>
+    <!-- User visible title for the the keyboard shortcut that triggers the notification shade. -->
+    <string name="keyboard_shortcut_group_system_notifications">Notifications</string>
+    <!-- User visible title for the the keyboard shortcut that triggers the keyboard shortcuts helper. -->
+    <string name="keyboard_shortcut_group_system_shortcuts_helper">Keyboard Shortcuts</string>
+    <!-- User visible title for the the keyboard shortcut that switches input methods. -->
+    <string name="keyboard_shortcut_group_system_switch_input">Switch input method</string>
+
+    <!-- User visible title for the system-wide applications keyboard shortcuts list. -->
+    <string name="keyboard_shortcut_group_applications">Applications</string>
+    <!-- User visible title for the keyboard shortcut that takes the user to the assist app. -->
+    <string name="keyboard_shortcut_group_applications_assist">Assist</string>
+    <!-- User visible title for the keyboard shortcut that takes the user to the browser app. -->
+    <string name="keyboard_shortcut_group_applications_browser">Browser</string>
+    <!-- User visible title for the keyboard shortcut that takes the user to the contacts app. -->
+    <string name="keyboard_shortcut_group_applications_contacts">Contacts</string>
+    <!-- User visible title for the keyboard shortcut that takes the user to the email app. -->
+    <string name="keyboard_shortcut_group_applications_email">Email</string>
+    <!-- User visible title for the keyboard shortcut that takes the user to the instant messaging app. -->
+    <string name="keyboard_shortcut_group_applications_im">IM</string>
+    <!-- User visible title for the keyboard shortcut that takes the user to the music app. -->
+    <string name="keyboard_shortcut_group_applications_music">Music</string>
+    <!-- User visible title for the keyboard shortcut that takes the user to the YouTube app. -->
+    <string name="keyboard_shortcut_group_applications_youtube">YouTube</string>
+    <!-- User visible title for the keyboard shortcut that takes the user to the calendar app. -->
+    <string name="keyboard_shortcut_group_applications_calendar">Calendar</string>
 
     <!-- SysUI Tuner: Option to show full do not disturb panel in volume [CHAR LIMIT=60] -->
     <string name="tuner_full_zen_title">Show with volume controls</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2b134af..5db35b1 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -180,6 +180,11 @@
         <item name="android:textColor">@color/data_usage_secondary</item>
     </style>
 
+    <style name="TextAppearance.QS.TileLabel">
+        <item name="android:textSize">@dimen/qs_tile_text_size</item>
+        <item name="android:fontFamily">sans-serif-condensed</item>
+    </style>
+
     <style name="BaseBrightnessDialogContainer">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index aa3f6e5..d12ab29 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -514,7 +514,7 @@
         if (canBeExpanded) {
             if (DEBUG) Log.d(TAG, "working on an expandable child");
             mNaturalHeight = mScaler.getNaturalHeight();
-            mSmallSize = v.getMinExpandHeight();
+            mSmallSize = v.getCollapsedHeight();
         } else {
             if (DEBUG) Log.d(TAG, "working on a non-expandable child");
             mNaturalHeight = mOldHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/ResizingSpace.java b/packages/SystemUI/src/com/android/systemui/ResizingSpace.java
new file mode 100644
index 0000000..c2bc53e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ResizingSpace.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 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.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+
+public class ResizingSpace extends View {
+
+    private final int mWidth;
+    private final int mHeight;
+
+    public ResizingSpace(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        if (getVisibility() == VISIBLE) {
+            setVisibility(INVISIBLE);
+        }
+        TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.ViewGroup_Layout);
+        mWidth = a.getResourceId(android.R.styleable.ViewGroup_Layout_layout_width, 0);
+        mHeight = a.getResourceId(android.R.styleable.ViewGroup_Layout_layout_height, 0);
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        LayoutParams params = getLayoutParams();
+        boolean changed = false;
+        if (mWidth > 0) {
+            int width = getContext().getResources().getDimensionPixelOffset(mWidth);
+            if (width != params.width) {
+                params.width = width;
+                changed = true;
+            }
+        }
+        if (mHeight > 0) {
+            int height = getContext().getResources().getDimensionPixelOffset(mHeight);
+            if (height != params.height) {
+                params.height = height;
+                changed = true;
+            }
+        }
+        if (changed) {
+            setLayoutParams(params);
+        }
+    }
+
+    /**
+     * Draw nothing.
+     *
+     * @param canvas an unused parameter.
+     */
+    @Override
+    public void draw(Canvas canvas) {
+    }
+
+    /**
+     * Compare to: {@link View#getDefaultSize(int, int)}
+     * If mode is AT_MOST, return the child size instead of the parent size
+     * (unless it is too big).
+     */
+    private static int getDefaultSize2(int size, int measureSpec) {
+        int result = size;
+        int specMode = MeasureSpec.getMode(measureSpec);
+        int specSize = MeasureSpec.getSize(measureSpec);
+
+        switch (specMode) {
+            case MeasureSpec.UNSPECIFIED:
+                result = size;
+                break;
+            case MeasureSpec.AT_MOST:
+                result = Math.min(size, specSize);
+                break;
+            case MeasureSpec.EXACTLY:
+                result = specSize;
+                break;
+        }
+        return result;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        setMeasuredDimension(
+                getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),
+                getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 8f79bda..e838191 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -325,10 +325,11 @@
     /**
      * @param view The view to be dismissed
      * @param velocity The desired pixels/second speed at which the view should move
+     * @param useAccelerateInterpolator Should an accelerating Interpolator be used
      */
-    public void dismissChild(final View view, float velocity) {
+    public void dismissChild(final View view, float velocity, boolean useAccelerateInterpolator) {
         dismissChild(view, velocity, null /* endAction */, 0 /* delay */,
-                velocity == 0 /* useAccelerateInterpolator */, 0 /* fixedDuration */);
+                useAccelerateInterpolator, 0 /* fixedDuration */, false /* isDismissAll */);
     }
 
     /**
@@ -340,17 +341,22 @@
      * @param fixedDuration If not 0, this exact duration will be taken
      */
     public void dismissChild(final View animView, float velocity, final Runnable endAction,
-            long delay, boolean useAccelerateInterpolator, long fixedDuration) {
+            long delay, boolean useAccelerateInterpolator, long fixedDuration,
+            boolean isDismissAll) {
         final boolean canBeDismissed = mCallback.canChildBeDismissed(animView);
         float newPos;
         boolean isLayoutRtl = animView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
 
-        if (velocity < 0
-                || (velocity == 0 && getTranslation(animView) < 0)
-                // if we use the Menu to dismiss an item in landscape, animate up
-                || (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y)
-                // if the language is rtl we prefer swiping to the left
-                || (velocity == 0 && getTranslation(animView) == 0 && isLayoutRtl)) {
+        // if we use the Menu to dismiss an item in landscape, animate up
+        boolean animateUpForMenu = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
+                && mSwipeDirection == Y;
+        // if the language is rtl we prefer swiping to the left
+        boolean animateLeftForRtl = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
+                && isLayoutRtl;
+        boolean animateLeft = velocity < 0
+                || (velocity == 0 && getTranslation(animView) < 0 && !isDismissAll);
+
+        if (animateLeft || animateLeftForRtl || animateUpForMenu) {
             newPos = -getSize(animView);
         } else {
             newPos = getSize(animView);
@@ -569,7 +575,8 @@
                 if (!handleUpEvent(ev, mCurrView, velocity, getTranslation(mCurrView))) {
                     if (isDismissGesture(ev)) {
                         // flingadingy
-                        dismissChild(mCurrView, swipedFastEnough() ? velocity : 0f);
+                        dismissChild(mCurrView, velocity,
+                                !swipedFastEnough() /* useAccelerateInterpolator */);
                     } else {
                         // snappity
                         mCallback.onDragCancelled(mCurrView);
@@ -615,11 +622,9 @@
 
     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);
+        boolean ret = (Math.abs(velocity) > getEscapeVelocity())
+                && (velocity > 0) == (translation > 0);
         return ret;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index b2b6127..455a69f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -123,6 +123,17 @@
         startServicesIfNeeded(SERVICES);
     }
 
+    /**
+     * Ensures that all the Secondary user SystemUI services are running. If they are already
+     * running, this is a no-op. This is needed to conditinally start all the services, as we only
+     * need to have it in the main process.
+     *
+     * <p>This method must only be called from the main thread.</p>
+     */
+    void startSecondaryUserServicesIfNeeded() {
+        startServicesIfNeeded(SERVICES_PER_USER);
+    }
+
     private void startServicesIfNeeded(Class<?>[] services) {
         if (mServicesStarted) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
new file mode 100644
index 0000000..f619bfb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.app.ActivityManager;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Process;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+public class SystemUISecondaryUserService extends Service {
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        ((SystemUIApplication) getApplication()).startSecondaryUserServicesIfNeeded();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
+        if (args == null || args.length == 0) {
+            for (SystemUI ui: services) {
+                pw.println("dumping service: " + ui.getClass().getName());
+                ui.dump(fd, pw, args);
+            }
+        } else {
+            String svc = args[0];
+            for (SystemUI ui: services) {
+                String name = ui.getClass().getName();
+                if (name.endsWith(svc)) {
+                    ui.dump(fd, pw, args);
+                }
+            }
+        }
+    }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index d2c60ef..84d3599 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -115,9 +115,9 @@
         }
 
         @Override // Binder interface
-        public void onFinishedGoingToSleep(int reason) {
+        public void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) {
             checkPermission();
-            mKeyguardViewMediator.onFinishedGoingToSleep(reason);
+            mKeyguardViewMediator.onFinishedGoingToSleep(reason, cameraGestureTriggered);
         }
 
         @Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a5dfc4b..66754a7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -747,7 +747,7 @@
         notifyStartedGoingToSleep();
     }
 
-    public void onFinishedGoingToSleep(int why) {
+    public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) {
         if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + why + ")");
         synchronized (this) {
             mDeviceInteractive = false;
@@ -758,6 +758,16 @@
 
             notifyFinishedGoingToSleep();
 
+            if (cameraGestureTriggered) {
+                Log.i(TAG, "Camera gesture was triggered, preventing Keyguard locking.");
+
+                // Just to make sure, make sure the device is awake.
+                mContext.getSystemService(PowerManager.class).wakeUp(SystemClock.uptimeMillis(),
+                        "com.android.systemui:CAMERA_GESTURE_PREVENT_LOCK");
+                mPendingLock = false;
+                mPendingReset = false;
+            }
+
             if (mPendingReset) {
                 resetStateLocked();
                 mPendingReset = false;
@@ -771,7 +781,7 @@
             // We do not have timeout and power button instant lock setting for profile lock.
             // So we use the personal setting if there is any. But if there is no device
             // we need to make sure we lock it immediately when the screen is off.
-            if (!mLockLater) {
+            if (!mLockLater && !cameraGestureTriggered) {
                 doKeyguardForChildProfilesLocked();
             }
 
@@ -794,7 +804,7 @@
 
         // From DevicePolicyAdmin
         final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
-                .getMaximumTimeToLock(null, userId);
+                .getMaximumTimeToLockForUserAndProfiles(userId);
 
         long timeout;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
new file mode 100644
index 0000000..00e6221
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.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 com.android.systemui.qs;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import com.android.systemui.R;
+
+/**
+ * Similar to a ListView, but it will show only as many items as fit on screen and
+ * bind those instead of scrolling.
+ */
+public class AutoSizingList extends LinearLayout {
+
+    private static final String TAG = "AutoSizingList";
+    private final int mItemSize;
+    private final Handler mHandler;
+
+    private ListAdapter mAdapter;
+    private int mCount;
+
+    public AutoSizingList(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+
+        mHandler = new Handler();
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoSizingList);
+        mItemSize = a.getDimensionPixelSize(R.styleable.AutoSizingList_itemHeight, 0);
+    }
+
+    public void setAdapter(ListAdapter adapter) {
+        if (mAdapter != null) {
+            mAdapter.unregisterDataSetObserver(mDataObserver);
+        }
+        mAdapter = adapter;
+        if (adapter != null) {
+            adapter.registerDataSetObserver(mDataObserver);
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int requestedHeight = MeasureSpec.getSize(heightMeasureSpec);
+        if (requestedHeight != 0) {
+            int count = Math.min(requestedHeight / mItemSize, getDesiredCount());
+            if (mCount != count) {
+                postRebindChildren();
+                mCount = count;
+            }
+        }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    private int getDesiredCount() {
+        return mAdapter != null ? mAdapter.getCount() : 0;
+    }
+
+    private void postRebindChildren() {
+        mHandler.post(mBindChildren);
+    }
+
+    private void rebindChildren() {
+        if (mAdapter == null) {
+            return;
+        }
+        for (int i = 0; i < mCount; i++) {
+            View v = i < getChildCount() ? getChildAt(i) : null;
+            View newView = mAdapter.getView(i, v, this);
+            if (newView != v) {
+                if (v != null) {
+                    removeView(v);
+                }
+                addView(newView, i);
+            }
+        }
+        // Ditch extra views.
+        while (getChildCount() > mCount) {
+            removeViewAt(getChildCount() - 1);
+        }
+    }
+
+    private final Runnable mBindChildren = new Runnable() {
+        @Override
+        public void run() {
+            rebindChildren();
+        }
+    };
+
+    private final DataSetObserver mDataObserver = new DataSetObserver() {
+        @Override
+        public void onChanged() {
+            if (mCount > getDesiredCount()) {
+                mCount = getDesiredCount();
+            }
+            postRebindChildren();
+        }
+
+        @Override
+        public void onInvalidated() {
+            postRebindChildren();
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 115c9d0..5a23610 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -1,6 +1,8 @@
 package com.android.systemui.qs;
 
 import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.support.v4.view.PagerAdapter;
 import android.support.v4.view.ViewPager;
 import android.util.AttributeSet;
@@ -199,11 +201,22 @@
 
         @Override
         public boolean updateResources() {
-            if (super.updateResources()) {
-                mMaxRows = mColumns != 3 ? 2 : 3;
-                return true;
+            final int rows = getRows();
+            boolean changed = rows != mMaxRows;
+            if (changed) {
+                mMaxRows = rows;
+                requestLayout();
             }
-            return false;
+            return super.updateResources() || changed;
+        }
+
+        private int getRows() {
+            final Resources res = getContext().getResources();
+            if (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+                // Always have 3 rows in portrait.
+                return 3;
+            }
+            return Math.max(1, res.getInteger(R.integer.quick_settings_num_rows));
         }
 
         public void setMaxRows(int maxRows) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index de8eec4..4d959d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -157,7 +157,7 @@
         for (QSTile<?> tile : tiles) {
             QSTileBaseView tileView = mQsPanel.getTileView(tile);
             final TextView label = ((QSTileView) tileView).getLabel();
-            final View tileIcon = tileView.getIcon();
+            final View tileIcon = tileView.getIcon().getIconView();
             if (count < mNumQuickTiles && mAllowFancy) {
                 // Quick tiles.
                 QSTileBaseView quickTileView = mQuickQsPanel.getTileView(tile);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index 5d06aeb..e3a4909 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -47,10 +47,10 @@
     private final Rect mQsBounds = new Rect();
 
     private int mHeightOverride = -1;
-    private QSPanel mQSPanel;
+    protected QSPanel mQSPanel;
     private QSDetail mQSDetail;
     protected BaseStatusBarHeader mHeader;
-    private float mQsExpansion;
+    protected float mQsExpansion;
     private boolean mQsExpanded;
     private boolean mHeaderAnimating;
     private boolean mKeyguardShowing;
@@ -100,7 +100,13 @@
         // 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);
+        mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(
+                MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED));
+        int width = mQSPanel.getMeasuredWidth();
+        int height = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin
+                + mQSPanel.getMeasuredHeight();
+        super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
 
         // QSCustomizer is always be the height of the screen, but do this after
         // other measuring to avoid changing the height of the QSContainer.
@@ -156,14 +162,18 @@
     }
 
     private void updateBottom() {
-        int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
-        int height = mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
-                : (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
-                + mHeader.getCollapsedHeight();
+        int height = calculateContainerHeight();
         setBottom(getTop() + height);
         mQSDetail.setBottom(getTop() + height);
     }
 
+    protected int calculateContainerHeight() {
+        int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
+        return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
+                : (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
+                + mHeader.getCollapsedHeight();
+    }
+
     private void updateQsState() {
         boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling || mHeaderAnimating;
         mQSPanel.setExpanded(mQsExpanded);
@@ -296,4 +306,8 @@
             updateQsState();
         }
     };
+
+    public int getQsMinExpansionHeight() {
+        return mHeader.getHeight();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index 25b9105..2dd4a0a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -28,11 +28,10 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.TextView;
-
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 
@@ -45,16 +44,17 @@
 
     private final Context mContext;
     private final H mHandler = new H();
+    private final Adapter mAdapter = new Adapter();
 
     private String mTag;
     private Callback mCallback;
     private boolean mItemsVisible = true;
-    private LinearLayout mItems;
+    private AutoSizingList mItemList;
     private View mEmpty;
-    private View mMinHeightSpacer;
     private TextView mEmptyText;
     private ImageView mEmptyIcon;
-    private int mMaxItems;
+
+    private Item[] mItems;
 
     public QSDetailItems(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -73,27 +73,22 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mItems = (LinearLayout) findViewById(android.R.id.list);
-        mItems.setVisibility(GONE);
+        mItemList = (AutoSizingList) findViewById(android.R.id.list);
+        mItemList.setVisibility(GONE);
+        mItemList.setAdapter(mAdapter);
         mEmpty = findViewById(android.R.id.empty);
         mEmpty.setVisibility(GONE);
         mEmptyText = (TextView) mEmpty.findViewById(android.R.id.title);
         mEmptyIcon = (ImageView) mEmpty.findViewById(android.R.id.icon);
-        mMinHeightSpacer = findViewById(R.id.min_height_spacer);
-
-        // By default, a detail item view has fixed size.
-        mMaxItems = getResources().getInteger(
-                R.integer.quick_settings_detail_max_item_count);
-        setMinHeightInItems(mMaxItems);
     }
 
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         FontSizeUtils.updateFontSize(mEmptyText, R.dimen.qs_detail_empty_text_size);
-        int count = mItems.getChildCount();
+        int count = mItemList.getChildCount();
         for (int i = 0; i < count; i++) {
-            View item = mItems.getChildAt(i);
+            View item = mItemList.getChildAt(i);
             FontSizeUtils.updateFontSize(item, android.R.id.title,
                     R.dimen.qs_detail_item_primary_text_size);
             FontSizeUtils.updateFontSize(item, android.R.id.summary,
@@ -110,16 +105,6 @@
         mEmptyText.setText(text);
     }
 
-    /**
-     * Set the minimum height of this detail view, in item count.
-     */
-    public void setMinHeightInItems(int minHeightInItems) {
-        ViewGroup.LayoutParams lp = mMinHeightSpacer.getLayoutParams();
-        lp.height = minHeightInItems * getResources().getDimensionPixelSize(
-                R.dimen.qs_detail_item_height);
-        mMinHeightSpacer.setLayoutParams(lp);
-    }
-
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -153,65 +138,82 @@
     }
 
     private void handleSetItems(Item[] items) {
-        final int itemCount = items != null ? Math.min(items.length, mMaxItems) : 0;
+        final int itemCount = items != null ? items.length : 0;
         mEmpty.setVisibility(itemCount == 0 ? VISIBLE : GONE);
-        mItems.setVisibility(itemCount == 0 ? GONE : VISIBLE);
-        for (int i = mItems.getChildCount() - 1; i >= itemCount; i--) {
-            mItems.removeViewAt(i);
-        }
-        for (int i = 0; i < itemCount; i++) {
-            bind(items[i], mItems.getChildAt(i));
-        }
+        mItemList.setVisibility(itemCount == 0 ? GONE : VISIBLE);
+        mItems = items;
+        mAdapter.notifyDataSetChanged();
     }
 
     private void handleSetItemsVisible(boolean visible) {
         if (mItemsVisible == visible) return;
         mItemsVisible = visible;
-        for (int i = 0; i < mItems.getChildCount(); i++) {
-            mItems.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
+        for (int i = 0; i < mItemList.getChildCount(); i++) {
+            mItemList.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
         }
     }
 
-    private void bind(final Item item, View view) {
-        if (view == null) {
-            view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, this, false);
-            mItems.addView(view);
+    private class Adapter extends BaseAdapter {
+
+        @Override
+        public int getCount() {
+            return mItems != null ? mItems.length : 0;
         }
-        view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
-        final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
-        iv.setImageResource(item.icon);
-        iv.getOverlay().clear();
-        if (item.overlay != null) {
-            item.overlay.setBounds(0, 0, item.overlay.getIntrinsicWidth(),
-                    item.overlay.getIntrinsicHeight());
-            iv.getOverlay().add(item.overlay);
+
+        @Override
+        public Object getItem(int position) {
+            return mItems[position];
         }
-        final TextView title = (TextView) view.findViewById(android.R.id.title);
-        title.setText(item.line1);
-        final TextView summary = (TextView) view.findViewById(android.R.id.summary);
-        final boolean twoLines = !TextUtils.isEmpty(item.line2);
-        title.setMaxLines(twoLines ? 1 : 2);
-        summary.setVisibility(twoLines ? VISIBLE : GONE);
-        summary.setText(twoLines ? item.line2 : null);
-        view.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                if (mCallback != null) {
-                    mCallback.onDetailItemClick(item);
-                }
+
+        @Override
+        public long getItemId(int position) {
+            return 0;
+        }
+
+        @Override
+        public View getView(int position, View view, ViewGroup parent) {
+            final Item item = mItems[position];
+            if (view == null) {
+                view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, parent,
+                        false);
             }
-        });
-        final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
-        disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
-        disconnect.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                if (mCallback != null) {
-                    mCallback.onDetailItemDisconnect(item);
-                }
+            view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
+            final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
+            iv.setImageResource(item.icon);
+            iv.getOverlay().clear();
+            if (item.overlay != null) {
+                item.overlay.setBounds(0, 0, item.overlay.getIntrinsicWidth(),
+                        item.overlay.getIntrinsicHeight());
+                iv.getOverlay().add(item.overlay);
             }
-        });
-    }
+            final TextView title = (TextView) view.findViewById(android.R.id.title);
+            title.setText(item.line1);
+            final TextView summary = (TextView) view.findViewById(android.R.id.summary);
+            final boolean twoLines = !TextUtils.isEmpty(item.line2);
+            title.setMaxLines(twoLines ? 1 : 2);
+            summary.setVisibility(twoLines ? VISIBLE : GONE);
+            summary.setText(twoLines ? item.line2 : null);
+            view.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (mCallback != null) {
+                        mCallback.onDetailItemClick(item);
+                    }
+                }
+            });
+            final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
+            disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
+            disconnect.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (mCallback != null) {
+                        mCallback.onDetailItemDisconnect(item);
+                    }
+                }
+            });
+            return view;
+        }
+    };
 
     private class H extends Handler {
         private static final int SET_ITEMS = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
index 546f8c3..6c224f7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
@@ -30,9 +30,9 @@
 
 public class QSIconView extends ViewGroup {
 
-    private final View mIcon;
-    private final int mIconSizePx;
-    private final int mTilePaddingBelowIconPx;
+    protected final View mIcon;
+    protected final int mIconSizePx;
+    protected final int mTilePaddingBelowIconPx;
     private boolean mAnimationEnabled = true;
 
     public QSIconView(Context context) {
@@ -50,6 +50,10 @@
         mAnimationEnabled = false;
     }
 
+    public View getIconView() {
+        return mIcon;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int w = MeasureSpec.getSize(widthMeasureSpec);
@@ -109,11 +113,11 @@
         return icon;
     }
 
-    protected static int exactly(int size) {
+    protected final int exactly(int size) {
         return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
     }
 
-    protected static void layout(View child, int left, int top) {
+    protected final void layout(View child, int left, int top) {
         child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index a05818a..1149c59 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -85,20 +85,7 @@
                 R.layout.quick_settings_brightness_dialog, this, false);
         addView(mBrightnessView);
 
-        mTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
-                R.layout.qs_paged_tile_layout, this, false);
-        addView((View) mTileLayout);
-        findViewById(android.R.id.edit).setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(final View v) {
-                mHost.startRunnableDismissingKeyguard(new Runnable() {
-                    @Override
-                    public void run() {
-                        showEdit(v);
-                    }
-                });
-            }
-        });
+        setupTileLayout();
 
         mFooter = new QSFooter(this, context);
         addView(mFooter.getView());
@@ -111,6 +98,14 @@
 
     }
 
+    protected void setupTileLayout() {
+        mTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
+                R.layout.qs_paged_tile_layout, this, false);
+        addView((View) mTileLayout);
+        findViewById(android.R.id.edit).setOnClickListener(view ->
+                mHost.startRunnableDismissingKeyguard(() -> showEdit(view)));
+    }
+
     public boolean isShowingCustomize() {
         return mCustomizePanel != null && mCustomizePanel.isCustomizing();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 98a1c23..c3766e8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -33,18 +33,16 @@
 /** View that represents a standard quick settings tile. **/
 public class QSTileView extends QSTileBaseView {
     protected final Context mContext;
-    private QSIconView mIconView;
     private final int mTileSpacingPx;
     private int mTilePaddingTopPx;
 
-    private TextView mLabel;
+    protected TextView mLabel;
     private ImageView mPadLock;
 
     public QSTileView(Context context, QSIconView icon) {
         super(context, icon);
 
         mContext = context;
-        mIconView = icon;
         final Resources res = context.getResources();
         mTileSpacingPx = res.getDimensionPixelSize(R.dimen.qs_tile_spacing);
 
@@ -81,14 +79,14 @@
         FontSizeUtils.updateFontSize(mLabel, R.dimen.qs_tile_text_size);
     }
 
-    private void createLabel() {
-        final Resources res = mContext.getResources();
+    protected void createLabel() {
         View view = LayoutInflater.from(mContext).inflate(R.layout.qs_tile_label, null);
         mLabel = (TextView) view.findViewById(R.id.tile_label);
         mPadLock = (ImageView) view.findViewById(R.id.restricted_padlock);
         addView(view);
     }
 
+    @Override
     protected void handleStateChanged(QSTile.State state) {
         super.handleStateChanged(state);
         if (!Objects.equal(mLabel.getText(), state.label)) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 55eda98..1e3c458 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -19,11 +19,12 @@
     private static final String TAG = "TileLayout";
 
     protected int mColumns;
-    private int mCellWidth;
-    private int mCellHeight;
-    private int mCellMargin;
+    protected int mCellWidth;
+    protected int mCellHeight;
+    protected int mCellMargin;
 
     protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
+    private int mCellMarginTop;
 
     public TileLayout(Context context) {
         this(context, null);
@@ -60,9 +61,10 @@
         final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
         mCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
         mCellMargin = res.getDimensionPixelSize(R.dimen.qs_tile_margin);
+        mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
         if (mColumns != columns) {
             mColumns = columns;
-            postInvalidate();
+            requestLayout();
             return true;
         }
         return false;
@@ -81,7 +83,8 @@
             record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
             previousView = record.tileView.updateAccessibilityOrder(previousView);
         }
-        setMeasuredDimension(width, (mCellHeight + mCellMargin) * rows);
+        setMeasuredDimension(width,
+                (mCellHeight + mCellMargin) * rows + (mCellMarginTop - mCellMargin));
     }
 
     private static int exactly(int size) {
@@ -114,7 +117,7 @@
     }
 
     private int getRowTop(int row) {
-        return row * (mCellHeight + mCellMargin) + mCellMargin;
+        return row * (mCellHeight + mCellMargin) + mCellMarginTop;
     }
 
     private int getColumnStart(int column) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
new file mode 100644
index 0000000..e512f93
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.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.qs.customize;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+import com.android.systemui.R;
+import com.android.systemui.qs.QSIconView;
+import com.android.systemui.qs.QSTileView;
+import libcore.util.Objects;
+
+public class CustomizeTileView extends QSTileView {
+
+    private TextView mAppLabel;
+
+    public CustomizeTileView(Context context, QSIconView icon) {
+        super(context, icon);
+    }
+
+    @Override
+    protected void createLabel() {
+        super.createLabel();
+        View view = LayoutInflater.from(mContext).inflate(R.layout.qs_tile_label, null);
+        mAppLabel = (TextView) view.findViewById(R.id.tile_label);
+        mAppLabel.setAlpha(.6f);
+        mAppLabel.setSingleLine(true);
+        addView(view);
+    }
+
+    public void setShowAppLabel(boolean showAppLabel) {
+        mAppLabel.setVisibility(showAppLabel ? View.VISIBLE : View.GONE);
+        mLabel.setSingleLine(showAppLabel);
+    }
+
+    public void setAppLabel(CharSequence label) {
+        if (!Objects.equal(label, mAppLabel.getText())) {
+            mAppLabel.setText(label);
+        }
+    }
+
+    public TextView getAppLabel() {
+        return mAppLabel;
+    }
+}
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 4c13451..e8e17b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -41,7 +41,6 @@
 import com.android.internal.logging.MetricsProto;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSIconView;
-import com.android.systemui.qs.QSTileView;
 import com.android.systemui.qs.customize.TileAdapter.Holder;
 import com.android.systemui.qs.customize.TileQueryHelper.TileInfo;
 import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener;
@@ -61,6 +60,10 @@
     private static final int TYPE_TILE = 0;
     private static final int TYPE_EDIT = 1;
     private static final int TYPE_ACCESSIBLE_DROP = 2;
+    private static final int TYPE_DIVIDER = 4;
+
+    private static final long EDIT_ID = 10000;
+    private static final long DIVIDER_ID = 20000;
 
     private final Context mContext;
 
@@ -68,7 +71,8 @@
     private final List<TileInfo> mTiles = new ArrayList<>();
     private final ItemTouchHelper mItemTouchHelper;
     private final AccessibilityManager mAccessibilityManager;
-    private int mDividerIndex;
+    private int mEditIndex;
+    private int mTileDividerIndex;
     private boolean mNeedsFocus;
     private List<String> mCurrentSpecs;
     private List<TileInfo> mOtherTiles;
@@ -87,7 +91,8 @@
 
     @Override
     public long getItemId(int position) {
-        return mTiles.get(position) != null ? mAllTiles.indexOf(mTiles.get(position)) : -1;
+        return mTiles.get(position) != null ? mAllTiles.indexOf(mTiles.get(position))
+                : position == mEditIndex ? EDIT_ID : DIVIDER_ID;
     }
 
     public ItemTouchHelper getItemTouchHelper() {
@@ -100,7 +105,7 @@
 
     public void saveSpecs(QSTileHost host) {
         List<String> newSpecs = new ArrayList<>();
-        for (int i = 0; mTiles.get(i) != null; i++) {
+        for (int i = 0; i < mTiles.size() && mTiles.get(i) != null; i++) {
             newSpecs.add(mTiles.get(i).spec);
         }
         host.changeTiles(mCurrentSpecs, newSpecs);
@@ -131,8 +136,19 @@
             }
         }
         mTiles.add(null);
+        for (int i = 0; i < mOtherTiles.size(); i++) {
+            final TileInfo tile = mOtherTiles.get(i);
+            if (tile.isSystem) {
+                mOtherTiles.remove(i--);
+                mTiles.add(tile);
+            }
+        }
+        if (mOtherTiles.size() != 0) {
+            mTileDividerIndex = mTiles.size();
+            mTiles.add(null);
+        }
         mTiles.addAll(mOtherTiles);
-        mDividerIndex = mTiles.indexOf(null);
+        mEditIndex = mTiles.indexOf(null);
         notifyDataSetChanged();
     }
 
@@ -147,9 +163,12 @@
 
     @Override
     public int getItemViewType(int position) {
-        if (mAccessibilityMoving && position == mDividerIndex - 1) {
+        if (mAccessibilityMoving && position == mEditIndex - 1) {
             return TYPE_ACCESSIBLE_DROP;
         }
+        if (position == mTileDividerIndex) {
+            return TYPE_DIVIDER;
+        }
         if (mTiles.get(position) == null) {
             return TYPE_EDIT;
         }
@@ -160,12 +179,15 @@
     public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
         final Context context = parent.getContext();
         LayoutInflater inflater = LayoutInflater.from(context);
+        if (viewType == TYPE_DIVIDER) {
+            return new Holder(inflater.inflate(R.layout.qs_customize_tile_divider, parent, false));
+        }
         if (viewType == TYPE_EDIT) {
             return new Holder(inflater.inflate(R.layout.qs_customize_divider, parent, false));
         }
         FrameLayout frame = (FrameLayout) inflater.inflate(R.layout.qs_customize_tile_frame, parent,
                 false);
-        frame.addView(new QSTileView(context, new QSIconView(context)));
+        frame.addView(new CustomizeTileView(context, new QSIconView(context)));
         return new Holder(frame);
     }
 
@@ -176,6 +198,9 @@
 
     @Override
     public void onBindViewHolder(final Holder holder, final int position) {
+        if (holder.getItemViewType() == TYPE_DIVIDER) {
+            return;
+        }
         if (holder.getItemViewType() == TYPE_EDIT) {
             ((TextView) holder.itemView.findViewById(android.R.id.title)).setText(
                     mCurrentDrag != null ? R.string.drag_to_remove_tiles
@@ -213,7 +238,7 @@
 
         TileInfo info = mTiles.get(position);
 
-        if (position > mDividerIndex) {
+        if (position > mEditIndex) {
             info.state.contentDescription = mContext.getString(
                     R.string.accessibility_qs_edit_add_tile_label, info.state.label);
         } else if (mAccessibilityMoving) {
@@ -224,9 +249,11 @@
                     R.string.accessibility_qs_edit_tile_label, position + 1, info.state.label);
         }
         holder.mTileView.onStateChanged(info.state);
+        holder.mTileView.setAppLabel(info.appLabel);
+        holder.mTileView.setShowAppLabel(position > mTileDividerIndex);
 
         if (mAccessibilityManager.isTouchExplorationEnabled()) {
-            final boolean selectable = !mAccessibilityMoving || position < mDividerIndex;
+            final boolean selectable = !mAccessibilityMoving || position < mEditIndex;
             holder.mTileView.setClickable(selectable);
             holder.mTileView.setFocusable(selectable);
             holder.mTileView.setImportantForAccessibility(selectable
@@ -239,7 +266,7 @@
                         if (mAccessibilityMoving) {
                             selectPosition(position, v);
                         } else {
-                            if (position < mDividerIndex) {
+                            if (position < mEditIndex) {
                                 showAccessibilityDialog(position, v);
                             } else {
                                 startAccessibleDrag(position);
@@ -253,7 +280,7 @@
 
     private void selectPosition(int position, View v) {
         // Remove the placeholder.
-        mTiles.remove(mDividerIndex--);
+        mTiles.remove(mEditIndex--);
         mAccessibilityMoving = false;
         move(mAccessibilityFromIndex, position, v);
         notifyDataSetChanged();
@@ -272,7 +299,7 @@
                         if (which == 0) {
                             startAccessibleDrag(position);
                         } else {
-                            move(position, mDividerIndex, v);
+                            move(position, mEditIndex, v);
                         }
                     }
                 }).setNegativeButton(android.R.string.cancel, null)
@@ -287,7 +314,7 @@
         mNeedsFocus = true;
         mAccessibilityFromIndex = position;
         // Add placeholder for last slot.
-        mTiles.add(mDividerIndex++, null);
+        mTiles.add(mEditIndex++, null);
         notifyDataSetChanged();
     }
 
@@ -296,25 +323,38 @@
     }
 
     private boolean move(int from, int to, View v) {
-        if (to > mDividerIndex) {
-            if (from >= mDividerIndex) {
+        if (to >= mEditIndex) {
+            if (from >= mEditIndex) {
                 return false;
             }
+            // Sort tiles into system/non-system groups.
+            TileInfo tile = mTiles.get(from);
+            if (tile.isSystem) {
+                if (to > mTileDividerIndex) {
+                    to = mTileDividerIndex;
+                }
+            } else {
+                if (mTileDividerIndex == mTiles.size()) {
+                    mTiles.add(null);
+                }
+                if (to <= mTileDividerIndex) {
+                    to = mTileDividerIndex;
+                }
+            }
         }
         CharSequence fromLabel = mTiles.get(from).state.label;
         move(from, to, mTiles);
-        mDividerIndex = mTiles.indexOf(null);
-        notifyItemChanged(from);
-        notifyItemMoved(from, to);
+        notifyDataSetChanged();
+        updateDividerLocations();
         CharSequence announcement;
-        if (to >= mDividerIndex) {
+        if (to >= mEditIndex) {
             MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_REMOVE_SPEC,
                     strip(mTiles.get(to)));
             MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_REMOVE,
                     from);
             announcement = mContext.getString(R.string.accessibility_qs_edit_tile_removed,
                     fromLabel);
-        } else if (from >= mDividerIndex) {
+        } else if (from >= mEditIndex) {
             MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_ADD_SPEC,
                     strip(mTiles.get(to)));
             MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_ADD,
@@ -333,6 +373,25 @@
         return true;
     }
 
+    private void updateDividerLocations() {
+        // The first null is the edit tiles label, the second null is the tile divider.
+        // If there is no second null, then there are no non-system tiles.
+        mEditIndex = -1;
+        mTileDividerIndex = mTiles.size();
+        for (int i = 0; i < mTiles.size(); i++) {
+            if (mTiles.get(i) == null) {
+                if (mEditIndex == -1) {
+                    mEditIndex = i;
+                } else {
+                    mTileDividerIndex = i;
+                }
+            }
+        }
+        if (mTiles.get(mTiles.size() - 1) == null) {
+            mTiles.remove(mTiles.size() - 1);
+        }
+    }
+
     private String strip(TileInfo tileInfo) {
         String spec = tileInfo.spec;
         if (spec.startsWith(CustomTile.PREFIX)) {
@@ -348,12 +407,12 @@
     }
 
     public class Holder extends ViewHolder {
-        private QSTileView mTileView;
+        private CustomizeTileView mTileView;
 
         public Holder(View itemView) {
             super(itemView);
             if (itemView instanceof FrameLayout) {
-                mTileView = (QSTileView) ((FrameLayout) itemView).getChildAt(0);
+                mTileView = (CustomizeTileView) ((FrameLayout) itemView).getChildAt(0);
                 mTileView.setBackground(null);
                 mTileView.getIcon().disableAnimation();
             }
@@ -367,6 +426,9 @@
             mTileView.findViewById(R.id.tile_label).animate()
                     .setDuration(DRAG_LENGTH)
                     .alpha(0);
+            mTileView.getAppLabel().animate()
+                    .setDuration(DRAG_LENGTH)
+                    .alpha(0);
         }
 
         public void stopDrag() {
@@ -377,13 +439,17 @@
             mTileView.findViewById(R.id.tile_label).animate()
                     .setDuration(DRAG_LENGTH)
                     .alpha(1);
+            mTileView.getAppLabel().animate()
+                    .setDuration(DRAG_LENGTH)
+                    .alpha(.6f);
         }
     }
 
     private final SpanSizeLookup mSizeLookup = new SpanSizeLookup() {
         @Override
         public int getSpanSize(int position) {
-            return getItemViewType(position) == TYPE_EDIT ? 3 : 1;
+            final int type = getItemViewType(position);
+            return type == TYPE_EDIT || type == TYPE_DIVIDER ? 3 : 1;
         }
     };
 
@@ -401,7 +467,7 @@
             for (int i = 0; i < childCount; i++) {
                 final View child = parent.getChildAt(i);
                 final ViewHolder holder = parent.getChildViewHolder(child);
-                if (holder.getAdapterPosition() < mDividerIndex) {
+                if (holder.getAdapterPosition() < mEditIndex) {
                     continue;
                 }
 
@@ -443,7 +509,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    notifyItemChanged(mDividerIndex);
+                    notifyItemChanged(mEditIndex);
                 }
             });
         }
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 bbc8856..d04a2fc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -31,6 +31,7 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.QSTile.DrawableIcon;
+import com.android.systemui.qs.QSTile.State;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.statusbar.phone.QSTileHost;
 
@@ -79,7 +80,7 @@
                     mainHandler.post(new Runnable() {
                         @Override
                         public void run() {
-                            addTile(spec, state);
+                            addTile(spec, null, state, true);
                             mListener.onTilesChanged(mTiles);
                         }
                     });
@@ -103,28 +104,33 @@
         mListener = listener;
     }
 
-    private void addTile(String spec, QSTile.State state) {
+    private void addTile(String spec, CharSequence appLabel, State state, boolean isSystem) {
         if (mSpecs.contains(spec)) {
             return;
         }
         TileInfo info = new TileInfo();
         info.state = state;
         info.spec = spec;
+        info.appLabel = appLabel;
+        info.isSystem = isSystem;
         mTiles.add(info);
         mSpecs.add(spec);
     }
 
-    private void addTile(String spec, Drawable drawable, CharSequence label, Context context) {
+    private void addTile(String spec, Drawable drawable, CharSequence label, CharSequence appLabel,
+            Context context) {
         QSTile.State state = new QSTile.State();
         state.label = label;
         state.contentDescription = label;
         state.icon = new DrawableIcon(drawable);
-        addTile(spec, state);
+        addTile(spec, appLabel, state, false);
     }
 
     public static class TileInfo {
         public String spec;
+        public CharSequence appLabel;
         public QSTile.State state;
+        public boolean isSystem;
     }
 
     private class QueryTilesTask extends AsyncTask<Void, Void, Collection<TileInfo>> {
@@ -147,7 +153,8 @@
                     icon.setTint(mContext.getColor(android.R.color.white));
                 }
                 CharSequence label = info.serviceInfo.loadLabel(pm);
-                addTile(spec, icon, label != null ? label.toString() : "null", mContext);
+                final CharSequence appLabel = info.serviceInfo.applicationInfo.loadLabel(pm);
+                addTile(spec, icon, label != null ? label.toString() : "null", appLabel, mContext);
             }
             return tiles;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 1fef8f1..63c85db 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -216,7 +216,6 @@
             mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
                     R.string.quick_settings_bluetooth_detail_empty_text);
             mItems.setCallback(this);
-            mItems.setMinHeightInItems(0);
             updateItems();
             setItemsVisible(mState.value);
             return mItems;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index fff7d78..b1d9555 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -78,6 +78,9 @@
 import com.android.systemui.recents.views.SystemBarScrimViews;
 import com.android.systemui.statusbar.BaseStatusBar;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 /**
  * The main Recents activity that is started from AlternateRecentsComponent.
  */
@@ -344,7 +347,7 @@
 
         // Update the nav bar scrim, but defer the animation until the enter-window event
         boolean animateNavBarScrim = !launchState.launchedViaDockGesture;
-        updateNavBarScrim(animateNavBarScrim, null);
+        mScrimViews.updateNavBarScrim(animateNavBarScrim, stack.getTaskCount() > 0, null);
 
         // If this is a new instance relaunched by AM, without going through the normal mechanisms,
         // then we have to manually trigger the enter animation state
@@ -417,39 +420,43 @@
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
-        // Update the nav bar for the current orientation
-        updateNavBarScrim(false /* animateNavBarScrim */, AnimationProps.IMMEDIATE);
 
         // Notify of the config change
         int newOrientation = getResources().getConfiguration().orientation;
+        int numStackTasks = mRecentsView.getStack().getStackTaskCount();
         EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
-                (mLastOrientation != newOrientation)));
+                (mLastOrientation != newOrientation), numStackTasks > 0));
         mLastOrientation = newOrientation;
     }
 
     @Override
     public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
         super.onMultiWindowModeChanged(isInMultiWindowMode);
+
+        // Reload the task stack completely
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
+        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);
+
+        TaskStack stack = loadPlan.getTaskStack();
+        int numStackTasks = stack.getStackTaskCount();
+
         EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
-                false /* fromOrientationChange */));
+                false /* fromOrientationChange */, numStackTasks > 0));
 
         if (mRecentsView != null) {
-            // Reload the task stack completely
-            RecentsConfiguration config = Recents.getConfiguration();
-            RecentsActivityLaunchState launchState = config.getLaunchState();
-            RecentsTaskLoader loader = Recents.getTaskLoader();
-            RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
-            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.updateStack(loadPlan.getTaskStack());
+            mRecentsView.updateStack(stack);
         }
 
-        EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode));
+        EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
+                numStackTasks > 0));
     }
 
     @Override
@@ -730,17 +737,19 @@
         return true;
     }
 
-    /**
-     * Updates the nav bar scrim.
-     */
-    private void updateNavBarScrim(boolean animateNavBarScrim, AnimationProps animation) {
-        // Animate the SystemUI scrims into view
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        int taskCount = mRecentsView.getStack().getTaskCount();
-        boolean hasNavBarScrim = (taskCount > 0) && !ssp.hasTransposedNavBar();
-        mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
-        if (animateNavBarScrim && animation != null) {
-            mScrimViews.animateNavBarScrimVisibility(true, animation);
+    @Override
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        super.dump(prefix, fd, writer, args);
+        String id = Integer.toHexString(System.identityHashCode(this));
+
+        writer.print(prefix); writer.print(TAG);
+        writer.print(" visible="); writer.print(mIsVisible ? "Y" : "N");
+        writer.print(" [0x"); writer.print(id); writer.print("]");
+        writer.println();
+
+        if (mRecentsView != null) {
+            mRecentsView.dump(prefix, writer);
         }
+        EventBus.getDefault().dump(prefix, writer);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 43d627d..aba05aa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -144,7 +144,6 @@
 
     // Task launching
     Rect mTaskStackBounds = new Rect();
-    Rect mLastTaskViewBounds = new Rect();
     TaskViewTransform mTmpTransform = new TaskViewTransform();
     int mStatusBarHeight;
     int mNavBarHeight;
@@ -169,8 +168,7 @@
         }
     });
 
-    protected Bitmap mThumbnailTransitionBitmapCache;
-    Task mThumbnailTransitionBitmapCacheKey;
+    protected Bitmap mThumbTransitionBitmapCache;
 
     public RecentsImpl(Context context) {
         mContext = context;
@@ -186,7 +184,6 @@
 
         // Initialize the static configuration resources
         reloadHeaderBarLayout();
-        updateHeaderBarLayout(null /* stack */);
 
         // When we start, preload the data associated with the previous recent tasks.
         // We can use a new plan since the caches will be the same.
@@ -201,12 +198,11 @@
     }
 
     public void onBootCompleted() {
-        updateHeaderBarLayout(null /* stack */);
+        // Do nothing
     }
 
     public void onConfigurationChanged() {
         reloadHeaderBarLayout();
-        updateHeaderBarLayout(null /* stack */);
     }
 
     /**
@@ -368,9 +364,14 @@
             loader.preloadTasks(sInstanceLoadPlan, topTask.id, topTaskHome.value);
             TaskStack stack = sInstanceLoadPlan.getTaskStack();
             if (stack.getTaskCount() > 0) {
-                // We try and draw the thumbnail transition bitmap in parallel before
-                // toggle/show recents is called
-                preCacheThumbnailTransitionBitmapAsync(topTask, stack, mDummyStackView);
+                // Only preload the icon (but not the thumbnail since it may not have been taken for
+                // the pausing activity)
+                preloadIcon(topTask);
+
+                // At this point, we don't know anything about the stack state.  So only calculate
+                // the dimensions of the thumbnail that we need for the transition into Recents, but
+                // do not draw it until we construct the activity options when we start Recents
+                updateHeaderBarLayout(stack);
             }
         }
     }
@@ -584,32 +585,47 @@
         Rect systemInsets = new Rect();
         ssp.getStableInsets(systemInsets);
         Rect windowRect = ssp.getWindowRect();
+        // When docked, the nav bar insets are consumed and the activity is measured without insets.
+        // However, the window bounds include the insets, so we need to subtract them here to make
+        // them identical.
+        if (ssp.hasDockedTask()) {
+            windowRect.bottom -= systemInsets.bottom;
+            systemInsets.bottom = 0;
+        }
         calculateWindowStableInsets(systemInsets, windowRect);
         windowRect.offsetTo(0, 0);
 
         TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
-        stackLayout.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right,
-                mTaskStackBounds);
 
         // Rebind the header bar and draw it for the transition
-        Rect taskStackBounds = new Rect(mTaskStackBounds);
         stackLayout.setSystemInsets(systemInsets);
         if (stack != null) {
-            stackLayout.initialize(windowRect, taskStackBounds,
+            stackLayout.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right,
+                    mTaskStackBounds);
+            stackLayout.reset();
+            stackLayout.initialize(windowRect, mTaskStackBounds,
                     TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
             mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
-        }
-        Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
-        if (!taskViewBounds.equals(mLastTaskViewBounds)) {
-            mLastTaskViewBounds.set(taskViewBounds);
 
+            Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
             int taskViewWidth = taskViewBounds.width();
             synchronized (mHeaderBarLock) {
-                mHeaderBar.measure(
-                    View.MeasureSpec.makeMeasureSpec(taskViewWidth, View.MeasureSpec.EXACTLY),
-                    View.MeasureSpec.makeMeasureSpec(mTaskBarHeight, View.MeasureSpec.EXACTLY));
+                if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
+                        mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
+                    mHeaderBar.measure(
+                        View.MeasureSpec.makeMeasureSpec(taskViewWidth, View.MeasureSpec.EXACTLY),
+                        View.MeasureSpec.makeMeasureSpec(mTaskBarHeight, View.MeasureSpec.EXACTLY));
+                }
                 mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight);
             }
+
+            // Update the transition bitmap to match the new header bar height
+            if (mThumbTransitionBitmapCache == null ||
+                    (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) ||
+                    (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) {
+                mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth,
+                        mTaskBarHeight, Bitmap.Config.ARGB_8888);
+            }
         }
     }
 
@@ -646,40 +662,6 @@
     }
 
     /**
-     * Caches the header thumbnail used for a window animation asynchronously into
-     * {@link #mThumbnailTransitionBitmapCache}.
-     */
-    private void preCacheThumbnailTransitionBitmapAsync(ActivityManager.RunningTaskInfo topTask,
-            TaskStack stack, TaskStackView stackView) {
-        preloadIcon(topTask);
-
-        // Update the header bar if necessary
-        updateHeaderBarLayout(stack);
-
-        // Update the destination rect
-        final Task toTask = new Task();
-        final TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
-        ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() {
-            @Override
-            public void run() {
-                final Bitmap transitionBitmap = drawThumbnailTransitionBitmap(toTask, toTransform);
-                if (transitionBitmap != null) {
-                    mHandler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            mThumbnailTransitionBitmapCache = transitionBitmap;
-                            mThumbnailTransitionBitmapCacheKey = toTask;
-                        }
-                    });
-                } else {
-                    Log.e(TAG, "Could not load thumbnail for task: " + toTask + " at transform: " +
-                            toTransform);
-                }
-            }
-        });
-    }
-
-    /**
      * Creates the activity options for a unknown state->recents transition.
      */
     protected ActivityOptions getUnknownTransitionActivityOptions() {
@@ -718,9 +700,10 @@
                 if (task.isFreeformTask()) {
                     mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
                                     stackScroller.getStackScroll(), mTmpTransform, null);
+                    Bitmap thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform,
+                            mThumbTransitionBitmapCache);
                     Rect toTaskRect = new Rect();
                     mTmpTransform.rect.round(toTaskRect);
-                    Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform);
                     specs.add(new AppTransitionAnimationSpec(task.key.id, thumbnail, toTaskRect));
                 }
             }
@@ -732,9 +715,10 @@
             // Update the destination rect
             Task toTask = new Task();
             TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
-            RectF toTaskRect = toTransform.rect;
-            Bitmap thumbnail = getThumbnailBitmap(topTask, toTask, toTransform);
+            Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
+                    mThumbTransitionBitmapCache);
             if (thumbnail != null) {
+                RectF toTaskRect = toTransform.rect;
                 return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
                         thumbnail, (int) toTaskRect.left, (int) toTaskRect.top,
                         (int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, null);
@@ -744,22 +728,6 @@
         }
     }
 
-    private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask,
-            TaskViewTransform toTransform) {
-        Bitmap thumbnail;
-        if (mThumbnailTransitionBitmapCacheKey != null
-                && mThumbnailTransitionBitmapCacheKey.key != null
-                && mThumbnailTransitionBitmapCacheKey.key.equals(toTask.key)) {
-            thumbnail = mThumbnailTransitionBitmapCache;
-            mThumbnailTransitionBitmapCacheKey = null;
-            mThumbnailTransitionBitmapCache = null;
-        } else {
-            preloadIcon(topTask);
-            thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform);
-        }
-        return thumbnail;
-    }
-
     /**
      * Returns the transition rect for the given task id.
      */
@@ -787,23 +755,19 @@
     /**
      * Draws the header of a task used for the window animation into a bitmap.
      */
-    private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform) {
+    private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform,
+            Bitmap thumbnail) {
         SystemServicesProxy ssp = Recents.getSystemServices();
         if (toTransform != null && toTask.key != null) {
-            Bitmap thumbnail;
             synchronized (mHeaderBarLock) {
-                int toHeaderWidth = (int) toTransform.rect.width();
-                int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale);
                 boolean disabledInSafeMode = !toTask.isSystemApp && ssp.isInSafeMode();
                 mHeaderBar.onTaskViewSizeChanged((int) toTransform.rect.width(),
                         (int) toTransform.rect.height());
-                thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight,
-                        Bitmap.Config.ARGB_8888);
                 if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
                     thumbnail.eraseColor(0xFFff0000);
                 } else {
+                    thumbnail.eraseColor(0);
                     Canvas c = new Canvas(thumbnail);
-                    c.scale(toTransform.scale, toTransform.scale);
                     // Workaround for b/27815919, reset the callback so that we do not trigger an
                     // invalidate on the header bar as a result of updating the icon
                     Drawable icon = mHeaderBar.getIconView().getDrawable();
@@ -845,6 +809,18 @@
         boolean hasRecentTasks = stack.getTaskCount() > 0;
         boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;
 
+        // Update the launch state that we need in updateHeaderBarLayout()
+        launchState.launchedFromHome = !useThumbnailTransition;
+        launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking;
+        launchState.launchedViaDockGesture = mLaunchedWhileDocking;
+        launchState.launchedViaDragGesture = mDraggingInRecents;
+        launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
+        launchState.launchedWithAltTab = mTriggeredFromAltTab;
+
+        // Preload the icon (this will be a null-op if we have preloaded the icon already in
+        // preloadRecents())
+        preloadIcon(topTask);
+
         // Update the header bar if necessary
         updateHeaderBarLayout(stack);
 
@@ -852,44 +828,27 @@
         TaskStackLayoutAlgorithm.VisibilityReport stackVr =
                 mDummyStackView.computeStackVisibilityReport();
 
-        // Update the launch state
-        launchState.launchedFromHome = false;
-        launchState.launchedFromApp = mLaunchedWhileDocking;
-        launchState.launchedViaDockGesture = mLaunchedWhileDocking;
-        launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
-        launchState.launchedWithAltTab = mTriggeredFromAltTab;
+        // Update the remaining launch state
         launchState.launchedNumVisibleTasks = stackVr.numVisibleTasks;
         launchState.launchedNumVisibleThumbnails = stackVr.numVisibleThumbnails;
-        launchState.launchedViaDragGesture = mDraggingInRecents;
 
         if (!animate) {
             startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1));
             return;
         }
 
+        ActivityOptions opts;
         if (useThumbnailTransition) {
-            launchState.launchedFromApp = true;
-
             // Try starting with a thumbnail transition
-            ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
-            if (opts != null) {
-                startRecentsActivity(opts);
-            } else {
-                // Fall through below to the non-thumbnail transition
-                useThumbnailTransition = false;
-            }
-        }
-
-        if (!useThumbnailTransition) {
-            launchState.launchedFromHome = true;
-
+            opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
+        } else {
             // If there is no thumbnail transition, but is launching from home into recents, then
             // use a quick home transition
-            ActivityOptions opts = hasRecentTasks
-                    ? getHomeTransitionActivityOptions()
-                    : getUnknownTransitionActivityOptions();
-            startRecentsActivity(opts);
+            opts = hasRecentTasks
+                ? getHomeTransitionActivityOptions()
+                : getUnknownTransitionActivityOptions();
         }
+        startRecentsActivity(opts);
         mLastToggleTime = SystemClock.elapsedRealtime();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
index 0d56ae9..38ad1c7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
@@ -30,6 +30,7 @@
 
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
@@ -652,19 +653,43 @@
     /**
      * @return a dump of the current state of the EventBus
      */
-    public String dump() {
+    public void dump(String prefix, PrintWriter writer) {
+        writer.println(dumpInternal(prefix));
+    }
+
+    public String dumpInternal(String prefix) {
+        String innerPrefix = prefix + "  ";
+        String innerInnerPrefix = innerPrefix + "  ";
         StringBuilder output = new StringBuilder();
+        output.append(prefix);
         output.append("Registered class types:");
         output.append("\n");
-        for (Class<?> clz : mSubscriberTypeMap.keySet()) {
-            output.append("\t");
+        ArrayList<Class<?>> subsciberTypes = new ArrayList<>(mSubscriberTypeMap.keySet());
+        Collections.sort(subsciberTypes, new Comparator<Class<?>>() {
+            @Override
+            public int compare(Class<?> o1, Class<?> o2) {
+                return o1.getSimpleName().compareTo(o2.getSimpleName());
+            }
+        });
+        for (int i = 0; i < subsciberTypes.size(); i++) {
+            Class<?> clz = subsciberTypes.get(i);
+            output.append(innerPrefix);
             output.append(clz.getSimpleName());
             output.append("\n");
         }
+        output.append(prefix);
         output.append("Event map:");
         output.append("\n");
-        for (Class<?> clz : mEventTypeMap.keySet()) {
-            output.append("\t");
+        ArrayList<Class<?>> classes = new ArrayList<>(mEventTypeMap.keySet());
+        Collections.sort(classes, new Comparator<Class<?>>() {
+            @Override
+            public int compare(Class<?> o1, Class<?> o2) {
+                return o1.getSimpleName().compareTo(o2.getSimpleName());
+            }
+        });
+        for (int i = 0; i < classes.size(); i++) {
+            Class<?> clz = classes.get(i);
+            output.append(innerPrefix);
             output.append(clz.getSimpleName());
             output.append(" -> ");
             output.append("\n");
@@ -673,7 +698,7 @@
                 Object subscriber = handler.subscriber.getReference();
                 if (subscriber != null) {
                     String id = Integer.toHexString(System.identityHashCode(subscriber));
-                    output.append("\t\t");
+                    output.append(innerInnerPrefix);
                     output.append(subscriber.getClass().getSimpleName());
                     output.append(" [0x" + id + ", #" + handler.priority + "]");
                     output.append("\n");
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
index 8be9ca7..e3bc2a7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
@@ -25,9 +25,12 @@
 
     public final boolean fromMultiWindow;
     public final boolean fromOrientationChange;
+    public final boolean hasStackTasks;
 
-    public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromOrientationChange) {
+    public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromOrientationChange,
+            boolean hasStackTasks) {
         this.fromMultiWindow = fromMultiWindow;
         this.fromOrientationChange = fromOrientationChange;
+        this.hasStackTasks = hasStackTasks;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
index 19245d9..cf2a68e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
@@ -24,8 +24,10 @@
 public class MultiWindowStateChangedEvent extends EventBus.Event {
 
     public final boolean inMultiWindow;
+    public final boolean hasStackTasks;
 
-    public MultiWindowStateChangedEvent(boolean inMultiWindow) {
+    public MultiWindowStateChangedEvent(boolean inMultiWindow, boolean hasStackTasks) {
         this.inMultiWindow = inMultiWindow;
+        this.hasStackTasks = hasStackTasks;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index e28612a..69d98af 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -243,4 +243,14 @@
     public static float dpToPx(Resources res, float dp) {
         return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
     }
+
+    /**
+     * Returns a lightweight dump of a rect.
+     */
+    public static String dumpRect(Rect r) {
+        if (r == null) {
+            return "N:0,0-0,0";
+        }
+        return r.left + "," + r.top + "-" + r.right + "," + r.bottom;
+    }
 }
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 76ca6ca..7aeff1f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -132,6 +132,8 @@
         SparseIntArray affiliatedTaskCounts = new SparseIntArray();
         String dismissDescFormat = mContext.getString(
                 R.string.accessibility_recents_item_will_be_dismissed);
+        String appInfoDescFormat = mContext.getString(
+                R.string.accessibility_recents_item_open_app_info);
         long lastStackActiveTime = Prefs.getLong(mContext,
                 Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0);
         if (RecentsDebugFlags.Static.EnableMockTasks) {
@@ -188,8 +190,9 @@
             // Load the title, icon, and color
             ActivityInfo info = loader.getAndUpdateActivityInfo(taskKey);
             String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
-            String contentDescription = loader.getAndUpdateContentDescription(taskKey, res);
-            String dismissDescription = String.format(dismissDescFormat, contentDescription);
+            String titleDescription = loader.getAndUpdateContentDescription(taskKey, res);
+            String dismissDescription = String.format(dismissDescFormat, titleDescription);
+            String appInfoDescription = String.format(appInfoDescFormat, titleDescription);
             Drawable icon = isStackTask
                     ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
                     : null;
@@ -201,9 +204,9 @@
 
             // Add the task to the stack
             Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, icon,
-                    thumbnail, title, contentDescription, dismissDescription, activityColor,
-                    backgroundColor, isLaunchTarget, isStackTask, isSystemApp, t.isDockable,
-                    t.bounds, t.taskDescription);
+                    thumbnail, title, titleDescription, dismissDescription, appInfoDescription,
+                    activityColor, backgroundColor, isLaunchTarget, isStackTask, isSystemApp,
+                    t.isDockable, t.bounds, t.taskDescription);
 
             allTasks.add(task);
             affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
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 d5d5aa0..24eeaf2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -29,6 +29,7 @@
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Objects;
 
@@ -37,6 +38,9 @@
  * A task represents the top most task in the system's task stack.
  */
 public class Task {
+
+    public static final String TAG = "Task";
+
     /* Task callbacks */
     public interface TaskCallbacks {
         /* Notifies when a task has been bound */
@@ -100,7 +104,8 @@
 
         @Override
         public String toString() {
-            return "t" + id + ", s" + stackId + ", u" + userId;
+            return "id=" + id + " stackId=" + stackId + " user=" + userId + " lastActiveTime=" +
+                    lastActiveTime;
         }
 
         private void updateHashCode() {
@@ -134,10 +139,12 @@
     @ViewDebug.ExportedProperty(category="recents")
     public String title;
     @ViewDebug.ExportedProperty(category="recents")
-    public String contentDescription;
+    public String titleDescription;
     @ViewDebug.ExportedProperty(category="recents")
     public String dismissDescription;
     @ViewDebug.ExportedProperty(category="recents")
+    public String appInfoDescription;
+    @ViewDebug.ExportedProperty(category="recents")
     public int colorPrimary;
     @ViewDebug.ExportedProperty(category="recents")
     public int colorBackground;
@@ -174,8 +181,8 @@
     }
 
     public Task(TaskKey key, int affiliationTaskId, int affiliationColor, Drawable icon,
-                Bitmap thumbnail, String title, String contentDescription,
-                String dismissDescription, int colorPrimary, int colorBackground,
+                Bitmap thumbnail, String title, String titleDescription, String dismissDescription,
+                String appInfoDescription, int colorPrimary, int colorBackground,
                 boolean isLaunchTarget, boolean isStackTask, boolean isSystemApp,
                 boolean isDockable, Rect bounds, ActivityManager.TaskDescription taskDescription) {
         boolean isInAffiliationGroup = (affiliationTaskId != key.id);
@@ -186,8 +193,9 @@
         this.icon = icon;
         this.thumbnail = thumbnail;
         this.title = title;
-        this.contentDescription = contentDescription;
+        this.titleDescription = titleDescription;
         this.dismissDescription = dismissDescription;
+        this.appInfoDescription = appInfoDescription;
         this.colorPrimary = hasAffiliationGroupColor ? affiliationColor : colorPrimary;
         this.colorBackground = colorBackground;
         this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary,
@@ -211,8 +219,9 @@
         this.icon = o.icon;
         this.thumbnail = o.thumbnail;
         this.title = o.title;
-        this.contentDescription = o.contentDescription;
+        this.titleDescription = o.titleDescription;
         this.dismissDescription = o.dismissDescription;
+        this.appInfoDescription = o.appInfoDescription;
         this.colorPrimary = o.colorPrimary;
         this.colorBackground = o.colorBackground;
         this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
@@ -302,4 +311,13 @@
     public String toString() {
         return "[" + key.toString() + "] " + title;
     }
+
+    public void dump(String prefix, PrintWriter writer) {
+        writer.print(prefix); writer.print(key);
+        if (affiliationTaskId != key.id) {
+            writer.print(" "); writer.print("affTaskId=" + affiliationTaskId);
+        }
+        writer.print(" "); writer.print(title);
+        writer.println();
+    }
 }
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 df3f56c..fbb5987 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -55,6 +55,7 @@
 import com.android.systemui.recents.views.DropTarget;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -208,6 +209,8 @@
  */
 public class TaskStack {
 
+    private static final String TAG = "TaskStack";
+
     /** Task stack callbacks */
     public interface TaskStackCallbacks {
         /**
@@ -725,7 +728,9 @@
     /** Finds the task with the specified task id. */
     public Task findTaskWithId(int taskId) {
         ArrayList<Task> tasks = computeAllTasksList();
-        for (Task task : tasks) {
+        int taskCount = tasks.size();
+        for (int i = 0; i < taskCount; i++) {
+            Task task = tasks.get(i);
             if (task.key.id == taskId) {
                 return task;
             }
@@ -880,7 +885,10 @@
         ArraySet<ComponentName> existingComponents = new ArraySet<>();
         ArraySet<ComponentName> removedComponents = new ArraySet<>();
         ArrayList<Task.TaskKey> taskKeys = getTaskKeys();
-        for (Task.TaskKey t : taskKeys) {
+        int taskKeyCount = taskKeys.size();
+        for (int i = 0; i < taskKeyCount; i++) {
+            Task.TaskKey t = taskKeys.get(i);
+
             // Skip if this doesn't apply to the current user
             if (t.userId != userId) continue;
 
@@ -903,8 +911,10 @@
     @Override
     public String toString() {
         String str = "Stack Tasks (" + mStackTaskList.size() + "):\n";
-        for (Task t : mStackTaskList.getTasks()) {
-            str += "    " + t.toString() + "\n";
+        ArrayList<Task> tasks = mStackTaskList.getTasks();
+        int taskCount = tasks.size();
+        for (int i = 0; i < taskCount; i++) {
+            str += "    " + tasks.get(i).toString() + "\n";
         }
         return str;
     }
@@ -921,4 +931,17 @@
         }
         return map;
     }
+
+    public void dump(String prefix, PrintWriter writer) {
+        String innerPrefix = prefix + "  ";
+
+        writer.print(prefix); writer.print(TAG);
+        writer.print(" numStackTasks="); writer.print(mStackTaskList.size());
+        writer.println();
+        ArrayList<Task> tasks = mStackTaskList.getTasks();
+        int taskCount = tasks.size();
+        for (int i = 0; i < taskCount; i++) {
+            tasks.get(i).dump(innerPrefix, writer);
+        }
+    }
 }
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 134b90c..13e1a14 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -15,8 +15,6 @@
  */
 package com.android.systemui.recents.tv;
 
-import android.animation.AnimatorInflater;
-import android.animation.AnimatorSet;
 import android.app.Activity;
 import android.app.ActivityOptions;
 import android.content.Intent;
@@ -39,14 +37,12 @@
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
-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.ToggleRecentsEvent;
 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.UpdateFreeformTaskViewVisibilityEvent;
 import com.android.systemui.recents.events.ui.UserInteractionEvent;
 import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -55,11 +51,13 @@
 import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.animations.HomeRecentsEnterExitAnimationHolder;
 import com.android.systemui.recents.tv.views.RecentsTvView;
+import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
 import com.android.systemui.recents.tv.views.TaskStackHorizontalViewAdapter;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.tv.pip.PipManager;
-import com.android.systemui.tv.pip.PipControlsView;
+import com.android.systemui.tv.pip.PipRecentsOverlayManager;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -78,17 +76,17 @@
     private RecentsPackageMonitor mPackageMonitor;
     private long mLastTabKeyEventTime;
     private boolean mIgnoreAltTabRelease;
+    private boolean mLaunchedFromHome;
 
     private RecentsTvView mRecentsView;
-    private PipControlsView mPipControlsView;
-    private View mPipShadeView;
-    private AnimatorSet mPipControlsViewFadeInAnimator;
-    private AnimatorSet mPipControlsViewFadeOutAnimator;
+    private View mPipView;
     private TaskStackHorizontalViewAdapter mTaskStackViewAdapter;
+    private TaskStackHorizontalGridView mTaskStackHorizontalGridView;
     private FinishRecentsRunnable mFinishLaunchHomeRunnable;
+    private HomeRecentsEnterExitAnimationHolder mHomeRecentsEnterExitAnimationHolder;
 
-    private PipManager mPipManager;
-    private PipManager.Listener mPipListener = new PipManager.Listener() {
+    private final PipManager mPipManager = PipManager.getInstance();
+    private final PipManager.Listener mPipListener = new PipManager.Listener() {
         @Override
         public void onPipEntered() {
             updatePipUI();
@@ -113,10 +111,32 @@
 
         @Override
         public void onPipResizeAboutToStart() { }
-
-        @Override
-        public void onMediaControllerChanged() { }
     };
+    private PipRecentsOverlayManager mPipRecentsOverlayManager;
+    private final PipRecentsOverlayManager.Callback mPipRecentsOverlayManagerCallback =
+            new PipRecentsOverlayManager.Callback() {
+                @Override
+                public void onClosed() {
+                    dismissRecentsToLaunchTargetTaskOrHome();
+                }
+
+                @Override
+                public void onBackPressed() {
+                    RecentsTvActivity.this.onBackPressed();
+                }
+
+                @Override
+                public void onRecentsFocused() {
+                    mRecentsView.requestFocus();
+                }
+            };
+    private final View.OnFocusChangeListener mPipViewFocusChangeListener =
+            new View.OnFocusChangeListener() {
+                @Override
+                public void onFocusChange(View v, boolean hasFocus) {
+                    handlePipViewFocusChange(hasFocus);
+                }
+            };
 
     /**
      * A common Runnable to finish Recents by launching Home with an animation depending on the
@@ -157,6 +177,7 @@
         if (!plan.hasTasks()) {
             loader.preloadTasks(plan, -1, launchState.launchedFromHome);
         }
+        mLaunchedFromHome = launchState.launchedFromHome;
         TaskStack stack = plan.getTaskStack();
         RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
         loadOpts.runningTaskId = launchState.launchedToTaskId;
@@ -170,7 +191,8 @@
         Collections.reverse(stackTasks);
         if (mTaskStackViewAdapter == null) {
             mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
-            mRecentsView.setTaskStackViewAdapter(mTaskStackViewAdapter);
+            mTaskStackHorizontalGridView = mRecentsView
+                    .setTaskStackViewAdapter(mTaskStackViewAdapter);
         } else {
             mTaskStackViewAdapter.setNewStackTasks(stackTasks);
         }
@@ -212,17 +234,24 @@
     }
 
     void dismissRecentsToHome(boolean animateTaskViews) {
-        DismissRecentsToHomeAnimationStarted dismissEvent =
-                new DismissRecentsToHomeAnimationStarted(animateTaskViews);
-        dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
-        dismissEvent.addPostAnimationCallback(new Runnable() {
+        Runnable closeSystemWindows = new Runnable() {
             @Override
             public void run() {
                 Recents.getSystemServices().sendCloseSystemWindows(
                         BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
             }
-        });
-        EventBus.getDefault().send(dismissEvent);
+        };
+        DismissRecentsToHomeAnimationStarted dismissEvent =
+                new DismissRecentsToHomeAnimationStarted(animateTaskViews);
+        dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
+        dismissEvent.addPostAnimationCallback(closeSystemWindows);
+
+        if(mTaskStackHorizontalGridView.getChildCount() > 0) {
+            mHomeRecentsEnterExitAnimationHolder.startExitAnimation(dismissEvent);
+        } else {
+            closeSystemWindows.run();
+            mFinishLaunchHomeRunnable.run();
+        }
     }
 
     boolean dismissRecentsToHomeIfVisible(boolean animated) {
@@ -248,7 +277,7 @@
             finish();
             return;
         }
-        mPipManager = PipManager.getInstance();
+        mPipRecentsOverlayManager = PipManager.getInstance().getPipRecentsOverlayManager();
 
         // Register this activity with the event bus
         EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
@@ -263,21 +292,18 @@
         mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
-        mPipControlsView = (PipControlsView) findViewById(R.id.pip_controls);
-        mPipControlsView.setListener(new PipControlsView.Listener() {
-            @Override
-            public void onClosed() {
-                dismissRecentsToLaunchTargetTaskOrHome();
-            }
-        });
-        mPipShadeView = findViewById(R.id.pip_shade);
 
-        mPipControlsViewFadeInAnimator = (AnimatorSet) AnimatorInflater.loadAnimator(this,
-                R.anim.tv_pip_controls_fade_in);
-        mPipControlsViewFadeInAnimator.setTarget(mPipControlsView);
-        mPipControlsViewFadeOutAnimator = (AnimatorSet) AnimatorInflater.loadAnimator(this,
-                R.anim.tv_pip_controls_fade_out);
-        mPipControlsViewFadeOutAnimator.setTarget(mPipControlsView);
+        mPipView = findViewById(R.id.pip);
+        // Place mPipView at the PIP bounds for fine tuned focus handling.
+        Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
+        LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
+        lp.width = pipBounds.width();
+        lp.height = pipBounds.height();
+        lp.leftMargin = pipBounds.left;
+        lp.topMargin = pipBounds.top;
+        mPipView.setLayoutParams(lp);
+
+        mPipRecentsOverlayManager.setCallback(mPipRecentsOverlayManagerCallback);
 
         getWindow().getAttributes().privateFlags |=
                 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
@@ -289,7 +315,6 @@
                 Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
         mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);
 
-        updatePipUI();
         mPipManager.addListener(mPipListener);
     }
 
@@ -306,6 +331,19 @@
         // Update the recent tasks
         updateRecentsTasks();
 
+        mHomeRecentsEnterExitAnimationHolder = new HomeRecentsEnterExitAnimationHolder(
+                getApplicationContext(), mTaskStackHorizontalGridView);
+        if(mTaskStackHorizontalGridView != null &&
+                mTaskStackHorizontalGridView.getChildCount() > 0) {
+            if(mLaunchedFromHome) {
+                mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
+            } else {
+                mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
+            }
+        } else {
+            mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
+        }
+
         // 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
@@ -321,22 +359,34 @@
         SystemServicesProxy ssp = Recents.getSystemServices();
         EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
 
-        mPipManager.onRecentsStarted();
-        // Give focus to the recents row whenever its visible to an user.
-        mRecentsView.requestFocus();
+        updatePipUI();
     }
 
     @Override
     public void onEnterAnimationComplete() {
         super.onEnterAnimationComplete();
+        if(mLaunchedFromHome) {
+            mHomeRecentsEnterExitAnimationHolder.startEnterAnimation();
+        }
         EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
     }
 
     @Override
+    public void onResume() {
+        super.onResume();
+        mPipRecentsOverlayManager.onRecentsResumed();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mPipRecentsOverlayManager.onRecentsPaused();
+    }
+
+    @Override
     protected void onStop() {
         super.onStop();
 
-        mPipManager.onRecentsStopped();
         mIgnoreAltTabRelease = false;
         // Notify that recents is now hidden
         EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
@@ -422,12 +472,6 @@
         }
     }
 
-    public final void onBusEvent(EnterRecentsWindowLastAnimationFrameEvent event) {
-        EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(true));
-        mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
-        mRecentsView.invalidate();
-    }
-
     public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
         int launchToTaskId = launchState.launchedToTaskId;
@@ -467,6 +511,11 @@
     @Override
     public boolean onPreDraw() {
         mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
+        if(mLaunchedFromHome) {
+            mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
+        } else {
+            mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
+        }
         // We post to make sure that this information is delivered after this traversals is
         // finished.
         mRecentsView.post(new Runnable() {
@@ -480,25 +529,32 @@
 
     private void updatePipUI() {
         if (mPipManager.isPipShown()) {
-            mPipControlsView.setAlpha(0);
-            mPipControlsView.setVisibility(View.VISIBLE);
-            mPipShadeView.setVisibility(View.INVISIBLE);
-            mPipControlsView.setOnChildFocusChangeListener(new View.OnFocusChangeListener() {
-                @Override
-                public void onFocusChange(View v, boolean hasFocus) {
-                    mPipManager.onPipViewFocusChangedInRecents(hasFocus);
-                    if (hasFocus) {
-                        mPipControlsViewFadeInAnimator.start();
-                    } else {
-                        mPipControlsViewFadeOutAnimator.start();
-                    }
-                    mPipShadeView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
-                }
-            });
-            mPipShadeView.setVisibility(View.GONE);
+            mPipView.setVisibility(View.VISIBLE);
+            mPipView.setOnFocusChangeListener(mPipViewFocusChangeListener);
+            if (mPipView.hasFocus()) {
+                // This can happen only if the activity is resumed. Ask for reset.
+                handlePipViewFocusChange(true);
+            } else {
+                mPipView.requestFocus();
+            }
         } else {
-            mPipControlsView.setVisibility(View.GONE);
-            mPipShadeView.setVisibility(View.GONE);
+            mPipView.setVisibility(View.GONE);
+            mPipRecentsOverlayManager.removePipRecentsOverlayView();
+        }
+    }
+
+    /**
+     * Handles the PIP view's focus change.
+     * This starts the relevant recents row animation
+     * and give focus to the recents overlay if needed.
+     */
+    private void handlePipViewFocusChange(boolean hasFocus) {
+        mRecentsView.startRecentsRowFocusAnimation(!hasFocus);
+        if (hasFocus) {
+            // When PIP view has focus, recents overlay view will takes the focus
+            // as if it's the part of the Recents UI.
+            mPipRecentsOverlayManager.requestFocus(
+                    mTaskStackViewAdapter.getItemCount() > 0);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
index c1b47dc..9a9e33b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
@@ -25,6 +25,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 
+import com.android.systemui.SystemUIApplication;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -34,6 +35,7 @@
 import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.tv.views.TaskCardView;
+import com.android.systemui.statusbar.tv.TvStatusBar;
 
 public class RecentsTvImpl extends RecentsImpl{
     public final static String RECENTS_TV_ACTIVITY =
@@ -81,16 +83,7 @@
         }
 
         if (!useThumbnailTransition) {
-            // If there is no thumbnail transition, but is launching from home into recents, then
-            // use a quick home transition and do the animation from home
-            if (hasRecentTasks) {
-                ActivityOptions opts = getHomeTransitionActivityOptions();
-                startRecentsActivity(topTask, opts, true /* fromHome */, false /* fromThumbnail */);
-            } else {
-                // Otherwise we do the normal fade from an unknown source
-                ActivityOptions opts = getUnknownTransitionActivityOptions();
-                startRecentsActivity(topTask, opts, true /* fromHome */, false /* fromThumbnail */);
-            }
+            startRecentsActivity(topTask, null, true /* fromHome */, false /* fromThumbnail */);
         }
         mLastToggleTime = SystemClock.elapsedRealtime();
     }
@@ -124,7 +117,7 @@
      */
     private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
             ActivityManager.RunningTaskInfo topTask) {
-        Bitmap thumbnail = mThumbnailTransitionBitmapCache;
+        Bitmap thumbnail = mThumbTransitionBitmapCache;
         Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
         if (thumbnail != null) {
             return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
@@ -134,4 +127,13 @@
         // If both the screenshot and thumbnail fails, then just fall back to the default transition
         return getUnknownTransitionActivityOptions();
     }
+
+    @Override
+    public void onVisibilityChanged(Context context, boolean visible) {
+        SystemUIApplication app = (SystemUIApplication) context;
+        TvStatusBar statusBar = app.getComponent(TvStatusBar.class);
+        if (statusBar != null) {
+            statusBar.updateRecentsVisibility(visible);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
index 8996d0b..fbcfa97 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
@@ -18,9 +18,8 @@
 
 import android.animation.Animator;
 import android.content.res.Resources;
-import android.support.v4.view.animation.FastOutSlowInInterpolator;
-import android.view.View;
 import android.widget.LinearLayout;
+import com.android.systemui.Interpolators;
 import com.android.systemui.recents.tv.views.TaskCardView;
 
 import com.android.systemui.R;
@@ -28,7 +27,6 @@
 public class DismissAnimationsHolder {
     private LinearLayout mDismissArea;
     private LinearLayout mTaskCardView;
-    private FastOutSlowInInterpolator mFastOutSlowIn;
     private int mCardYDelta;
     private long mShortDuration;
     private long mLongDuration;
@@ -36,7 +34,6 @@
     public DismissAnimationsHolder(TaskCardView taskCardView) {
         mTaskCardView = (LinearLayout) taskCardView.findViewById(R.id.recents_tv_card);
         mDismissArea = (LinearLayout) taskCardView.findViewById(R.id.card_dismiss);
-        mFastOutSlowIn = new FastOutSlowInInterpolator();
 
         Resources res = taskCardView.getResources();
         mCardYDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_shift_down);
@@ -45,36 +42,42 @@
     }
 
     public void startEnterAnimation() {
-        mDismissArea.animate().setDuration(mShortDuration);
-        mDismissArea.animate().setInterpolator(mFastOutSlowIn);
-        mDismissArea.animate().alpha(1.0f);
+        mDismissArea.animate()
+                .setDuration(mShortDuration)
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .alpha(1.0f);
 
-        mTaskCardView.animate().setDuration(mShortDuration);
-        mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
-        mTaskCardView.animate().translationYBy(mCardYDelta);
-        mTaskCardView.animate().alpha(0.5f);
+        mTaskCardView.animate()
+                .setDuration(mShortDuration)
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .translationYBy(mCardYDelta)
+                .alpha(0.5f);
     }
 
     public void startExitAnimation() {
-        mDismissArea.animate().setDuration(mShortDuration);
-        mDismissArea.animate().setInterpolator(mFastOutSlowIn);
-        mDismissArea.animate().alpha(0.0f);
+        mDismissArea.animate()
+                .setDuration(mShortDuration)
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .alpha(0.0f);
 
-        mTaskCardView.animate().setDuration(mShortDuration);
-        mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
-        mTaskCardView.animate().translationYBy(-mCardYDelta);
-        mTaskCardView.animate().alpha(1.0f);
+        mTaskCardView.animate()
+                .setDuration(mShortDuration)
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .translationYBy(-mCardYDelta)
+                .alpha(1.0f);
     }
 
     public void startDismissAnimation(Animator.AnimatorListener listener) {
-        mDismissArea.animate().setDuration(mShortDuration);
-        mDismissArea.animate().setInterpolator(mFastOutSlowIn);
-        mDismissArea.animate().alpha(0.0f);
+        mDismissArea.animate()
+                .setDuration(mShortDuration)
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .alpha(0.0f);
 
-        mTaskCardView.animate().setDuration(mLongDuration);
-        mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
-        mTaskCardView.animate().translationYBy(mCardYDelta);
-        mTaskCardView.animate().alpha(0.0f);
-        mTaskCardView.animate().setListener(listener);
+        mTaskCardView.animate()
+                .setDuration(mLongDuration)
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                .translationYBy(mCardYDelta)
+                .alpha(0.0f)
+                .setListener(listener);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
new file mode 100644
index 0000000..278de87
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.animations;
+
+import android.content.Context;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
+import com.android.systemui.recents.tv.views.TaskCardView;
+import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
+
+
+public class HomeRecentsEnterExitAnimationHolder {
+
+    private Context mContext;
+    private TaskStackHorizontalGridView mGridView;
+    private long mDelay;
+    private int mDuration;
+    private int mTranslationX;
+
+    public HomeRecentsEnterExitAnimationHolder(Context context,
+            TaskStackHorizontalGridView gridView) {
+        mContext = context;
+        mGridView = gridView;
+        mTranslationX = mContext.getResources()
+                .getDimensionPixelSize(R.dimen.recents_tv_home_recents_shift);
+        mDelay = mContext.getResources().getInteger(R.integer.recents_home_delay);
+        mDuration =  mContext.getResources().getInteger(R.integer.recents_home_duration);
+    }
+
+    public void startEnterAnimation() {
+        for(int i = 0; i < mGridView.getChildCount(); i++) {
+            TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+            view.setTranslationX(-mTranslationX);
+            view.setAlpha(0.0f);
+            view.animate()
+                    .alpha(1.0f)
+                    .translationX(0)
+                    .setDuration(mDuration)
+                    .setStartDelay(mDelay * i)
+                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        }
+    }
+
+    public void startExitAnimation(DismissRecentsToHomeAnimationStarted dismissEvent) {
+        for(int i = mGridView.getChildCount() - 1; i >= 0; i--) {
+            TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+            view.animate()
+                    .alpha(0.0f)
+                    .translationXBy(-mTranslationX)
+                    .setDuration(mDuration)
+                    .setStartDelay(mDelay * (mGridView.getChildCount() - 1 - i))
+                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+            if(i == 0) {
+                view.animate().setListener(dismissEvent.getAnimationTrigger()
+                        .decrementOnAnimationEnd());
+                dismissEvent.getAnimationTrigger().increment();
+            }
+        }
+    }
+
+    public void setEnterFromHomeStartingAnimationValues() {
+        for(int i = 0; i < mGridView.getChildCount(); i++) {
+            TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+            view.setTranslationX(-mTranslationX);
+            view.setAlpha(0.0f);
+        }
+    }
+
+    public void setEnterFromAppStartingAnimationValues() {
+        for(int i = 0; i < mGridView.getChildCount(); i++) {
+            TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+            view.setTranslationX(0);
+            view.setAlpha(1.0f);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
new file mode 100644
index 0000000..28abc34
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.animations;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.res.Resources;
+import android.view.View;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.recents.tv.views.TaskCardView;
+
+/**
+ * Recents row's focus animation with PIP controls.
+ */
+public class RecentsRowFocusAnimationHolder {
+    private static final float DIM_ALPHA = 0.5f;
+
+    private View mView;
+    private View mTitleView;
+
+    private AnimatorSet mFocusGainAnimatorSet;
+    private AnimatorSet mFocusLoseAnimatorSet;
+
+    public RecentsRowFocusAnimationHolder(View view, View titleView) {
+        mView = view;
+        mTitleView = titleView;
+
+        Resources res = view.getResources();
+        int duration = res.getInteger(R.integer.recents_tv_pip_focus_anim_duration);
+
+        mFocusGainAnimatorSet = new AnimatorSet();
+        mFocusGainAnimatorSet.playTogether(
+                ObjectAnimator.ofFloat(mView, "alpha", 1f),
+                ObjectAnimator.ofFloat(mTitleView, "alpha", 1f));
+        mFocusGainAnimatorSet.setDuration(duration);
+        mFocusGainAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+
+        mFocusLoseAnimatorSet = new AnimatorSet();
+        mFocusLoseAnimatorSet.playTogether(
+                ObjectAnimator.ofFloat(mView, "alpha", DIM_ALPHA),
+                ObjectAnimator.ofFloat(mTitleView, "alpha", 0f));
+        mFocusLoseAnimatorSet.setDuration(duration);
+        mFocusLoseAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+    }
+
+    /**
+     * Returns the Recents row's focus change animation.
+     */
+    public Animator getFocusChangeAnimator(boolean hasFocus) {
+        return hasFocus ? mFocusGainAnimatorSet : mFocusLoseAnimatorSet;
+    }
+
+    /**
+     * Resets the views to the initial state immediately.
+     */
+    public void reset() {
+        mView.setAlpha(1f);
+        mTitleView.setAlpha(1f);
+    }
+}
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 d966614..9e4abac 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
@@ -37,6 +37,7 @@
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.animations.RecentsRowFocusAnimationHolder;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -52,6 +53,7 @@
     private TaskStack mStack;
     private TaskStackHorizontalGridView mTaskStackHorizontalView;
     private View mEmptyView;
+    private RecentsRowFocusAnimationHolder mEmptyViewFocusAnimationHolder;
     private boolean mAwaitingFirstLayout = true;
     private Rect mSystemInsets = new Rect();
     private RecentsTvTransitionHelper mTransitionHelper;
@@ -77,6 +79,8 @@
         LayoutInflater inflater = LayoutInflater.from(context);
         mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
         addView(mEmptyView);
+        mEmptyViewFocusAnimationHolder = new RecentsRowFocusAnimationHolder(mEmptyView, null);
+
         mHandler = new Handler();
         mTransitionHelper = new RecentsTvTransitionHelper(mContext, mHandler);
     }
@@ -94,7 +98,6 @@
             mTaskStackHorizontalView.setStack(stack);
         }
 
-
         if (stack.getStackTaskCount() > 0) {
             hideEmptyView();
         } else {
@@ -134,33 +137,40 @@
     public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
         if (mTaskStackHorizontalView != null) {
             // Iterate the stack views and try and find the given task.
-            List<TaskCardView> taskViews = mTaskStackHorizontalView.getTaskViews();
-            int taskViewCount = taskViews.size();
-            for (int j = 0; j < taskViewCount; j++) {
-                TaskCardView tv = taskViews.get(j);
-                if (tv.getTask() == task) {
-                    SystemServicesProxy ssp = Recents.getSystemServices();
-                    ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
-                    return true;
-                }
+            if (mTaskStackHorizontalView.getChildViewForTask(task) != null) {
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
+                return true;
             }
         }
         return false;
     }
 
     /**
+     * Starts the focus change animation.
+     */
+    public void startRecentsRowFocusAnimation(boolean hasFocus) {
+        if (mEmptyView.getVisibility() == View.VISIBLE) {
+            mEmptyViewFocusAnimationHolder.getFocusChangeAnimator(hasFocus).start();
+        } else {
+            mTaskStackHorizontalView.startRecentsRowFocusAnimation(hasFocus);
+        }
+    }
+
+    /**
      * Hides the task stack and shows the empty view.
      */
     public void showEmptyView() {
         mEmptyView.setVisibility(View.VISIBLE);
-        mEmptyView.bringToFront();
+        mTaskStackHorizontalView.setVisibility(View.GONE);
     }
 
     /**
      * Shows the task stack and hides the empty view.
      */
     public void hideEmptyView() {
-        mEmptyView.setVisibility(View.INVISIBLE);
+        mEmptyView.setVisibility(View.GONE);
+        mTaskStackHorizontalView.setVisibility(View.VISIBLE);
     }
 
     /**
@@ -208,9 +218,15 @@
         }
     }
 
-    public void setTaskStackViewAdapter(TaskStackHorizontalViewAdapter taskStackViewAdapter) {
+    public TaskStackHorizontalGridView setTaskStackViewAdapter(
+            TaskStackHorizontalViewAdapter taskStackViewAdapter) {
         if(mTaskStackHorizontalView != null) {
             mTaskStackHorizontalView.setAdapter(taskStackViewAdapter);
         }
+        return mTaskStackHorizontalView;
+    }
+
+    public TaskStackHorizontalGridView getGridView() {
+        return mTaskStackHorizontalView;
     }
 }
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 3343aec..e1f8699 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
@@ -24,6 +24,7 @@
 import android.util.TypedValue;
 import android.view.Display;
 import android.view.KeyEvent;
+import android.view.View;
 import android.view.WindowManager;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -31,6 +32,7 @@
 
 import com.android.systemui.R;
 import com.android.systemui.recents.tv.animations.DismissAnimationsHolder;
+import com.android.systemui.recents.tv.animations.RecentsRowFocusAnimationHolder;
 import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
 import com.android.systemui.recents.model.Task;
 
@@ -44,6 +46,7 @@
 
     private ViewFocusAnimator mViewFocusAnimator;
     private DismissAnimationsHolder mDismissAnimationsHolder;
+    private RecentsRowFocusAnimationHolder mRecentsRowFocusAnimationHolder;
 
     public TaskCardView(Context context) {
         this(context, null);
@@ -61,10 +64,13 @@
 
     @Override
     protected void onFinishInflate() {
+        super.onFinishInflate();
         mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
         mTitleTextView = (TextView) findViewById(R.id.card_title_text);
         mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
         mDismissAnimationsHolder = new DismissAnimationsHolder(this);
+        View title = findViewById(R.id.card_info_field);
+        mRecentsRowFocusAnimationHolder = new RecentsRowFocusAnimationHolder(this, title);
     }
 
     public void init(Task task) {
@@ -193,6 +199,10 @@
         mDismissAnimationsHolder.startDismissAnimation(listener);
     }
 
+    public RecentsRowFocusAnimationHolder getRecentsRowFocusAnimationHolder() {
+        return mRecentsRowFocusAnimationHolder;
+    }
+
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
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 5eb9fda..603721a 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,11 @@
  */
 package com.android.systemui.recents.tv.views;
 
+import android.animation.Animator;
+import android.animation.AnimatorSet;
 import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
 import android.support.v17.leanback.widget.HorizontalGridView;
 import android.util.AttributeSet;
 import android.view.View;
@@ -36,10 +40,19 @@
  * Horizontal Grid View Implementation to show the Task Stack for TV.
  */
 public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks {
-
+    private static final int ANIMATION_DELAY_MS = 50;
+    private static final int MSG_START_RECENT_ROW_FOCUS_ANIMATION = 100;
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            if (msg.what == MSG_START_RECENT_ROW_FOCUS_ANIMATION) {
+                startRecentsRowFocusAnimation(msg.arg1 == 1);
+            }
+        }
+    };
     private TaskStack mStack;
-    private ArrayList<TaskCardView> mTaskViews = new ArrayList<>();
     private Task mFocusedTask;
+    private AnimatorSet mRecentsRowFocusAnimation;
 
     public TaskStackHorizontalGridView(Context context) {
         this(context, null);
@@ -62,10 +75,18 @@
         super.onDetachedFromWindow();
         EventBus.getDefault().unregister(this);
     }
+
     /**
      * Resets this view for reuse.
      */
     public void reset() {
+        for (int i = 0; i < getChildCount(); i++) {
+            ((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder().reset();
+        }
+        if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
+            mRecentsRowFocusAnimation.cancel();
+        }
+        mHandler.removeCallbacksAndMessages(null);
         requestLayout();
     }
 
@@ -119,10 +140,8 @@
      * @return Child view for given task
      */
     public TaskCardView getChildViewForTask(Task task) {
-        List<TaskCardView> taskViews = getTaskViews();
-        int taskViewCount = taskViews.size();
-        for (int i = 0; i < taskViewCount; i++) {
-            TaskCardView tv = taskViews.get(i);
+        for (int i = 0; i < getChildCount(); i++) {
+            TaskCardView tv = (TaskCardView) getChildAt(i);
             if (tv.getTask() == task) {
                 return tv;
             }
@@ -130,12 +149,36 @@
         return null;
     }
 
-    public List<TaskCardView> getTaskViews() {
-        return mTaskViews;
+    /**
+     * Starts the focus change animation.
+     */
+    public void startRecentsRowFocusAnimation(final boolean hasFocus) {
+        if (getChildCount() == 0) {
+            // Animation request may happen before view is attached.
+            // Post again with small dealy so animation can be run again later.
+            if (getAdapter().getItemCount() > 0) {
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(
+                        MSG_START_RECENT_ROW_FOCUS_ANIMATION, hasFocus ? 1 : 0),
+                        ANIMATION_DELAY_MS);
+            }
+            return;
+        }
+        if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
+            mRecentsRowFocusAnimation.cancel();
+        }
+        Animator animator = ((TaskCardView) getChildAt(0)).getRecentsRowFocusAnimationHolder()
+                .getFocusChangeAnimator(hasFocus);
+        mRecentsRowFocusAnimation = new AnimatorSet();
+        AnimatorSet.Builder builder = mRecentsRowFocusAnimation.play(animator);
+        for (int i = 1; i < getChildCount(); i++) {
+            builder.with(((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder()
+                    .getFocusChangeAnimator(hasFocus));
+        }
+        mRecentsRowFocusAnimation.start();
     }
 
     @Override
-    public void onStackTaskAdded(TaskStack stack, Task newTask){
+    public void onStackTaskAdded(TaskStack stack, Task newTask) {
         getAdapter().notifyItemInserted(stack.getStackTasks().indexOf(newTask));
     }
 
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 e0d0486..21a43d5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -74,6 +74,8 @@
 import com.android.systemui.stackdivider.WindowManagerProxy;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -83,6 +85,8 @@
  */
 public class RecentsView extends FrameLayout {
 
+    private static final String TAG = "RecentsView";
+
     private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135;
     private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
     private static final float DEFAULT_SCRIM_ALPHA = 0.33f;
@@ -367,8 +371,10 @@
             int topBottomInsets = mSystemInsets.top + mSystemInsets.bottom;
             int childWidth = mEmptyView.getMeasuredWidth();
             int childHeight = mEmptyView.getMeasuredHeight();
-            int childLeft = left + Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
-            int childTop = top + Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
+            int childLeft = left + mSystemInsets.left +
+                    Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
+            int childTop = top + mSystemInsets.top +
+                    Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
             mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
         }
 
@@ -756,4 +762,22 @@
                 top + mStackActionButton.getMeasuredHeight());
         return actionButtonRect;
     }
+
+    public void dump(String prefix, PrintWriter writer) {
+        String innerPrefix = prefix + "  ";
+        String id = Integer.toHexString(System.identityHashCode(this));
+
+        writer.print(prefix); writer.print(TAG);
+        writer.print(" awaitingFirstLayout="); writer.print(mAwaitingFirstLayout ? "Y" : "N");
+        writer.print(" insets="); writer.print(Utilities.dumpRect(mSystemInsets));
+        writer.print(" [0x"); writer.print(id); writer.print("]");
+        writer.println();
+
+        if (mStack != null) {
+            mStack.dump(innerPrefix, writer);
+        }
+        if (mTaskStackView != null) {
+            mTaskStackView.dump(innerPrefix, writer);
+        }
+    }
 }
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 13ad9a5..07a1d4e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -16,40 +16,58 @@
 
 package com.android.systemui.recents.views;
 
-import android.app.Activity;
 import android.content.Context;
 import android.view.View;
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsActivity;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
 import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
+import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 
 /** Manages the scrims for the various system bars. */
 public class SystemBarScrimViews {
 
-    Context mContext;
+    private static final int DEFAULT_ANIMATION_DURATION = 150;
 
-    View mNavBarScrimView;
+    private Context mContext;
 
-    boolean mHasNavBarScrim;
-    boolean mShouldAnimateNavBarScrim;
+    private View mNavBarScrimView;
 
-    int mNavBarScrimEnterDuration;
+    private boolean mHasNavBarScrim;
+    private boolean mShouldAnimateNavBarScrim;
 
-    public SystemBarScrimViews(Activity activity) {
+    private int mNavBarScrimEnterDuration;
+
+    public SystemBarScrimViews(RecentsActivity activity) {
         mContext = activity;
         mNavBarScrimView = activity.findViewById(R.id.nav_bar_scrim);
+        mNavBarScrimView.forceHasOverlappingRendering(false);
         mNavBarScrimEnterDuration = activity.getResources().getInteger(
                 R.integer.recents_nav_bar_scrim_enter_duration);
     }
 
     /**
+     * Updates the nav bar scrim.
+     */
+    public void updateNavBarScrim(boolean animateNavBarScrim, boolean hasStackTasks,
+            AnimationProps animation) {
+        prepareEnterRecentsAnimation(isNavBarScrimRequired(hasStackTasks), animateNavBarScrim);
+        if (animateNavBarScrim && animation != null) {
+            animateNavBarScrimVisibility(true, animation);
+        }
+    }
+
+    /**
      * Prepares the scrim views for animating when entering Recents. This will be called before
      * the first draw, unless we are updating the scrim on configuration change.
      */
-    public void prepareEnterRecentsAnimation(boolean hasNavBarScrim, boolean animateNavBarScrim) {
+    private void prepareEnterRecentsAnimation(boolean hasNavBarScrim, boolean animateNavBarScrim) {
         mHasNavBarScrim = hasNavBarScrim;
         mShouldAnimateNavBarScrim = animateNavBarScrim;
 
@@ -60,7 +78,7 @@
     /**
      * Animates the nav bar scrim visibility.
      */
-    public void animateNavBarScrimVisibility(boolean visible, AnimationProps animation) {
+    private void animateNavBarScrimVisibility(boolean visible, AnimationProps animation) {
         int toY = 0;
         if (visible) {
             mNavBarScrimView.setVisibility(View.VISIBLE);
@@ -79,6 +97,14 @@
         }
     }
 
+    /**
+     * @return Whether to show the nav bar scrim.
+     */
+    private boolean isNavBarScrimRequired(boolean hasStackTasks) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        return hasStackTasks && !ssp.hasTransposedNavBar() && !ssp.hasDockedTask();
+    }
+
     /**** EventBus events ****/
 
     /**
@@ -101,21 +127,48 @@
      */
     public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
         if (mHasNavBarScrim) {
-            AnimationProps animation = new AnimationProps()
-                    .setDuration(AnimationProps.BOUNDS,
-                            TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
-                    .setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN);
+            AnimationProps animation = createBoundsAnimation(
+                    TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION);
             animateNavBarScrimVisibility(false, animation);
         }
     }
 
     public final void onBusEvent(DismissAllTaskViewsEvent event) {
         if (mHasNavBarScrim) {
-            AnimationProps animation = new AnimationProps()
-                    .setDuration(AnimationProps.BOUNDS,
-                            TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
-                    .setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN);
+            AnimationProps animation = createBoundsAnimation(
+                    TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION);
             animateNavBarScrimVisibility(false, animation);
         }
     }
+
+    public final void onBusEvent(ConfigurationChangedEvent event) {
+        animateScrimToCurrentNavBarState(event.hasStackTasks);
+    }
+
+    public final void onBusEvent(MultiWindowStateChangedEvent event) {
+        animateScrimToCurrentNavBarState(event.hasStackTasks);
+    }
+
+    /**
+     * Animates the scrim to match the state of the current nav bar.
+     */
+    private void animateScrimToCurrentNavBarState(boolean hasStackTasks) {
+        boolean hasNavBarScrim = isNavBarScrimRequired(hasStackTasks);
+        if (mHasNavBarScrim != hasNavBarScrim) {
+            AnimationProps animation = hasNavBarScrim
+                    ? createBoundsAnimation(DEFAULT_ANIMATION_DURATION)
+                    : AnimationProps.IMMEDIATE;
+            animateNavBarScrimVisibility(hasNavBarScrim, animation);
+        }
+        mHasNavBarScrim = hasNavBarScrim;
+    }
+
+    /**
+     * @return a default animation to aniamte the bounds of the scrim.
+     */
+    private AnimationProps createBoundsAnimation(int duration) {
+        return new AnimationProps()
+                .setDuration(AnimationProps.BOUNDS, duration)
+                .setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN);
+    }
 }
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 1c433d8..fe91f42 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -456,7 +456,8 @@
         TaskStack stack = mStackView.getStack();
 
         final float curScroll = stackScroller.getStackScroll();
-        final float newScroll = stackLayout.getStackScrollForTask(newFocusedTask);
+        final float newScroll = stackScroller.getBoundedStackScroll(
+                stackLayout.getStackScrollForTask(newFocusedTask));
         boolean willScrollToFront = newScroll > curScroll;
         boolean willScroll = Float.compare(newScroll, curScroll) != 0;
 
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 2508304..b75a91e 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.R;
 import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.RecentsDebugFlags;
@@ -38,6 +39,7 @@
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -108,6 +110,8 @@
  */
 public class TaskStackLayoutAlgorithm {
 
+    private static final String TAG = "TaskStackLayoutAlgorithm";
+
     // The distribution of view bounds alpha
     // XXX: This is a hack because you can currently set the max alpha to be > 1f
     public static final float OUTLINE_ALPHA_MIN_VALUE = 0f;
@@ -530,18 +534,24 @@
                 ? stack.indexOfStackTask(launchTask)
                 : mNumStackTasks - 1;
         if (getInitialFocusState() == STATE_FOCUSED) {
+            int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
+            float maxBottomNormX = getNormalizedXFromFocusedY(maxBottomOffset, FROM_BOTTOM);
+            mFocusedRange.offset(0f);
             mMinScrollP = 0;
-            mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
+            mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
+                    Math.max(0, mFocusedRange.getAbsoluteX(maxBottomNormX)));
             if (launchState.launchedFromHome) {
                 mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
             } else {
                 mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
             }
+            mInitialNormX = null;
         } 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;
+            mInitialNormX = null;
         } else {
             // Set the max scroll to be the point where the front most task is visible with the
             // stack bottom offset
@@ -553,7 +563,10 @@
                     Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
             boolean scrollToFront = launchState.launchedFromHome ||
                     launchState.launchedViaDockGesture;
-            if (scrollToFront) {
+            if (launchState.launchedWithAltTab) {
+                mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
+                mInitialNormX = null;
+            } else if (scrollToFront) {
                 mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
                 mInitialNormX = null;
             } else {
@@ -650,8 +663,9 @@
      * Returns the default focus state.
      */
     public int getInitialFocusState() {
+        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
         RecentsDebugFlags debugFlags = Recents.getDebugFlags();
-        if (debugFlags.isPagingEnabled()) {
+        if (debugFlags.isPagingEnabled() || launchState.launchedWithAltTab) {
             return STATE_FOCUSED;
         } else {
             return STATE_UNFOCUSED;
@@ -673,7 +687,6 @@
     }
 
     /**
-     *
      * Returns the current stack state.
      */
     public StackState getStackState() {
@@ -803,8 +816,9 @@
     public TaskViewTransform getStackTransformScreenCoordinates(Task task, float stackScroll,
             TaskViewTransform transformOut, TaskViewTransform frontTransform) {
         Rect windowRect = Recents.getSystemServices().getWindowRect();
-        TaskViewTransform transform = getStackTransform(task, stackScroll, transformOut,
-                frontTransform);
+        TaskViewTransform transform = getStackTransform(task, stackScroll, mFocusState,
+                transformOut, frontTransform, true /* forceUpdate */,
+                false /* ignoreTaskOverrides */);
         transform.rect.offset(windowRect.left, windowRect.top);
         return transform;
     }
@@ -1024,6 +1038,18 @@
     }
 
     /**
+     * Returns the normalized x on the focused curve given an absolute Y position (relative to the
+     * stack height).
+     */
+    private float getNormalizedXFromFocusedY(float y, @AnchorSide int fromSide) {
+        float offset = (fromSide == FROM_TOP)
+                ? mStackRect.height() - y
+                : y;
+        float offsetPct = offset / mStackRect.height();
+        return mFocusedCurveInterpolator.getX(offsetPct);
+    }
+
+    /**
      * Creates a new path for the focused curve.
      */
     private Path constructFocusedCurve() {
@@ -1033,10 +1059,13 @@
         float topPeekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
         float bottomPeekHeightPct = (float) (mStackBottomOffset + mFocusedBottomPeekHeight) /
                 mStackRect.height();
+        float minBottomPeekHeightPct = (float) (mFocusedTopPeekHeight + mTaskRect.height() -
+                mMinMargin) / mStackRect.height();
         Path p = new Path();
         p.moveTo(0f, 1f);
         p.lineTo(0.5f, 1f - topPeekHeightPct);
-        p.lineTo(1f - (0.5f / mFocusedRange.relativeMax), bottomPeekHeightPct);
+        p.lineTo(1f - (0.5f / mFocusedRange.relativeMax), Math.max(1f - minBottomPeekHeightPct,
+                bottomPeekHeightPct));
         p.lineTo(1f, 0f);
         return p;
     }
@@ -1130,4 +1159,44 @@
         mBackOfStackTransform.visible = true;
         mFrontOfStackTransform.visible = true;
     }
-}
+
+    public void dump(String prefix, PrintWriter writer) {
+        String innerPrefix = prefix + "  ";
+
+        writer.print(prefix); writer.print(TAG);
+        writer.write(" numStackTasks="); writer.write(mNumStackTasks);
+        writer.println();
+
+        writer.print(innerPrefix);
+        writer.print("insets="); writer.print(Utilities.dumpRect(mSystemInsets));
+        writer.print(" stack="); writer.print(Utilities.dumpRect(mStackRect));
+        writer.print(" task="); writer.print(Utilities.dumpRect(mTaskRect));
+        writer.print(" freeform="); writer.print(Utilities.dumpRect(mFreeformRect));
+        writer.print(" actionButton="); writer.print(Utilities.dumpRect(mStackActionButtonRect));
+        writer.println();
+
+        writer.print(innerPrefix);
+        writer.print("minScroll="); writer.print(mMinScrollP);
+        writer.print(" maxScroll="); writer.print(mMaxScrollP);
+        writer.print(" initialScroll="); writer.print(mInitialScrollP);
+        writer.println();
+
+        writer.print(innerPrefix);
+        writer.print("focusState="); writer.print(mFocusState);
+        writer.println();
+
+        if (mTaskIndexOverrideMap.size() > 0) {
+            for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
+                int taskId = mTaskIndexOverrideMap.keyAt(i);
+                float x = mTaskIndexMap.get(taskId);
+                float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);
+
+                writer.print(innerPrefix);
+                writer.print("taskId= "); writer.print(taskId);
+                writer.print(" x= "); writer.print(x);
+                writer.print(" overrideX= "); writer.print(overrideX);
+                writer.println();
+            }
+        }
+    }
+}
\ No newline at end of file
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 5416a48..13c8403 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -90,6 +90,7 @@
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -102,6 +103,8 @@
         TaskStackLayoutAlgorithm.TaskStackLayoutAlgorithmCallbacks,
         ViewPool.ViewPoolConsumer<TaskView, Task> {
 
+    private static final String TAG = "TaskStackView";
+
     private final static String KEY_SAVED_STATE_SUPER = "saved_instance_state_super";
     private final static String KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE =
             "saved_instance_state_layout_focused_state";
@@ -2067,4 +2070,37 @@
         mScreenPinningEnabled = ssp.getSystemSetting(getContext(),
                 Settings.System.LOCK_TO_APP_ENABLED) != 0;
     }
+
+    public void dump(String prefix, PrintWriter writer) {
+        String innerPrefix = prefix + "  ";
+        String id = Integer.toHexString(System.identityHashCode(this));
+
+        writer.print(prefix); writer.print(TAG);
+        writer.print(" hasDefRelayout=");
+        writer.print(mDeferredTaskViewLayoutAnimation != null ? "Y" : "N");
+        writer.print(" clipDirty="); writer.print(mTaskViewsClipDirty ? "Y" : "N");
+        writer.print(" awaitingFirstLayout="); writer.print(mAwaitingFirstLayout ? "Y" : "N");
+        writer.print(" initialState="); writer.print(mInitialState);
+        writer.print(" inMeasureLayout="); writer.print(mInMeasureLayout ? "Y" : "N");
+        writer.print(" enterAnimCompleted="); writer.print(mEnterAnimationComplete ? "Y" : "N");
+        writer.print(" touchExplorationOn="); writer.print(mTouchExplorationEnabled ? "Y" : "N");
+        writer.print(" screenPinningOn="); writer.print(mScreenPinningEnabled ? "Y" : "N");
+        writer.print(" numIgnoreTasks="); writer.print(mIgnoreTasks.size());
+        writer.print(" numViewPool="); writer.print(mViewPool.getViews().size());
+        writer.print(" stableStackBounds="); writer.print(Utilities.dumpRect(mStableStackBounds));
+        writer.print(" stackBounds="); writer.print(Utilities.dumpRect(mStackBounds));
+        writer.print(" stableWindow="); writer.print(Utilities.dumpRect(mStableWindowRect));
+        writer.print(" window="); writer.print(Utilities.dumpRect(mWindowRect));
+        writer.print(" [0x"); writer.print(id); writer.print("]");
+        writer.println();
+
+        if (mFocusedTask != null) {
+            writer.print(innerPrefix);
+            writer.print("Focused task: ");
+            mFocusedTask.dump(innerPrefix, writer);
+        }
+
+        mLayoutAlgorithm.dump(innerPrefix, writer);
+        mStackScroller.dump(innerPrefix, writer);
+    }
 }
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 583fb88..19b3c94 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -30,6 +30,8 @@
 import com.android.systemui.R;
 import com.android.systemui.recents.misc.Utilities;
 
+import java.io.PrintWriter;
+
 /* The scrolling logic for a TaskStackView */
 public class TaskStackViewScroller {
 
@@ -246,4 +248,10 @@
             mScroller.abortAnimation();
         }
     }
+
+    public void dump(String prefix, PrintWriter writer) {
+        writer.print(prefix); writer.print(TAG);
+        writer.print(" stackScroll:"); writer.print(mStackScrollP);
+        writer.println();
+    }
 }
\ No newline at end of file
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 a2f61c2..570ff8a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -459,7 +459,7 @@
         if (!mTitleView.getText().toString().equals(t.title)) {
             mTitleView.setText(t.title);
         }
-        mTitleView.setContentDescription(t.contentDescription);
+        mTitleView.setContentDescription(t.titleDescription);
         mTitleView.setTextColor(t.useLightOnPrimaryColor ?
                 mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
         if (!t.isDockable && ssp.hasDockedTask()) {
@@ -501,6 +501,7 @@
 
         // In accessibility, a single click on the focused app info button will show it
         if (touchExplorationEnabled) {
+            mIconView.setContentDescription(t.appInfoDescription);
             mIconView.setOnClickListener(this);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 3eeabc7..e5ac0d3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -141,9 +141,9 @@
             return;
         }
 
+        int viewWidth = mTaskViewRect.width();
+        int viewHeight = mTaskViewRect.height();
         if (mBitmapShader != null) {
-            int viewWidth = mTaskViewRect.width();
-            int viewHeight = mTaskViewRect.height();
 
             // We are drawing the thumbnail in the same orientation, so just fit the width
             int thumbnailWidth = (int) (mThumbnailRect.width() * mThumbnailScale);
@@ -180,6 +180,9 @@
 
                 canvas.restoreToCount(count);
             }
+        } else {
+            canvas.drawRoundRect(0, 0, viewWidth, viewHeight, mCornerRadius, mCornerRadius,
+                    mBgFillPaint);
         }
     }
 
@@ -319,12 +322,12 @@
         mDisabledInSafeMode = disabledInSafeMode;
         if (t.thumbnail != null) {
             setThumbnail(t.thumbnail, thumbnailInfo);
-            if (t.colorBackground != 0) {
-                mBgFillPaint.setColor(t.colorBackground);
-            }
         } else {
             setThumbnail(null, null);
         }
+        if (t.colorBackground != 0) {
+            mBgFillPaint.setColor(t.colorBackground);
+        }
     }
 
     /** Unbinds the thumbnail view from the task */
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index e8cf126..d294c80 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -34,8 +34,6 @@
  * Controls the docked stack divider.
  */
 public class Divider extends SystemUI {
-    private static final String TAG = "Divider";
-    private int mDividerWindowWidth;
     private DividerWindowManager mWindowManager;
     private DividerView mView;
     private DockDividerVisibilityListener mDockDividerVisibilityListener;
@@ -46,8 +44,6 @@
     @Override
     public void start() {
         mWindowManager = new DividerWindowManager(mContext);
-        mDividerWindowWidth = mContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.docked_stack_divider_thickness);
         update(mContext.getResources().getConfiguration());
         putComponent(Divider.class, this);
         mDockDividerVisibilityListener = new DockDividerVisibilityListener();
@@ -70,9 +66,11 @@
         mView = (DividerView)
                 LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
         mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
+        final int size = mContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_thickness);
         final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
-        final int width = landscape ? mDividerWindowWidth : MATCH_PARENT;
-        final int height = landscape ? MATCH_PARENT : mDividerWindowWidth;
+        final int width = landscape ? size : MATCH_PARENT;
+        final int height = landscape ? MATCH_PARENT : size;
         mWindowManager.add(mView, width, height);
         mView.setWindowManager(mWindowManager);
     }
@@ -97,6 +95,9 @@
                 if (mVisible != visible) {
                     mVisible = visible;
                     mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+
+                    // Update state because animations won't finish.
+                    mView.setMinimizedDockStack(mMinimized);
                 }
             }
         });
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 7a933cd..3005535 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -134,6 +134,7 @@
     private ValueAnimator mCurrentAnimator;
     private boolean mEntranceAnimationRunning;
     private GestureDetector mGestureDetector;
+    private boolean mDockedStackMinimized;
 
     private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
         @Override
@@ -239,16 +240,6 @@
     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
@@ -273,6 +264,15 @@
         return super.onApplyWindowInsets(insets);
     }
 
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (changed) {
+            mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
+                    mHandle.getRight(), mHandle.getBottom()));
+        }
+    }
+
     public void setWindowManager(DividerWindowManager windowManager) {
         mWindowManager = windowManager;
     }
@@ -538,6 +538,7 @@
                     : mBackground.getWidth());
             mBackground.setScaleX(MINIMIZE_DOCK_SCALE);
         }
+        mDockedStackMinimized = minimized;
     }
 
     public void setMinimizedDockStack(boolean minimized, long animDuration) {
@@ -566,6 +567,7 @@
                 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                 .setDuration(animDuration)
                 .start();
+        mDockedStackMinimized = minimized;
     }
 
     private void resetBackground() {
@@ -883,7 +885,7 @@
 
     public final void onBusEvent(UndockingTaskEvent undockingTaskEvent) {
         int dockSide = mWindowManagerProxy.getDockSide();
-        if (dockSide != WindowManager.DOCKED_INVALID) {
+        if (dockSide != WindowManager.DOCKED_INVALID && !mDockedStackMinimized) {
             startDragging(false /* animate */, false /* touching */);
             SnapTarget target = dockSideTopLeft(dockSide)
                     ? mSnapAlgorithm.getDismissEndTarget()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 0e21517..1b2393a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -19,7 +19,9 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
 import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
 import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -89,6 +91,7 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -98,6 +101,7 @@
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.NotificationGuts.OnGutsClosedListener;
 import com.android.systemui.statusbar.phone.NavigationBarView;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -105,7 +109,6 @@
 import com.android.systemui.statusbar.policy.PreviewInflater;
 import com.android.systemui.statusbar.policy.RemoteInputView;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.GearDisplayedListener;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
 import java.util.ArrayList;
@@ -113,12 +116,12 @@
 import java.util.Locale;
 
 import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
-import static com.android.keyguard.KeyguardHostView.OnDismissAction;
 
 public abstract class BaseStatusBar extends SystemUI implements
         CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
         ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
-        ExpandableNotificationRow.OnExpandClickListener, GearDisplayedListener {
+        ExpandableNotificationRow.OnExpandClickListener,
+        OnGutsClosedListener {
     public static final String TAG = "StatusBar";
     public static final boolean DEBUG = false;
     public static final boolean MULTIUSER_DEBUG = false;
@@ -240,7 +243,6 @@
 
     // which notification is currently being longpress-examined by the user
     private NotificationGuts mNotificationGutsExposed;
-    private ExpandableNotificationRow mNotificationGearDisplayed;
 
     private KeyboardShortcuts mKeyboardShortcuts;
 
@@ -285,9 +287,10 @@
     private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) {
         @Override
         public void onChange(boolean selfChange) {
-            // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
-            // so we just dump our cache ...
+            // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
+            // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
             mUsersAllowingPrivateNotifications.clear();
+            mUsersAllowingNotifications.clear();
             // ... and refresh all the notifications
             updateNotifications();
         }
@@ -347,7 +350,7 @@
                 }, afterKeyguardGone);
                 return true;
             } else {
-                return super.onClickHandler(view, pendingIntent, fillInIntent);
+                return superOnClickHandler(view, pendingIntent, fillInIntent);
             }
         }
 
@@ -384,7 +387,8 @@
 
         private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
                 Intent fillInIntent) {
-            return super.onClickHandler(view, pendingIntent, fillInIntent);
+            return super.onClickHandler(view, pendingIntent, fillInIntent,
+                    StackId.FULLSCREEN_WORKSPACE_STACK_ID);
         }
 
         private boolean handleRemoteInput(View view, PendingIntent pendingIntent, Intent fillInIntent) {
@@ -990,7 +994,7 @@
                             }
                             TaskStackBuilder.create(mContext)
                                     .addNextIntentWithParentStack(intent)
-                                    .startActivities(null,
+                                    .startActivities(getActivityOptions(),
                                             new UserHandle(UserHandle.getUserId(appUid)));
                             overrideActivityPendingAppTransition(keyguardShowing);
                         } catch (RemoteException e) {
@@ -1009,6 +1013,7 @@
         PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
         row.setTag(sbn.getPackageName());
         final NotificationGuts guts = row.getGuts();
+        guts.setClosedListener(this);
         final String pkg = sbn.getPackageName();
         String appname = pkg;
         Drawable pkgicon = null;
@@ -1036,6 +1041,7 @@
             settingsButton.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
                     MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
+                    guts.resetFalsingCheck();
                     startAppNotificationSettingsActivity(pkg, appUidF);
                 }
             });
@@ -1046,26 +1052,41 @@
         row.findViewById(R.id.done).setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                guts.saveImportance(sbn);
-
-                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);
+                // If the user has security enabled, show challenge if the setting is changed.
+                if (guts.hasImportanceChanged() && isLockscreenPublicMode() &&
+                        (mState == StatusBarState.KEYGUARD
+                        || mState == StatusBarState.SHADE_LOCKED)) {
+                    OnDismissAction dismissAction = new OnDismissAction() {
+                        @Override
+                        public boolean onDismiss() {
+                            saveImportanceCloseControls(sbn, row, guts, v);
+                            return true;
+                        }
+                    };
+                    onLockedNotificationImportanceChange(dismissAction);
+                } else {
+                    saveImportanceCloseControls(sbn, row, guts, v);
+                }
             }
         });
-
         guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey()));
     }
 
-    protected GearDisplayedListener getGearDisplayedListener() {
-        return this;
+    private void saveImportanceCloseControls(StatusBarNotification sbn,
+            ExpandableNotificationRow row, NotificationGuts guts, View done) {
+        guts.resetFalsingCheck();
+        guts.saveImportance(sbn);
+
+        int[] rowLocation = new int[2];
+        int[] doneLocation = new int[2];
+        row.getLocationOnScreen(rowLocation);
+        done.getLocationOnScreen(doneLocation);
+
+        final int centerX = done.getWidth() / 2;
+        final int centerY = done.getHeight() / 2;
+        final int x = doneLocation[0] - rowLocation[0] + centerX;
+        final int y = doneLocation[1] - rowLocation[1] + centerY;
+        dismissPopups(x, y);
     }
 
     protected SwipeHelper.LongPressListener getNotificationLongClicker() {
@@ -1103,7 +1124,8 @@
                 // Post to ensure the the guts are properly laid out.
                 guts.post(new Runnable() {
                     public void run() {
-                        dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */);
+                        dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */,
+                                false /* animate */);
                         guts.setVisibility(View.VISIBLE);
                         final double horz = Math.max(guts.getWidth() - x, x);
                         final double vert = Math.max(guts.getHeight() - y, y);
@@ -1121,7 +1143,8 @@
                             }
                         });
                         a.start();
-                        guts.setExposed(true);
+                        guts.setExposed(true /* exposed */,
+                                mState == StatusBarState.KEYGUARD /* needsFalsingProtection */);
                         row.closeRemoteInput();
                         mStackScroller.onHeightChanged(null, true /* needsAnimation */);
                         mNotificationGutsExposed = guts;
@@ -1132,53 +1155,34 @@
         };
     }
 
-    @Override
-    public void onGearDisplayed(ExpandableNotificationRow row) {
-        MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
-                row.getStatusBarNotification().getPackageName());
-        mNotificationGearDisplayed = row;
+    /**
+     * Returns the exposed NotificationGuts or null if none are exposed.
+     */
+    public NotificationGuts getExposedGuts() {
+        return mNotificationGutsExposed;
     }
 
     public void dismissPopups() {
-        dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */);
+        dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */, false /* animate */);
     }
 
     private void dismissPopups(int x, int y) {
-        dismissPopups(x, y, true /* resetGear */);
+        dismissPopups(x, y, true /* resetGear */, false /* animate */);
     }
 
-    public void dismissPopups(int x, int y, boolean resetGear) {
+    public void dismissPopups(int x, int y, boolean resetGear, boolean animate) {
         if (mNotificationGutsExposed != null) {
-            final NotificationGuts v = mNotificationGutsExposed;
-            mNotificationGutsExposed = null;
+            mNotificationGutsExposed.closeControls(x, y, true /* notify */);
+        }
+        if (resetGear) {
+            mStackScroller.resetExposedGearView(animate, true /* force */);
+        }
+    }
 
-            if (v.getWindowToken() == null) return;
-            if (x == -1 || y == -1) {
-                x = (v.getLeft() + v.getRight()) / 2;
-                y = (v.getTop() + v.getHeight() / 2);
-            }
-            final double horz = Math.max(v.getWidth() - x, x);
-            final double vert = Math.max(v.getHeight() - y, y);
-            final float r = (float) Math.hypot(horz, vert);
-            final Animator a = ViewAnimationUtils.createCircularReveal(v,
-                    x, y, r, 0);
-            a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-            a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-            a.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    super.onAnimationEnd(animation);
-                    v.setVisibility(View.GONE);
-                }
-            });
-            a.start();
-            v.setExposed(false);
-            mStackScroller.onHeightChanged(null, true /* needsAnimation */);
-        }
-        if (resetGear && mNotificationGearDisplayed != null) {
-            mNotificationGearDisplayed.resetTranslation();
-            mNotificationGearDisplayed = null;
-        }
+    @Override
+    public void onGutsClosed(NotificationGuts guts) {
+        mStackScroller.onHeightChanged(null, true /* needsAnimation */);
+        mNotificationGutsExposed = null;
     }
 
     @Override
@@ -1453,6 +1457,8 @@
         }
     }
 
+    protected void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {}
+
     protected void onLockedRemoteInput(ExpandableNotificationRow row, View clickedView) {}
 
     @Override
@@ -1740,7 +1746,7 @@
                         } catch (RemoteException e) {
                         }
                         try {
-                            intent.send();
+                            intent.send(null, 0, null, null, null, null, getActivityOptions());
                         } catch (PendingIntent.CanceledException e) {
                             // the stack trace isn't very helpful here.
                             // Just log the exception message.
@@ -1840,15 +1846,17 @@
                                             .getIdentifier();
                                     if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
                                             && mKeyguardManager.isDeviceLocked(userId)) {
-                                        // Show work challenge, do not run pendingintent and
-                                        // remove notification
-                                        startWorkChallenge(userId, intent.getIntentSender(),
-                                                notificationKey);
-                                        return;
+                                        if (startWorkChallengeIfNecessary(userId,
+                                                intent.getIntentSender(), notificationKey)) {
+                                            // Show work challenge, do not run pendingintent and
+                                            // remove notification
+                                            return;
+                                        }
                                     }
                                 }
                                 try {
-                                    intent.send();
+                                    intent.send(null, 0, null, null, null, null,
+                                            getActivityOptions());
                                 } catch (PendingIntent.CanceledException e) {
                                     // the stack trace isn't very helpful here.
                                     // Just log the exception message.
@@ -1881,21 +1889,25 @@
             }, afterKeyguardGone);
         }
 
-        public void startWorkChallenge(int userId, IntentSender intendSender,
+        public boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
                 String notificationKey) {
+            final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
+                    null, userId);
+            if (newIntent == null) {
+                return false;
+            }
             final Intent callBackIntent = new Intent(
                     WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
             callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
             callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
             callBackIntent.setPackage(mContext.getPackageName());
 
-            final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
-                    null, userId);
             newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                     | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_CLEAR_TASK);
             newIntent.putExtra(Intent.EXTRA_INTENT, PendingIntent
                     .getBroadcast(mContext, 0, callBackIntent, 0).getIntentSender());
             mContext.startActivity(newIntent);
+            return true;
         }
 
         public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
@@ -1924,6 +1936,14 @@
         }
     }
 
+    protected Bundle getActivityOptions() {
+        // Anything launched from the notification shade should always go into the
+        // fullscreen stack.
+        ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchStackId(StackId.FULLSCREEN_WORKSPACE_STACK_ID);
+        return options.toBundle();
+    }
+
     protected void visibilityChanged(boolean visible) {
         if (mVisible != visible) {
             mVisible = visible;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 7f87c3c..2dabf5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -170,22 +170,22 @@
                 : RUBBERBAND_FACTOR_STATIC;
         float rubberband = heightDelta * rubberbandFactor;
         if (expandable
-                && (rubberband + child.getMinExpandHeight()) > child.getMaxContentHeight()) {
+                && (rubberband + child.getCollapsedHeight()) > child.getMaxContentHeight()) {
             float overshoot =
-                    (rubberband + child.getMinExpandHeight()) - child.getMaxContentHeight();
+                    (rubberband + child.getCollapsedHeight()) - child.getMaxContentHeight();
             overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
             rubberband -= overshoot;
         }
-        child.setActualHeight((int) (child.getMinExpandHeight() + rubberband));
+        child.setActualHeight((int) (child.getCollapsedHeight() + rubberband));
     }
 
     private void cancelExpansion(final ExpandableView child) {
-        if (child.getActualHeight() == child.getMinExpandHeight()) {
+        if (child.getActualHeight() == child.getCollapsedHeight()) {
             mCallback.setUserLockedChild(child, false);
             return;
         }
         ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
-                child.getActualHeight(), child.getMinExpandHeight());
+                child.getActualHeight(), child.getCollapsedHeight());
         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 f9edeb3..7ca7d12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -470,7 +470,7 @@
         if(mExpandedWhenPinned) {
             return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
         } else if (atLeastMinHeight) {
-            return Math.max(getMinHeight(), mHeadsUpHeight);
+            return Math.max(getCollapsedHeight(), mHeadsUpHeight);
         } else {
             return mHeadsUpHeight;
         }
@@ -1040,12 +1040,12 @@
             } else if (isExpanded()) {
                 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
             } else {
-                return Math.max(getMinHeight(), mHeadsUpHeight);
+                return Math.max(getCollapsedHeight(), mHeadsUpHeight);
             }
         } else if (isExpanded()) {
             return getMaxExpandHeight();
         } else {
-            return getMinHeight();
+            return getCollapsedHeight();
         }
     }
 
@@ -1301,9 +1301,9 @@
     }
 
     @Override
-    public int getMinExpandHeight() {
+    public int getCollapsedHeight() {
         if (mIsSummaryWithChildren && !mShowingPublic) {
-            return mChildrenContainer.getMinExpandHeight();
+            return mChildrenContainer.getCollapsedHeight();
         }
         return getMinHeight();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 91418ad..6dcd61f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -153,11 +153,11 @@
     }
 
     /**
-     * @return The minimum height this child chan be expanded to. Note that this might be different
-     * than {@link #getMinHeight()} because some elements can't be collapsed by an expand gesture
-     * to it's absolute minimal height
+     * @return The collapsed height of this view. Note that this might be different
+     * than {@link #getMinHeight()} because some elements like groups may have different sizes when
+     * they are system expanded.
      */
-    public int getMinExpandHeight() {
+    public int getCollapsedHeight() {
         return getHeight();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 8fe60a0..977a77d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -21,6 +21,9 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
 import android.hardware.input.InputManager;
 import android.os.Handler;
 import android.os.Looper;
@@ -37,6 +40,7 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager.KeyboardShortcutsReceiver;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
@@ -52,158 +56,13 @@
 /**
  * Contains functionality for handling keyboard shortcuts.
  */
-public class KeyboardShortcuts {
+public final class KeyboardShortcuts {
     private static final String TAG = KeyboardShortcuts.class.getSimpleName();
 
-    private static final SparseArray<String> SPECIAL_CHARACTER_NAMES = new SparseArray<>();
-    private static final SparseArray<String> MODIFIER_NAMES = new SparseArray<>();
-
-    private static void loadSpecialCharacterNames(Context context) {
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_HOME, context.getString(R.string.keyboard_key_home));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_BACK, context.getString(R.string.keyboard_key_back));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_DPAD_UP, context.getString(R.string.keyboard_key_dpad_up));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_DPAD_DOWN, context.getString(R.string.keyboard_key_dpad_down));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_DPAD_LEFT, context.getString(R.string.keyboard_key_dpad_left));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_DPAD_RIGHT, context.getString(R.string.keyboard_key_dpad_right));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_DPAD_CENTER, context.getString(R.string.keyboard_key_dpad_center));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_PERIOD, ".");
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_TAB, context.getString(R.string.keyboard_key_tab));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_SPACE, context.getString(R.string.keyboard_key_space));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_ENTER, context.getString(R.string.keyboard_key_enter));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_DEL, context.getString(R.string.keyboard_key_backspace));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
-                context.getString(R.string.keyboard_key_media_play_pause));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_MEDIA_STOP, context.getString(R.string.keyboard_key_media_stop));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_MEDIA_NEXT, context.getString(R.string.keyboard_key_media_next));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PREVIOUS,
-                context.getString(R.string.keyboard_key_media_previous));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_REWIND,
-                context.getString(R.string.keyboard_key_media_rewind));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
-                context.getString(R.string.keyboard_key_media_fast_forward));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_PAGE_UP, context.getString(R.string.keyboard_key_page_up));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_PAGE_DOWN, context.getString(R.string.keyboard_key_page_down));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_A,
-                context.getString(R.string.keyboard_key_button_template, "A"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_B,
-                context.getString(R.string.keyboard_key_button_template, "B"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_C,
-                context.getString(R.string.keyboard_key_button_template, "C"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_X,
-                context.getString(R.string.keyboard_key_button_template, "X"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Y,
-                context.getString(R.string.keyboard_key_button_template, "Y"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Z,
-                context.getString(R.string.keyboard_key_button_template, "Z"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L1,
-                context.getString(R.string.keyboard_key_button_template, "L1"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R1,
-                context.getString(R.string.keyboard_key_button_template, "R1"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L2,
-                context.getString(R.string.keyboard_key_button_template, "L2"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R2,
-                context.getString(R.string.keyboard_key_button_template, "R2"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_START,
-                context.getString(R.string.keyboard_key_button_template, "Start"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_SELECT,
-                context.getString(R.string.keyboard_key_button_template, "Select"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_MODE,
-                context.getString(R.string.keyboard_key_button_template, "Mode"));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_FORWARD_DEL, context.getString(R.string.keyboard_key_forward_del));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ESCAPE, "Esc");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SYSRQ, "SysRq");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BREAK, "Break");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SCROLL_LOCK, "Scroll Lock");
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_MOVE_HOME, context.getString(R.string.keyboard_key_move_home));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_MOVE_END, context.getString(R.string.keyboard_key_move_end));
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_INSERT, context.getString(R.string.keyboard_key_insert));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F1, "F1");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F2, "F2");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F3, "F3");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F4, "F4");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F5, "F5");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F6, "F6");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F7, "F7");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F8, "F8");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F9, "F9");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F10, "F10");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F11, "F11");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F12, "F12");
-        SPECIAL_CHARACTER_NAMES.put(
-                KeyEvent.KEYCODE_NUM_LOCK, context.getString(R.string.keyboard_key_num_lock));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_0,
-                context.getString(R.string.keyboard_key_numpad_template, "0"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_1,
-                context.getString(R.string.keyboard_key_numpad_template, "1"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_2,
-                context.getString(R.string.keyboard_key_numpad_template, "2"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_3,
-                context.getString(R.string.keyboard_key_numpad_template, "3"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_4,
-                context.getString(R.string.keyboard_key_numpad_template, "4"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_5,
-                context.getString(R.string.keyboard_key_numpad_template, "5"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_6,
-                context.getString(R.string.keyboard_key_numpad_template, "6"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_7,
-                context.getString(R.string.keyboard_key_numpad_template, "7"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_8,
-                context.getString(R.string.keyboard_key_numpad_template, "8"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_9,
-                context.getString(R.string.keyboard_key_numpad_template, "9"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE,
-                context.getString(R.string.keyboard_key_numpad_template, "/"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY,
-                context.getString(R.string.keyboard_key_numpad_template, "*"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT,
-                context.getString(R.string.keyboard_key_numpad_template, "-"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ADD,
-                context.getString(R.string.keyboard_key_numpad_template, "+"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DOT,
-                context.getString(R.string.keyboard_key_numpad_template, "."));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_COMMA,
-                context.getString(R.string.keyboard_key_numpad_template, ","));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ENTER,
-                context.getString(R.string.keyboard_key_numpad_template,
-                        context.getString(R.string.keyboard_key_enter)));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_EQUALS,
-                context.getString(R.string.keyboard_key_numpad_template, "="));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN,
-                context.getString(R.string.keyboard_key_numpad_template, "("));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN,
-                context.getString(R.string.keyboard_key_numpad_template, ")"));
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ZENKAKU_HANKAKU, "半角/全角");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_EISU, "英数");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MUHENKAN, "無変換");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_HENKAN, "変換");
-        SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな");
-
-        MODIFIER_NAMES.put(KeyEvent.META_META_ON, "Meta");
-        MODIFIER_NAMES.put(KeyEvent.META_CTRL_ON, "Ctrl");
-        MODIFIER_NAMES.put(KeyEvent.META_ALT_ON, "Alt");
-        MODIFIER_NAMES.put(KeyEvent.META_SHIFT_ON, "Shift");
-        MODIFIER_NAMES.put(KeyEvent.META_SYM_ON, "Sym");
-        MODIFIER_NAMES.put(KeyEvent.META_FUNCTION_ON, "Fn");
-    }
+    private final SparseArray<String> mSpecialCharacterNames = new SparseArray<>();
+    private final SparseArray<String> mModifierNames = new SparseArray<>();
+    private final SparseArray<Drawable> mSpecialCharacterDrawables = new SparseArray<>();
+    private final SparseArray<Drawable> mModifierDrawables = new SparseArray<>();
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
     private final Context mContext;
@@ -218,9 +77,170 @@
 
     public KeyboardShortcuts(Context context) {
         this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
-        if (SPECIAL_CHARACTER_NAMES.size() == 0) {
-            loadSpecialCharacterNames(context);
-        }
+        loadResources(context);
+    }
+
+    private void loadResources(Context context) {
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_HOME, context.getString(R.string.keyboard_key_home));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_BACK, context.getString(R.string.keyboard_key_back));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_DPAD_UP, context.getString(R.string.keyboard_key_dpad_up));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_DPAD_DOWN, context.getString(R.string.keyboard_key_dpad_down));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_DPAD_LEFT, context.getString(R.string.keyboard_key_dpad_left));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_DPAD_RIGHT, context.getString(R.string.keyboard_key_dpad_right));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_DPAD_CENTER, context.getString(R.string.keyboard_key_dpad_center));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_PERIOD, ".");
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_TAB, context.getString(R.string.keyboard_key_tab));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_SPACE, context.getString(R.string.keyboard_key_space));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_ENTER, context.getString(R.string.keyboard_key_enter));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_DEL, context.getString(R.string.keyboard_key_backspace));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
+                context.getString(R.string.keyboard_key_media_play_pause));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_MEDIA_STOP, context.getString(R.string.keyboard_key_media_stop));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_MEDIA_NEXT, context.getString(R.string.keyboard_key_media_next));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_PREVIOUS,
+                context.getString(R.string.keyboard_key_media_previous));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_REWIND,
+                context.getString(R.string.keyboard_key_media_rewind));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
+                context.getString(R.string.keyboard_key_media_fast_forward));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_PAGE_UP, context.getString(R.string.keyboard_key_page_up));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_PAGE_DOWN, context.getString(R.string.keyboard_key_page_down));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_A,
+                context.getString(R.string.keyboard_key_button_template, "A"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_B,
+                context.getString(R.string.keyboard_key_button_template, "B"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_C,
+                context.getString(R.string.keyboard_key_button_template, "C"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_X,
+                context.getString(R.string.keyboard_key_button_template, "X"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_Y,
+                context.getString(R.string.keyboard_key_button_template, "Y"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_Z,
+                context.getString(R.string.keyboard_key_button_template, "Z"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_L1,
+                context.getString(R.string.keyboard_key_button_template, "L1"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_R1,
+                context.getString(R.string.keyboard_key_button_template, "R1"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_L2,
+                context.getString(R.string.keyboard_key_button_template, "L2"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_R2,
+                context.getString(R.string.keyboard_key_button_template, "R2"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_START,
+                context.getString(R.string.keyboard_key_button_template, "Start"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_SELECT,
+                context.getString(R.string.keyboard_key_button_template, "Select"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_MODE,
+                context.getString(R.string.keyboard_key_button_template, "Mode"));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_FORWARD_DEL, context.getString(R.string.keyboard_key_forward_del));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_ESCAPE, "Esc");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_SYSRQ, "SysRq");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_BREAK, "Break");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_SCROLL_LOCK, "Scroll Lock");
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_MOVE_HOME, context.getString(R.string.keyboard_key_move_home));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_MOVE_END, context.getString(R.string.keyboard_key_move_end));
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_INSERT, context.getString(R.string.keyboard_key_insert));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F1, "F1");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F2, "F2");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F3, "F3");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F4, "F4");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F5, "F5");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F6, "F6");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F7, "F7");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F8, "F8");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F9, "F9");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F10, "F10");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F11, "F11");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_F12, "F12");
+        mSpecialCharacterNames.put(
+                KeyEvent.KEYCODE_NUM_LOCK, context.getString(R.string.keyboard_key_num_lock));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_0,
+                context.getString(R.string.keyboard_key_numpad_template, "0"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_1,
+                context.getString(R.string.keyboard_key_numpad_template, "1"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_2,
+                context.getString(R.string.keyboard_key_numpad_template, "2"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_3,
+                context.getString(R.string.keyboard_key_numpad_template, "3"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_4,
+                context.getString(R.string.keyboard_key_numpad_template, "4"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_5,
+                context.getString(R.string.keyboard_key_numpad_template, "5"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_6,
+                context.getString(R.string.keyboard_key_numpad_template, "6"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_7,
+                context.getString(R.string.keyboard_key_numpad_template, "7"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_8,
+                context.getString(R.string.keyboard_key_numpad_template, "8"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_9,
+                context.getString(R.string.keyboard_key_numpad_template, "9"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE,
+                context.getString(R.string.keyboard_key_numpad_template, "/"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY,
+                context.getString(R.string.keyboard_key_numpad_template, "*"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT,
+                context.getString(R.string.keyboard_key_numpad_template, "-"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_ADD,
+                context.getString(R.string.keyboard_key_numpad_template, "+"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_DOT,
+                context.getString(R.string.keyboard_key_numpad_template, "."));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_COMMA,
+                context.getString(R.string.keyboard_key_numpad_template, ","));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_ENTER,
+                context.getString(R.string.keyboard_key_numpad_template,
+                        context.getString(R.string.keyboard_key_enter)));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_EQUALS,
+                context.getString(R.string.keyboard_key_numpad_template, "="));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN,
+                context.getString(R.string.keyboard_key_numpad_template, "("));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN,
+                context.getString(R.string.keyboard_key_numpad_template, ")"));
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_ZENKAKU_HANKAKU, "半角/全角");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_EISU, "英数");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_MUHENKAN, "無変換");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_HENKAN, "変換");
+        mSpecialCharacterNames.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな");
+
+        mModifierNames.put(KeyEvent.META_META_ON, "Meta");
+        mModifierNames.put(KeyEvent.META_CTRL_ON, "Ctrl");
+        mModifierNames.put(KeyEvent.META_ALT_ON, "Alt");
+        mModifierNames.put(KeyEvent.META_SHIFT_ON, "Shift");
+        mModifierNames.put(KeyEvent.META_SYM_ON, "Sym");
+        mModifierNames.put(KeyEvent.META_FUNCTION_ON, "Fn");
+
+        mSpecialCharacterDrawables.put(
+                KeyEvent.KEYCODE_DEL, context.getDrawable(R.drawable.ic_ksh_key_backspace));
+        mSpecialCharacterDrawables.put(
+                KeyEvent.KEYCODE_ENTER, context.getDrawable(R.drawable.ic_ksh_key_enter));
+        mSpecialCharacterDrawables.put(
+                KeyEvent.KEYCODE_DPAD_UP, context.getDrawable(R.drawable.ic_ksh_key_up));
+        mSpecialCharacterDrawables.put(
+                KeyEvent.KEYCODE_DPAD_RIGHT, context.getDrawable(R.drawable.ic_ksh_key_right));
+        mSpecialCharacterDrawables.put(
+                KeyEvent.KEYCODE_DPAD_DOWN, context.getDrawable(R.drawable.ic_ksh_key_down));
+        mSpecialCharacterDrawables.put(
+                KeyEvent.KEYCODE_DPAD_LEFT, context.getDrawable(R.drawable.ic_ksh_key_left));
+
+        mModifierDrawables.put(
+                KeyEvent.META_META_ON, context.getDrawable(R.drawable.ic_ksh_key_meta));
     }
 
     public void toggleKeyboardShortcuts(int deviceId) {
@@ -245,7 +265,57 @@
                         systemGroup.addItem(new KeyboardShortcutInfo(
                                 mContext.getString(R.string.keyboard_shortcut_group_system_recents),
                                 KeyEvent.KEYCODE_TAB, KeyEvent.META_ALT_ON));
+                        systemGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_system_notifications),
+                                KeyEvent.KEYCODE_N, KeyEvent.META_META_ON));
+                        systemGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_system_shortcuts_helper),
+                                KeyEvent.KEYCODE_SLASH, KeyEvent.META_META_ON));
+                        systemGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_system_switch_input),
+                                KeyEvent.KEYCODE_SPACE, KeyEvent.META_META_ON));
                         result.add(systemGroup);
+
+                        KeyboardShortcutGroup applicationGroup = new KeyboardShortcutGroup(
+                                mContext.getString(R.string.keyboard_shortcut_group_applications),
+                                true);
+                        applicationGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_applications_assist),
+                                KeyEvent.KEYCODE_UNKNOWN, KeyEvent.META_META_ON));
+                        applicationGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_applications_browser),
+                                KeyEvent.KEYCODE_B, KeyEvent.META_META_ON));
+                        applicationGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_applications_contacts),
+                                KeyEvent.KEYCODE_C, KeyEvent.META_META_ON));
+                        applicationGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_applications_email),
+                                KeyEvent.KEYCODE_E, KeyEvent.META_META_ON));
+                        applicationGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_applications_im),
+                                KeyEvent.KEYCODE_T, KeyEvent.META_META_ON));
+                        applicationGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_applications_music),
+                                KeyEvent.KEYCODE_P, KeyEvent.META_META_ON));
+                        applicationGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_applications_youtube),
+                                KeyEvent.KEYCODE_Y, KeyEvent.META_META_ON));
+                        applicationGroup.addItem(new KeyboardShortcutInfo(
+                                mContext.getString(
+                                        R.string.keyboard_shortcut_group_applications_calendar),
+                                KeyEvent.KEYCODE_L, KeyEvent.META_META_ON));
+                        result.add(applicationGroup);
+
                         showKeyboardShortcutsDialog(result);
                     }
                 }, deviceId);
@@ -293,6 +363,8 @@
             List<KeyboardShortcutGroup> keyboardShortcutGroups) {
         LayoutInflater inflater = LayoutInflater.from(mContext);
         final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size();
+        // Needed to be able to scale the image items to the same height as the text items.
+        final int shortcutTextItemHeight = getShortcutTextItemHeight(inflater);
         for (int i = 0; i < keyboardShortcutGroupsSize; i++) {
             KeyboardShortcutGroup group = keyboardShortcutGroups.get(i);
             TextView categoryTitle = (TextView) inflater.inflate(
@@ -314,7 +386,7 @@
                     Log.w(TAG, "Keyboard Shortcut contains key not on device, skipping.");
                     continue;
                 }
-                List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
+                List<StringOrDrawable> shortcutKeys = getHumanReadableShortcutKeys(info);
                 if (shortcutKeys == null) {
                     // Ignore shortcuts we can't display keys for.
                     Log.w(TAG, "Keyboard Shortcut contains unsupported keys, skipping.");
@@ -330,11 +402,26 @@
                         .findViewById(R.id.keyboard_shortcuts_item_container);
                 final int shortcutKeysSize = shortcutKeys.size();
                 for (int k = 0; k < shortcutKeysSize; k++) {
-                    String shortcutKey = shortcutKeys.get(k);
-                    TextView shortcutKeyView = (TextView) inflater.inflate(
-                            R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer, false);
-                    shortcutKeyView.setText(shortcutKey);
-                    shortcutItemsContainer.addView(shortcutKeyView);
+                    StringOrDrawable shortcutRepresentation = shortcutKeys.get(k);
+                    if (shortcutRepresentation.drawable != null) {
+                        ImageView shortcutKeyIconView = (ImageView) inflater.inflate(
+                                R.layout.keyboard_shortcuts_key_icon_view, shortcutItemsContainer,
+                                false);
+                        Bitmap bitmap = Bitmap.createBitmap(shortcutTextItemHeight,
+                                shortcutTextItemHeight, Bitmap.Config.ARGB_8888);
+                        Canvas canvas = new Canvas(bitmap);
+                        shortcutRepresentation.drawable.setBounds(0, 0, canvas.getWidth(),
+                                canvas.getHeight());
+                        shortcutRepresentation.drawable.draw(canvas);
+                        shortcutKeyIconView.setImageBitmap(bitmap);
+                        shortcutItemsContainer.addView(shortcutKeyIconView);
+                    } else if (shortcutRepresentation.string != null) {
+                        TextView shortcutKeyTextView = (TextView) inflater.inflate(
+                                R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer,
+                                false);
+                        shortcutKeyTextView.setText(shortcutRepresentation.string);
+                        shortcutItemsContainer.addView(shortcutKeyTextView);
+                    }
                 }
                 shortcutContainer.addView(shortcutView);
             }
@@ -348,17 +435,34 @@
         }
     }
 
-    private List<String> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
-        List<String> shortcutKeys = getHumanReadableModifiers(info);
+    private int getShortcutTextItemHeight(LayoutInflater inflater) {
+        TextView shortcutKeyTextView = (TextView) inflater.inflate(
+                R.layout.keyboard_shortcuts_key_view, null, false);
+        shortcutKeyTextView.measure(
+                View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+        return shortcutKeyTextView.getMeasuredHeight()
+                - shortcutKeyTextView.getPaddingTop()
+                - shortcutKeyTextView.getPaddingBottom();
+    }
+
+    private List<StringOrDrawable> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
+        List<StringOrDrawable> shortcutKeys = getHumanReadableModifiers(info);
         if (shortcutKeys == null) {
             return null;
         }
-        String displayLabelString;
-        if (info.getKeycode() == KeyEvent.KEYCODE_UNKNOWN) {
+        String displayLabelString = null;
+        Drawable displayLabelDrawable = null;
+        if (info.getBaseCharacter() > Character.MIN_VALUE) {
             displayLabelString = String.valueOf(info.getBaseCharacter());
-        } else if (SPECIAL_CHARACTER_NAMES.get(info.getKeycode()) != null) {
-            displayLabelString = SPECIAL_CHARACTER_NAMES.get(info.getKeycode());
+        } else if (mSpecialCharacterDrawables.get(info.getKeycode()) != null) {
+            displayLabelDrawable = mSpecialCharacterDrawables.get(info.getKeycode());
+        } else if (mSpecialCharacterNames.get(info.getKeycode()) != null) {
+            displayLabelString = mSpecialCharacterNames.get(info.getKeycode());
         } else {
+            // Special case for shortcuts with no base key or keycode.
+            if (info.getKeycode() == KeyEvent.KEYCODE_UNKNOWN) {
+                return shortcutKeys;
+            }
             // TODO: Have a generic map for when we don't have the device's.
             char displayLabel = mKeyCharacterMap == null
                     ? 0 : mKeyCharacterMap.getDisplayLabel(info.getKeycode());
@@ -368,20 +472,31 @@
                 return null;
             }
         }
-        shortcutKeys.add(displayLabelString.toUpperCase());
+
+        if (displayLabelDrawable != null) {
+            shortcutKeys.add(new StringOrDrawable(displayLabelDrawable));
+        } else if (displayLabelString != null) {
+            shortcutKeys.add(new StringOrDrawable(displayLabelString.toUpperCase()));
+        }
         return shortcutKeys;
     }
 
-    private List<String> getHumanReadableModifiers(KeyboardShortcutInfo info) {
-        final List<String> shortcutKeys = new ArrayList<>();
+    private List<StringOrDrawable> getHumanReadableModifiers(KeyboardShortcutInfo info) {
+        final List<StringOrDrawable> shortcutKeys = new ArrayList<>();
         int modifiers = info.getModifiers();
         if (modifiers == 0) {
             return shortcutKeys;
         }
-        for(int i = 0; i < MODIFIER_NAMES.size(); ++i) {
-            final int supportedModifier = MODIFIER_NAMES.keyAt(i);
+        for(int i = 0; i < mModifierNames.size(); ++i) {
+            final int supportedModifier = mModifierNames.keyAt(i);
             if ((modifiers & supportedModifier) != 0) {
-                shortcutKeys.add(MODIFIER_NAMES.get(supportedModifier).toUpperCase());
+                if (mModifierDrawables.get(supportedModifier) != null) {
+                    shortcutKeys.add(new StringOrDrawable(
+                            mModifierDrawables.get(supportedModifier)));
+                } else {
+                    shortcutKeys.add(new StringOrDrawable(
+                            mModifierNames.get(supportedModifier).toUpperCase()));
+                }
                 modifiers &= ~supportedModifier;
             }
         }
@@ -391,4 +506,17 @@
         }
         return shortcutKeys;
     }
+
+    private static final class StringOrDrawable {
+        public String string;
+        public Drawable drawable;
+
+        public StringOrDrawable(String string) {
+            this.string = string;
+        }
+
+        public StringOrDrawable(Drawable drawable) {
+            this.drawable = drawable;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index f4fb0b9..5b00523 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -604,7 +604,7 @@
             }
             int expandedVisualType = getVisualTypeForHeight(height);
             int collapsedVisualType = getVisualTypeForHeight(
-                    mContainingNotification.getMinExpandHeight());
+                    mContainingNotification.getCollapsedHeight());
             return mTransformationStartVisibleType == collapsedVisualType
                     ? expandedVisualType
                     : collapsedVisualType;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 45a24a0..3c464d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -16,28 +16,35 @@
 
 package com.android.systemui.statusbar;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.app.INotificationManager;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
+import android.os.Handler;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.ViewAnimationUtils;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RadioButton;
+import android.widget.RadioGroup;
 import android.widget.SeekBar;
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.Utils;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
 import com.android.systemui.tuner.TunerService;
 
 /**
@@ -46,6 +53,8 @@
 public class NotificationGuts extends LinearLayout implements TunerService.Tunable {
     public static final String SHOW_SLIDER = "show_importance_slider";
 
+    private static final long CLOSE_GUTS_DELAY = 8000;
+
     private Drawable mBackground;
     private int mClipTopAmount;
     private int mActualHeight;
@@ -59,10 +68,35 @@
     private RadioButton mSilent;
     private RadioButton mReset;
 
+    private Handler mHandler;
+    private Runnable mFalsingCheck;
+    private boolean mNeedsFalsingProtection;
+    private OnGutsClosedListener mListener;
+
+    public interface OnGutsClosedListener {
+        public void onGutsClosed(NotificationGuts guts);
+    }
+
     public NotificationGuts(Context context, AttributeSet attrs) {
         super(context, attrs);
         setWillNotDraw(false);
         TunerService.get(mContext).addTunable(this, SHOW_SLIDER);
+        mHandler = new Handler();
+        mFalsingCheck = new Runnable() {
+            @Override
+            public void run() {
+                if (mNeedsFalsingProtection && mExposed) {
+                    closeControls(-1 /* x */, -1 /* y */, true /* notify */);
+                }
+            }
+        };
+    }
+
+    public void resetFalsingCheck() {
+        mHandler.removeCallbacks(mFalsingCheck);
+        if (mNeedsFalsingProtection && mExposed) {
+            mHandler.postDelayed(mFalsingCheck, CLOSE_GUTS_DELAY);
+        }
     }
 
     @Override
@@ -130,30 +164,23 @@
             importanceSlider.setVisibility(View.VISIBLE);
             importanceButtons.setVisibility(View.GONE);
         } else {
-            int userImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+            mStartingImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
             try {
-                userImportance =
+                mStartingImportance =
                         mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
             } catch (RemoteException e) {}
-            bindToggles(importanceButtons, userImportance, systemApp);
+            bindToggles(importanceButtons, mStartingImportance, systemApp);
             importanceButtons.setVisibility(View.VISIBLE);
             importanceSlider.setVisibility(View.GONE);
         }
     }
 
+    public boolean hasImportanceChanged() {
+        return mStartingImportance != getSelectedImportance();
+    }
+
     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;
-            }
-        }
+        int progress = getSelectedImportance();
         MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
                 progress - mStartingImportance);
         try {
@@ -163,8 +190,29 @@
         }
     }
 
+    private int getSelectedImportance() {
+        if (mSeekBar!= null && mSeekBar.isShown()) {
+            return mSeekBar.getProgress();
+        } else {
+            if (mBlock.isChecked()) {
+                return NotificationListenerService.Ranking.IMPORTANCE_NONE;
+            } else if (mSilent.isChecked()) {
+                return NotificationListenerService.Ranking.IMPORTANCE_LOW;
+            } else {
+                return NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+            }
+        }
+    }
+
     private void bindToggles(final View importanceButtons, final int importance,
             final boolean systemApp) {
+        ((RadioGroup) importanceButtons).setOnCheckedChangeListener(
+                new RadioGroup.OnCheckedChangeListener() {
+                    @Override
+                    public void onCheckedChanged(RadioGroup group, int checkedId) {
+                        resetFalsingCheck();
+                    }
+                });
         mBlock = (RadioButton) importanceButtons.findViewById(R.id.block_importance);
         mSilent = (RadioButton) importanceButtons.findViewById(R.id.silent_importance);
         mReset = (RadioButton) importanceButtons.findViewById(R.id.reset_importance);
@@ -198,6 +246,7 @@
         mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
             @Override
             public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                resetFalsingCheck();
                 if (progress < minProgress) {
                     seekBar.setProgress(minProgress);
                     progress = minProgress;
@@ -210,7 +259,7 @@
 
             @Override
             public void onStartTrackingTouch(SeekBar seekBar) {
-                // no-op
+                resetFalsingCheck();
             }
 
             @Override
@@ -256,6 +305,38 @@
         mSeekBar.setProgress(mStartingImportance);
     }
 
+    public void closeControls(int x, int y, boolean notify) {
+        if (getWindowToken() == null) {
+            if (notify && mListener != null) {
+                mListener.onGutsClosed(this);
+            }
+            return;
+        }
+        if (x == -1 || y == -1) {
+            x = (getLeft() + getRight()) / 2;
+            y = (getTop() + getHeight() / 2);
+        }
+        final double horz = Math.max(getWidth() - x, x);
+        final double vert = Math.max(getHeight() - y, y);
+        final float r = (float) Math.hypot(horz, vert);
+        final Animator a = ViewAnimationUtils.createCircularReveal(this,
+                x, y, r, 0);
+        a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+        a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+        a.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                setVisibility(View.GONE);
+            }
+        });
+        a.start();
+        setExposed(false, mNeedsFalsingProtection);
+        if (notify && mListener != null) {
+            mListener.onGutsClosed(this);
+        }
+    }
+
     public void setActualHeight(int actualHeight) {
         mActualHeight = actualHeight;
         invalidate();
@@ -277,8 +358,18 @@
         return false;
     }
 
-    public void setExposed(boolean exposed) {
+    public void setClosedListener(OnGutsClosedListener listener) {
+        mListener = listener;
+    }
+
+    public void setExposed(boolean exposed, boolean needsFalsingProtection) {
         mExposed = exposed;
+        mNeedsFalsingProtection = needsFalsingProtection;
+        if (mExposed && mNeedsFalsingProtection) {
+            resetFalsingCheck();
+        } else {
+            mHandler.removeCallbacks(mFalsingCheck);
+        }
     }
 
     public boolean areGutsExposed() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index c70aad2..06d79a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -131,11 +131,8 @@
         mComparators.add(HeaderProcessor.forTextView(mRow,
                 com.android.internal.R.id.app_name_text));
         mComparators.add(HeaderProcessor.forTextView(mRow,
-                com.android.internal.R.id.header_sub_text));
-        mComparators.add(HeaderProcessor.forTextView(mRow,
-                com.android.internal.R.id.header_content_info));
-        mDividers.add(com.android.internal.R.id.sub_text_divider);
-        mDividers.add(com.android.internal.R.id.content_info_divider);
+                com.android.internal.R.id.header_text));
+        mDividers.add(com.android.internal.R.id.header_text_divider);
         mDividers.add(com.android.internal.R.id.time_divider);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
index a3e78c1..a5ebbba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -41,7 +41,7 @@
         /**
          * Called when a notification is slid back over the gear.
          */
-        public void onSettingsIconRowReset(NotificationSettingsIconRow row);
+        public void onSettingsIconRowReset(ExpandableNotificationRow row);
     }
 
     private ExpandableNotificationRow mParent;
@@ -92,9 +92,9 @@
         mAnimating = false;
         mSnapping = false;
         mDismissing = false;
-        setIconLocation(true /* on left */);
+        setIconLocation(true /* on left */, true /* force */);
         if (mListener != null) {
-            mListener.onSettingsIconRowReset(this);
+            mListener.onSettingsIconRowReset(mParent);
         }
     }
 
@@ -104,6 +104,7 @@
 
     public void setNotificationRowParent(ExpandableNotificationRow parent) {
         mParent = parent;
+        setIconLocation(mOnLeft, true /* force */);
     }
 
     public void setAppName(String appName) {
@@ -183,7 +184,7 @@
         if (isIconLocationChange(transX)) {
             setGearAlpha(0f);
         }
-        setIconLocation(transX > 0 /* fromLeft */);
+        setIconLocation(transX > 0 /* fromLeft */, false /* force */);
         mFadeAnimator = ValueAnimator.ofFloat(mGearIcon.getAlpha(), 1);
         mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
@@ -220,12 +221,20 @@
         mFadeAnimator.start();
     }
 
-    public void setIconLocation(boolean onLeft) {
-        if (onLeft == mOnLeft || mSnapping) {
-            // Same side? Do nothing.
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        setIconLocation(mOnLeft, true /* force */);
+    }
+
+    public void setIconLocation(boolean onLeft, boolean force) {
+        if ((!force && onLeft == mOnLeft) || mSnapping || mParent == null) {
+            // Do nothing
             return;
         }
-        setTranslationX(onLeft ? 0 : (mParent.getWidth() - mHorizSpaceForGear));
+        final boolean isRtl = mParent.isLayoutRtl();
+        final float left = isRtl ? -(mParent.getWidth() - mHorizSpaceForGear) : 0;
+        final float right = isRtl ? 0 : (mParent.getWidth() - mHorizSpaceForGear);
+        setTranslationX(onLeft ? left : right);
         mOnLeft = onLeft;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
index 63ee0c0..41eed56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java
@@ -113,7 +113,8 @@
             filter.addAction(Intent.ACTION_USER_SWITCHED);
             filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
             filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
-            filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+            filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+            filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
             mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
         } else {
             mContext.unregisterReceiver(mReceiver);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 260c969..ec45d60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -182,7 +182,7 @@
 
     private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape) {
         for (int i = 0; i < buttons.length; i++) {
-            inflateButton(buttons[i], parent, landscape);
+            inflateButton(buttons[i], parent, landscape, i);
         }
     }
 
@@ -195,7 +195,8 @@
     }
 
     @Nullable
-    protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape) {
+    protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,
+            int indexInParent) {
         LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
         float size = extractSize(buttonSpec);
         String button = extractButton(buttonSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 56a7dbe..6859348 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -76,6 +76,8 @@
     private Drawable mHomeDefaultIcon, mHomeCarModeIcon;
     private Drawable mRecentIcon;
     private Drawable mDockedIcon;
+    private Drawable mImeIcon;
+    private Drawable mMenuIcon;
 
     private NavigationBarGestureHelper mGestureHelper;
     private DeadZone mDeadZone;
@@ -270,7 +272,8 @@
     }
 
     private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
-        if (oldConfig.orientation != newConfig.orientation) {
+        if (oldConfig.orientation != newConfig.orientation
+                || oldConfig.densityDpi != newConfig.densityDpi) {
             mDockedIcon = ctx.getDrawable(R.drawable.ic_sysbar_docked);
         }
         if (oldConfig.densityDpi != newConfig.densityDpi) {
@@ -280,8 +283,10 @@
             mBackAltLandIcon = mBackAltIcon;
 
             mHomeDefaultIcon = ctx.getDrawable(R.drawable.ic_sysbar_home);
-
             mRecentIcon = ctx.getDrawable(R.drawable.ic_sysbar_recent);
+            mMenuIcon = ctx.getDrawable(R.drawable.ic_sysbar_menu);
+            mImeIcon = ctx.getDrawable(R.drawable.ic_ime_switcher_default);
+
             updateCarModeIcons(ctx);
         }
     }
@@ -348,9 +353,11 @@
 
         final boolean showImeButton = ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
         getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
+        getImeSwitchButton().setImageDrawable(mImeIcon);
 
         // Update menu button in case the IME state has changed.
         setMenuVisibility(mShowMenu, true);
+        getMenuButton().setImageDrawable(mMenuIcon);
 
         setDisabledFlags(mDisabledFlags, true);
     }
@@ -595,14 +602,12 @@
         super.onConfigurationChanged(newConfig);
         boolean uiCarModeChanged = updateCarMode(newConfig);
         updateTaskSwitchHelper();
-        if (uiCarModeChanged) {
-            // uiMode changed either from carmode or to carmode.
-            // replace the nav bar button icons based on which mode
-            // we are switching to.
-            setNavigationIconHints(mNavigationIconHints, true);
-        }
         updateIcons(getContext(), mConfiguration, newConfig);
         updateRecentsIcon();
+        if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi) {
+            // If car mode or density changes, we need to reset the icons.
+            setNavigationIconHints(mNavigationIconHints, true);
+        }
         mConfiguration.updateFrom(newConfig);
     }
 
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 45e94f7..62c0fa9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -306,7 +306,7 @@
 
         // Calculate quick setting heights.
         int oldMaxHeight = mQsMaxExpansionHeight;
-        mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQsContainer.getHeader().getHeight();
+        mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQsContainer.getQsMinExpansionHeight();
         mQsMaxExpansionHeight = mQsContainer.getDesiredHeight();
         positionClockAndNotifications();
         if (mQsExpanded && mQsFullyExpanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index c9bb15d..c4b7932 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -845,15 +845,19 @@
     };
 
     public void cancelPeek() {
+        boolean cancelled = mPeekPending;
         if (mPeekAnimator != null) {
+            cancelled = true;
             mPeekAnimator.cancel();
         }
         removeCallbacks(mPeekRunnable);
         mPeekPending = false;
 
-        // When peeking, we already tell mBar that we expanded ourselves. Make sure that we also
-        // notify mBar that we might have closed ourselves.
-        notifyBarPanelExpansionChanged();
+        if (cancelled) {
+            // When peeking, we already tell mBar that we expanded ourselves. Make sure that we also
+            // notify mBar that we might have closed ourselves.
+            notifyBarPanelExpansionChanged();
+        }
     }
 
     public void expand(final boolean animate) {
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 4c5c843..bf58592 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -21,7 +21,9 @@
 import android.animation.AnimatorListenerAdapter;
 import android.annotation.NonNull;
 import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
 import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
 import android.app.IActivityManager;
 import android.app.Notification;
 import android.app.PendingIntent;
@@ -753,7 +755,6 @@
         mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
                 R.id.notification_stack_scroller);
         mStackScroller.setLongPressListener(getNotificationLongClicker());
-        mStackScroller.setGearDisplayedListener(getGearDisplayedListener());
         mStackScroller.setPhoneStatusBar(this);
         mStackScroller.setGroupManager(mGroupManager);
         mStackScroller.setHeadsUpManager(mHeadsUpManager);
@@ -3091,8 +3092,8 @@
                             null, mContext.getBasePackageName(),
                             intent,
                             intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                            null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null,
-                            UserHandle.CURRENT.getIdentifier());
+                            null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
+                            getActivityOptions(), UserHandle.CURRENT.getIdentifier());
                 } catch (RemoteException e) {
                     Log.w(TAG, "Unable to start activity", e);
                 }
@@ -3302,10 +3303,14 @@
     protected void loadDimens() {
         final Resources res = mContext.getResources();
 
+        int oldBarHeight = mNaturalBarHeight;
         mNaturalBarHeight = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
-
-        mMaxAllowedKeyguardNotifications = res.getInteger(R.integer.keyguard_max_notification_count);
+        if (mStatusBarWindowManager != null && mNaturalBarHeight != oldBarHeight) {
+            mStatusBarWindowManager.setBarHeight(mNaturalBarHeight);
+        }
+        mMaxAllowedKeyguardNotifications = res.getInteger(
+                R.integer.keyguard_max_notification_count);
 
         if (DEBUG) Log.v(TAG, "updateResources");
     }
@@ -4192,6 +4197,12 @@
     }
 
     @Override
+    public void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
+        mLeaveOpenOnKeyguardHide = true;
+        dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */);
+    }
+
+    @Override
     protected void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) {
         mLeaveOpenOnKeyguardHide = true;
         showBouncer();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index c883cc9..0ac2e7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -137,7 +137,8 @@
         filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
-        filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
 
         // listen for user / profile change.
@@ -507,7 +508,8 @@
                 updateSimState(intent);
             } else if (action.equals(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED)) {
                 updateTTY(intent);
-            } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED)) {
+            } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) ||
+                    action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
                 updateQuietState();
                 updateManagedProfile();
             } else if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 902fd3d..cc3b4bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -41,7 +41,9 @@
     private Runnable mHideExpandedRunnable = new Runnable() {
         @Override
         public void run() {
-            mBar.makeExpandedInvisible();
+            if (mPanelFraction == 0.0f) {
+                mBar.makeExpandedInvisible();
+            }
         }
     };
 
@@ -135,6 +137,7 @@
         super.onTrackingStarted();
         mBar.onTrackingStarted();
         mScrimController.onTrackingStarted();
+        removePendingHideExpandedRunnables();
     }
 
     @Override
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 f3aba4f..ea9a5a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -45,7 +45,7 @@
 import com.android.systemui.tuner.TunerService;
 
 public class QuickStatusBarHeader extends BaseStatusBarHeader implements
-        NextAlarmChangeCallback, OnClickListener {
+        NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener {
 
     private static final String TAG = "QuickStatusBarHeader";
 
@@ -54,7 +54,7 @@
     private ActivityStarter mActivityStarter;
     private NextAlarmController mNextAlarmController;
     private SettingsButton mSettingsButton;
-    private View mSettingsContainer;
+    protected View mSettingsContainer;
 
     private TextView mAlarmStatus;
     private TextView mAlarmStatusCollapsed;
@@ -75,19 +75,19 @@
 
     private QuickQSPanel mHeaderQsPanel;
     private boolean mShowEmergencyCallsOnly;
-    private MultiUserSwitch mMultiUserSwitch;
+    protected MultiUserSwitch mMultiUserSwitch;
     private ImageView mMultiUserAvatar;
 
     private float mDateTimeTranslation;
     private float mDateTimeAlarmTranslation;
     private float mDateScaleFactor;
-    private float mGearTranslation;
+    protected float mGearTranslation;
 
     private TouchAnimator mSecondHalfAnimator;
     private TouchAnimator mFirstHalfAnimator;
     private TouchAnimator mDateSizeAnimator;
     private TouchAnimator mAlarmTranslation;
-    private TouchAnimator mSettingsAlpha;
+    protected TouchAnimator mSettingsAlpha;
     private float mExpansionAmount;
     private QSTileHost mHost;
 
@@ -172,6 +172,11 @@
                 .addFloat(mDateTimeGroup, "scaleY", 1, mDateScaleFactor)
                 .setStartDelay(.36f)
                 .build();
+
+        updateSettingsAnimator();
+    }
+
+    protected void updateSettingsAnimator() {
         mSettingsAlpha = new TouchAnimator.Builder()
                 .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0)
                 .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0)
@@ -241,7 +246,7 @@
     @Override
     protected void onDetachedFromWindow() {
         setListening(false);
-        mHost.getUserInfoController().remListener(mUserListener);
+        mHost.getUserInfoController().remListener(this);
         mHost.getNetworkController().removeEmergencyListener(this);
         super.onDetachedFromWindow();
     }
@@ -275,7 +280,7 @@
         updateVisibilities();
     }
 
-    private void updateVisibilities() {
+    protected void updateVisibilities() {
         updateAlarmVisibilities();
         mEmergencyOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly
                 ? View.VISIBLE : View.INVISIBLE);
@@ -309,7 +314,7 @@
 
     public void setupHost(final QSTileHost host) {
         mHost = host;
-        host.setHeaderView(this);
+        host.setHeaderView(mExpandIndicator);
         mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
         mHeaderQsPanel.setHost(host, null /* No customization in header */);
         setUserInfoController(host.getUserInfoController());
@@ -365,7 +370,7 @@
 
     @Override
     public void setUserInfoController(UserInfoController userInfoController) {
-        userInfoController.addListener(mUserListener);
+        userInfoController.addListener(this);
     }
 
     @Override
@@ -379,10 +384,8 @@
         }
     }
 
-    private final OnUserInfoChangedListener mUserListener = new OnUserInfoChangedListener() {
-        @Override
-        public void onUserInfoChanged(String name, Drawable picture) {
-            mMultiUserAvatar.setImageDrawable(picture);
-        }
-    };
+    @Override
+    public void onUserInfoChanged(String name, Drawable picture) {
+        mMultiUserAvatar.setImageDrawable(picture);
+    }
 }
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 b271380..888e19c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -323,6 +323,11 @@
         apply(mCurrentState);
     }
 
+    public void setBarHeight(int barHeight) {
+        mBarHeight = barHeight;
+        apply(mCurrentState);
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("StatusBarWindowManager state:");
         pw.println(mCurrentState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 6a2ecf4e..ebfa018 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -226,6 +226,10 @@
                 return false;
             }
         }
+        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            mStackScrollLayout.closeControlsIfOutsideTouch(ev);
+        }
+
         return super.dispatchTouchEvent(ev);
     }
 
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 ab44b6a..ea0bdf2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -23,6 +23,7 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -52,6 +53,7 @@
 import com.android.systemui.BitmapHelper;
 import com.android.systemui.GuestResumeSessionReceiver;
 import com.android.systemui.R;
+import com.android.systemui.SystemUISecondaryUserService;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.tiles.UserDetailView;
 import com.android.systemui.statusbar.phone.ActivityStarter;
@@ -101,6 +103,8 @@
     private boolean mSimpleUserSwitcher;
     private boolean mAddUsersWhenLocked;
     private boolean mPauseRefreshUsers;
+    private int mSecondaryUser = UserHandle.USER_NULL;
+    private Intent mSecondaryUserServiceIntent;
     private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
 
     public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
@@ -121,6 +125,8 @@
         mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
                 null /* permission */, null /* scheduler */);
 
+        mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class);
+
         filter = new IntentFilter();
         filter.addAction(ACTION_REMOVE_GUEST);
         filter.addAction(ACTION_LOGOUT_USER);
@@ -477,6 +483,20 @@
                 }
                 notifyAdapters();
 
+                // Disconnect from the old secondary user's service
+                if (mSecondaryUser != UserHandle.USER_NULL) {
+                    context.stopServiceAsUser(mSecondaryUserServiceIntent,
+                            UserHandle.of(mSecondaryUser));
+                    mSecondaryUser = UserHandle.USER_NULL;
+                }
+                // Connect to the new secondary user's service (purely to ensure that a persistent
+                // SystemUI application is created for that user)
+                if (userInfo != null && !userInfo.isPrimary()) {
+                    context.startServiceAsUser(mSecondaryUserServiceIntent,
+                            UserHandle.of(userInfo.id));
+                    mSecondaryUser = userInfo.id;
+                }
+
                 if (UserManager.isSplitSystemUser() && userInfo != null && !userInfo.isGuest()
                         && userInfo.id != UserHandle.USER_SYSTEM) {
                     showLogoutNotification(currentId);
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 dc567fc..ee483e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -592,7 +592,7 @@
 
     public float getGroupExpandFraction() {
         int visibleChildrenExpandedHeight = getVisibleChildrenExpandHeight();
-        int minExpandHeight = getMinExpandHeight();
+        int minExpandHeight = getCollapsedHeight();
         float factor = (mActualHeight - minExpandHeight)
                 / (float) (visibleChildrenExpandedHeight - minExpandHeight);
         return Math.max(0.0f, Math.min(1.0f, factor));
@@ -618,11 +618,14 @@
     }
 
     public int getMinHeight() {
-        return getIntrinsicHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
+        return getMinHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
     }
 
-    public int getMinExpandHeight() {
-        int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
+    public int getCollapsedHeight() {
+        return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */));
+    }
+
+    private int getMinHeight(int maxAllowedVisibleChildren) {
         int minExpandHeight = mNotificationHeaderHeight;
         int visibleChildren = 0;
         boolean firstChild = true;
@@ -637,7 +640,7 @@
                 firstChild = false;
             }
             ExpandableNotificationRow child = mChildren.get(i);
-            minExpandHeight += child.getMinHeight();
+            minExpandHeight += child.getSingleLineView().getHeight();
             visibleChildren++;
         }
         minExpandHeight += mCollapsedBottompadding;
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 b5030e6..7c5cdfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -60,6 +60,7 @@
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.NotificationGuts;
 import com.android.systemui.statusbar.NotificationOverflowContainer;
 import com.android.systemui.statusbar.NotificationSettingsIconRow;
 import com.android.systemui.statusbar.NotificationSettingsIconRow.SettingsIconRowListener;
@@ -220,7 +221,6 @@
      */
     private int mMaxScrollAfterExpand;
     private SwipeHelper.LongPressListener mLongPressListener;
-    private GearDisplayedListener mGearDisplayedListener;
 
     private NotificationSettingsIconRow mCurrIconRow;
     private View mTranslatingParentView;
@@ -299,7 +299,7 @@
             setDimAmount((Float) animation.getAnimatedValue());
         }
     };
-    private ViewGroup mQsContainer;
+    protected ViewGroup mQsContainer;
     private boolean mContinuousShadowUpdate;
     private ViewTreeObserver.OnPreDrawListener mShadowUpdater
             = new ViewTreeObserver.OnPreDrawListener() {
@@ -374,8 +374,12 @@
     }
 
     @Override
-    public void onSettingsIconRowReset(NotificationSettingsIconRow row) {
-        mSwipeHelper.setSnappedToGear(false);
+    public void onSettingsIconRowReset(ExpandableNotificationRow row) {
+        if (mTranslatingParentView != null && row == mTranslatingParentView) {
+            mSwipeHelper.setSnappedToGear(false);
+            mGearExposedView = null;
+            mTranslatingParentView = null;
+        }
     }
 
     @Override
@@ -669,10 +673,6 @@
         mLongPressListener = listener;
     }
 
-    public void setGearDisplayedListener(GearDisplayedListener listener) {
-        mGearDisplayedListener = listener;
-    }
-
     public void setQsContainer(ViewGroup qsContainer) {
         mQsContainer = qsContainer;
     }
@@ -737,17 +737,9 @@
             // We start the swipe and snap back in the same frame, we don't want any animation
             mDragAnimPendingChildren.remove(animView);
         }
-
-        if (mCurrIconRow != null) {
-            if (targetLeft == 0) {
-                mCurrIconRow.resetState();
-                mCurrIconRow = null;
-                if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
-                    mGearExposedView = null;
-                }
-            } else {
-                mSwipeHelper.setSnappedToGear(true);
-            }
+        if (mCurrIconRow != null && targetLeft == 0) {
+            mCurrIconRow.resetState();
+            mCurrIconRow = null;
         }
     }
 
@@ -926,7 +918,7 @@
         int positionInLinearLayout = getPositionInLinearLayout(v);
 
         int targetScroll = positionInLinearLayout + expandableView.getActualHeight() +
-                mBottomInset - getHeight() + getTopPadding();
+                getImeInset() - getHeight() + getTopPadding();
         if (mOwnScrollY < targetScroll) {
             mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
             mDontReportNextOverScroll = true;
@@ -936,8 +928,7 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        mBottomInset = Math.max(0, insets.getSystemWindowInsetBottom()
-                - (getRootView().getHeight() - getHeight()));
+        mBottomInset = insets.getSystemWindowInsetBottom();
 
         int range = getScrollRange();
         if (mOwnScrollY > range) {
@@ -995,7 +986,8 @@
     }
 
     public void dismissViewAnimated(View child, Runnable endRunnable, int delay, long duration) {
-        mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration);
+        mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration,
+                true /* isDismissAll */);
     }
 
     public void snapViewIfNeeded(View child) {
@@ -1506,23 +1498,17 @@
     }
 
     private int getScrollRange() {
-        int scrollRange = 0;
-        ExpandableView firstChild = (ExpandableView) getFirstChildNotGone();
-        if (firstChild != null) {
-            int contentHeight = getContentHeight();
-            scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize
-                    + mBottomStackSlowDownHeight);
-            if (scrollRange > 0) {
-                int firstChildMaxExpandHeight = getMaxExpandHeight(firstChild);
-                // We want to at least be able collapse the first item and not ending in a weird
-                // end state.
-                scrollRange = Math.max(scrollRange, firstChildMaxExpandHeight
-                        - firstChild.getMinHeight());
-            }
-        }
-        int imeOverlap = Math.max(0,
-                getContentHeight() - (getHeight() - mBottomInset));
-        return scrollRange + imeOverlap;
+        int contentHeight = getContentHeight();
+        int scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize
+                + mBottomStackSlowDownHeight);
+        int imeInset = getImeInset();
+        scrollRange += Math.min(imeInset, Math.max(0,
+                getContentHeight() - (getHeight() - imeInset)));
+        return scrollRange;
+    }
+
+    private int getImeInset() {
+        return Math.max(0, mBottomInset - (getRootView().getHeight() - getHeight()));
     }
 
     /**
@@ -1947,7 +1933,7 @@
 
     public int getPeekHeight() {
         final ExpandableView firstChild = getFirstChildNotGone();
-        final int firstChildMinHeight = firstChild != null ? (int) firstChild.getMinHeight()
+        final int firstChildMinHeight = firstChild != null ? firstChild.getCollapsedHeight()
                 : mCollapsedSize;
         return mIntrinsicPadding + firstChildMinHeight + mBottomStackPeekSize
                 + mBottomStackSlowDownHeight;
@@ -3209,9 +3195,6 @@
             disableClipOptimization();
         }
         handleDismissAllClipping();
-        if (mCurrIconRow != null && mCurrIconRow.isVisible()) {
-            mCurrIconRow.getNotificationParent().animateTranslateNotification(0 /* left target */);
-        }
     }
 
     private void handleDismissAllClipping() {
@@ -3470,16 +3453,11 @@
         public void flingTopOverscroll(float velocity, boolean open);
     }
 
-    /**
-     * A listener that is notified when the gear is shown behind a notification.
-     */
-    public interface GearDisplayedListener {
-        void onGearDisplayed(ExpandableNotificationRow row);
-    }
-
     private class NotificationSwipeHelper extends SwipeHelper {
-        private static final long GEAR_SHOW_DELAY = 60;
+        private static final long SHOW_GEAR_DELAY = 60;
+        private static final long COVER_GEAR_DELAY = 4000;
         private CheckForDrag mCheckForDrag;
+        private Runnable mFalsingCheck;
         private Handler mHandler;
         private boolean mGearSnappedTo;
         private boolean mGearSnappedOnLeft;
@@ -3487,6 +3465,12 @@
         public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) {
             super(swipeDirection, callback, context);
             mHandler = new Handler();
+            mFalsingCheck = new Runnable() {
+                @Override
+                public void run() {
+                    resetExposedGearView(true /* animate */, true /* force */);
+                }
+            };
         }
 
         @Override
@@ -3501,9 +3485,10 @@
             }
             mCheckForDrag = null;
             mCurrIconRow = null;
+            mHandler.removeCallbacks(mFalsingCheck);
 
             // Slide back any notifications that might be showing a gear
-            resetExposedGearView();
+            resetExposedGearView(true /* animate */, false /* force */);
 
             if (currView instanceof ExpandableNotificationRow) {
                 // Set the listener for the current row's gear
@@ -3514,6 +3499,8 @@
 
         @Override
         public void onMoveUpdate(View view, float translation, float delta) {
+            mHandler.removeCallbacks(mFalsingCheck);
+
             if (mCurrIconRow != null) {
                 mCurrIconRow.setSnapping(false); // If we're moving, we're not snapping.
 
@@ -3532,7 +3519,8 @@
                     } else {
                         // Check scheduled, reset alpha and update location; check will fade it in
                         mCurrIconRow.setGearAlpha(0f);
-                        mCurrIconRow.setIconLocation(translation > 0 /* onLeft */);
+                        mCurrIconRow.setIconLocation(translation > 0 /* onLeft */,
+                                false /* force */);
                     }
                 }
             }
@@ -3547,10 +3535,10 @@
         }
 
         @Override
-        public void dismissChild(final View view, float velocity) {
-            super.dismissChild(view, velocity);
-            cancelCheckForDrag();
-            setSnappedToGear(false);
+        public void dismissChild(final View view, float velocity,
+                boolean useAccelerateInterpolator) {
+            super.dismissChild(view, velocity, useAccelerateInterpolator);
+            handleGearCoveredOrDismissed();
         }
 
         @Override
@@ -3558,11 +3546,17 @@
             super.snapChild(animView, targetLeft, velocity);
             onDragCancelled(animView);
             if (targetLeft == 0) {
-                cancelCheckForDrag();
-                setSnappedToGear(false);
+                handleGearCoveredOrDismissed();
             }
         }
 
+        private void handleGearCoveredOrDismissed() {
+            cancelCheckForDrag();
+            setSnappedToGear(false);
+            if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
+                mGearExposedView = null;
+            }
+        }
 
         @Override
         public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
@@ -3584,7 +3578,8 @@
                         snapChild(animView, 0 /* leftTarget */, velocity);
                     } else if (isDismissGesture(ev)) {
                         // Gesture is a dismiss that's not towards the gear
-                        dismissChild(animView, swipedFastEnough() ? velocity : 0f);
+                        dismissChild(animView, velocity,
+                                !swipedFastEnough() /* useAccelerateInterpolator */);
                     } else {
                         // Didn't move enough to dismiss or cover, snap to the gear
                         snapToGear(animView, velocity);
@@ -3609,7 +3604,8 @@
 
         private void dismissOrSnapBack(View animView, float velocity, MotionEvent ev) {
             if (isDismissGesture(ev)) {
-                dismissChild(animView, swipedFastEnough() ? velocity : 0f);
+                dismissChild(animView, velocity,
+                        !swipedFastEnough() /* useAccelerateInterpolator */);
             } else {
                 snapChild(animView, 0 /* leftTarget */, velocity);
             }
@@ -3620,38 +3616,47 @@
             final float target = mCurrIconRow.isIconOnLeft() ? snapBackThreshold
                     : -snapBackThreshold;
             mGearExposedView = mTranslatingParentView;
-            if (mGearDisplayedListener != null
-                    && (animView instanceof ExpandableNotificationRow)) {
-                mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
+            if (animView instanceof ExpandableNotificationRow) {
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
+                        ((ExpandableNotificationRow) animView).getStatusBarNotification()
+                                .getPackageName());
             }
             if (mCurrIconRow != null) {
                 mCurrIconRow.setSnapping(true);
                 setSnappedToGear(true);
             }
             onDragCancelled(animView);
+
+            // If we're on the lockscreen we want to false this.
+            if (mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+                mHandler.removeCallbacks(mFalsingCheck);
+                mHandler.postDelayed(mFalsingCheck, COVER_GEAR_DELAY);
+            }
             super.snapChild(animView, target, velocity);
         }
 
         private boolean swipedEnoughToShowGear(View animView) {
-            final float snapBackThreshold = getSpaceForGear(animView);
+            if (mTranslatingParentView == null) {
+                return false;
+            }
+            // 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;
+            final float snapBackThreshold = getSpaceForGear(animView) * multiplier;
             final float translation = getTranslation(animView);
             final boolean fromLeft = translation > 0;
             final float absTrans = Math.abs(translation);
             final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
 
-            // 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;
+            return mCurrIconRow.isVisible() && (mCurrIconRow.isIconOnLeft()
+                    ? (translation > snapBackThreshold && translation <= notiThreshold)
+                    : (translation < -snapBackThreshold && translation >= -notiThreshold));
         }
 
         @Override
         public Animator getViewTranslationAnimator(View v, float target,
                 AnimatorUpdateListener listener) {
-            if (mDismissAllInProgress) {
-                // When dismissing all, we translate the entire view instead.
-                return super.getViewTranslationAnimator(v, target, listener);
-            } else if (v instanceof ExpandableNotificationRow) {
+            if (v instanceof ExpandableNotificationRow) {
                 return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
             } else {
                 return super.getViewTranslationAnimator(v, target, listener);
@@ -3660,21 +3665,42 @@
 
         @Override
         public void setTranslation(View v, float translate) {
-            if (mDismissAllInProgress) {
-                // When dismissing all, we translate the entire view instead.
-                super.setTranslation(v, translate);
-            } else {
-                ((ExpandableView) v).setTranslation(translate);
-            }
+            ((ExpandableView) v).setTranslation(translate);
         }
 
         @Override
         public float getTranslation(View v) {
-            if (mDismissAllInProgress) {
-                // When dismissing all, we translate the entire view instead.
-                return super.getTranslation(v);
-            } else {
-                return ((ExpandableView) v).getTranslation();
+            return ((ExpandableView) v).getTranslation();
+        }
+
+        public void closeControlsIfOutsideTouch(MotionEvent ev) {
+            NotificationGuts guts = mPhoneStatusBar.getExposedGuts();
+            View view = null;
+            int height = 0;
+            if (guts != null) {
+                // Checking guts
+                view = guts;
+                height = guts.getActualHeight();
+            } else if (mCurrIconRow != null && mCurrIconRow.isVisible()
+                    && mTranslatingParentView != null) {
+                // Checking gear
+                view = mTranslatingParentView;
+                height = ((ExpandableView) mTranslatingParentView).getActualHeight();
+            }
+            if (view != null) {
+                final int rx = (int) ev.getRawX();
+                final int ry = (int) ev.getRawY();
+
+                getLocationOnScreen(mTempInt2);
+                int[] location = new int[2];
+                view.getLocationOnScreen(location);
+                final int x = location[0] - mTempInt2[0];
+                final int y = location[1] - mTempInt2[1];
+                Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
+                if (!rect.contains((int) rx, (int) ry)) {
+                    // Touch was outside visible guts / gear notification, close what's visible
+                    mPhoneStatusBar.dismissPopups(-1, -1, true /* resetGear */, true /* animate */);
+                }
             }
         }
 
@@ -3711,7 +3737,7 @@
         private void checkForDrag() {
             if (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag)) {
                 mCheckForDrag = new CheckForDrag();
-                mHandler.postDelayed(mCheckForDrag, GEAR_SHOW_DELAY);
+                mHandler.postDelayed(mCheckForDrag, SHOW_GEAR_DELAY);
             }
         }
 
@@ -3725,6 +3751,9 @@
         private final class CheckForDrag implements Runnable {
             @Override
             public void run() {
+                if (mTranslatingParentView == null) {
+                    return;
+                }
                 final float translation = getTranslation(mTranslatingParentView);
                 final float absTransX = Math.abs(translation);
                 final float bounceBackToGearWidth = getSpaceForGear(mTranslatingParentView);
@@ -3740,20 +3769,24 @@
             }
         }
 
-        private void resetExposedGearView() {
-            if (mGearExposedView == null || mGearExposedView == mTranslatingParentView) {
+        public void resetExposedGearView(boolean animate, boolean force) {
+            if (mGearExposedView == null
+                    || (!force && mGearExposedView == mTranslatingParentView)) {
                 // If no gear is showing or it's showing for this view we do nothing.
                 return;
             }
-
             final View prevGearExposedView = mGearExposedView;
+            if (animate) {
+                Animator anim = getViewTranslationAnimator(prevGearExposedView,
+                        0 /* leftTarget */, null /* updateListener */);
+                if (anim != null) {
+                    anim.start();
+                }
+            } else if (mGearExposedView instanceof ExpandableNotificationRow) {
+                ((ExpandableNotificationRow) mGearExposedView).resetTranslation();
+            }
             mGearExposedView = null;
             mGearSnappedTo = false;
-            Animator anim = getViewTranslationAnimator(prevGearExposedView,
-                    0 /* leftTarget */, null /* updateListener */);
-            if (anim != null) {
-                anim.start();
-            }
         }
     }
 
@@ -3769,6 +3802,14 @@
         }
     }
 
+    public void resetExposedGearView(boolean animate, boolean force) {
+        mSwipeHelper.resetExposedGearView(animate, force);
+    }
+
+    public void closeControlsIfOutsideTouch(MotionEvent ev) {
+        mSwipeHelper.closeControlsIfOutsideTouch(ev);
+    }
+
     static class AnimationEvent {
 
         static AnimationFilter[] FILTERS = new AnimationFilter[] {
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 4c94fe9..c7333c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -368,7 +368,7 @@
             childViewState.location = StackViewState.LOCATION_UNKNOWN;
             paddingAfterChild = getPaddingAfterChild(algorithmState, child);
             int childHeight = getMaxAllowedChildHeight(child);
-            int minHeight = child.getMinHeight();
+            int collapsedHeight = child.getCollapsedHeight();
             childViewState.yTranslation = currentYPosition;
             if (i == 0) {
                 updateFirstChildHeight(child, childViewState, childHeight, ambientState);
@@ -384,7 +384,7 @@
                     // According to the regular scroll view we are fully translated out of the
                     // bottom of the screen so we are fully in the bottom stack
                     updateStateForChildFullyInBottomStack(algorithmState,
-                            bottomStackStart, childViewState, minHeight, ambientState, child);
+                            bottomStackStart, childViewState, collapsedHeight, ambientState, child);
                 } else {
                     // According to the regular scroll view we are currently translating out of /
                     // into the bottom of the screen
@@ -475,17 +475,17 @@
         float newTranslation = Math.max(ambientState.getTopPadding()
                 + ambientState.getStackTranslation(), childState.yTranslation);
         childState.height = (int) Math.max(childState.height - (newTranslation
-                - childState.yTranslation), row.getMinHeight());
+                - childState.yTranslation), row.getCollapsedHeight());
         childState.yTranslation = newTranslation;
     }
 
     private void clampHunToMaxTranslation(AmbientState ambientState, ExpandableNotificationRow row,
             StackViewState childState) {
         float newTranslation;
-        float bottomPosition = ambientState.getMaxHeadsUpTranslation() - row.getMinHeight();
+        float bottomPosition = ambientState.getMaxHeadsUpTranslation() - row.getCollapsedHeight();
         newTranslation = Math.min(childState.yTranslation, bottomPosition);
         childState.height = (int) Math.max(childState.height
-                - (childState.yTranslation - newTranslation), row.getMinHeight());
+                - (childState.yTranslation - newTranslation), row.getCollapsedHeight());
         childState.yTranslation = newTranslation;
     }
 
@@ -534,10 +534,10 @@
         float offset = mBottomStackIndentationFunctor.getValue(algorithmState.partialInBottom);
         algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
         int newHeight = childHeight;
-        if (childHeight > child.getMinHeight()) {
+        if (childHeight > child.getCollapsedHeight()) {
             newHeight = (int) Math.max(Math.min(transitioningPositionStart + offset -
                     getPaddingAfterChild(algorithmState, child) - currentYPosition, childHeight),
-                    child.getMinHeight());
+                    child.getCollapsedHeight());
             childViewState.height = newHeight;
         }
         childViewState.yTranslation = transitioningPositionStart + offset - newHeight
@@ -547,7 +547,7 @@
 
     private void updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
             float transitioningPositionStart, StackViewState childViewState,
-            int minHeight, AmbientState ambientState, ExpandableView child) {
+            int collapsedHeight, AmbientState ambientState, ExpandableView child) {
         float currentYPosition;
         algorithmState.itemsInBottomStack += 1.0f;
         if (algorithmState.itemsInBottomStack < MAX_ITEMS_IN_BOTTOM_STACK) {
@@ -568,16 +568,14 @@
             childViewState.location = StackViewState.LOCATION_BOTTOM_STACK_HIDDEN;
             currentYPosition = ambientState.getInnerHeight();
         }
-        childViewState.height = minHeight;
-        childViewState.yTranslation = currentYPosition - minHeight;
+        childViewState.height = collapsedHeight;
+        childViewState.yTranslation = currentYPosition - collapsedHeight;
     }
 
 
     /**
      * Update the height of the first child i.e clamp it to the bottom stack
      *
-     *
-
      * @param child the child to update
      * @param childViewState the viewstate of the child
      * @param childHeight the height of the child
@@ -591,7 +589,7 @@
                     mBottomStackSlowDownLength + ambientState.getScrollY();
             // Collapse and expand the first child while the shade is being expanded
         childViewState.height = (int) Math.max(Math.min(bottomPeekStart, (float) childHeight),
-                    child.getMinHeight());
+                    child.getCollapsedHeight());
     }
 
     /**
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 f9bb5e3..450001f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -19,6 +19,7 @@
 import android.content.ComponentName;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 import android.view.View;
@@ -29,12 +30,22 @@
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.tv.pip.PipManager;
 
-/*
+/**
  * Status bar implementation for "large screen" products that mostly present no on-screen nav
  */
 
 public class TvStatusBar extends BaseStatusBar {
 
+    /**
+     * Tracking calls to View.setSystemUiVisibility().
+     */
+    int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
+
+    /**
+     * Last value sent to window manager.
+     */
+    private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
+
     @Override
     public void setIcon(String slot, StatusBarIcon icon) {
     }
@@ -207,4 +218,30 @@
     @Override
     public void clickTile(ComponentName tile) {
     }
+
+    @Override
+    public void start() {
+        super.start();
+        putComponent(TvStatusBar.class, this);
+    }
+
+    public void updateRecentsVisibility(boolean visible) {
+        // Update the recents visibility flag
+        if (visible) {
+            mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
+        } else {
+            mSystemUiVisibility &= ~View.RECENT_APPS_VISIBLE;
+        }
+        notifyUiVisibilityChanged(mSystemUiVisibility);
+    }
+
+    private void notifyUiVisibilityChanged(int vis) {
+        try {
+            if (mLastDispatchedSystemUiVisibility != vis) {
+                mWindowManagerService.statusBarVisibilityChanged(vis);
+                mLastDispatchedSystemUiVisibility = vis;
+            }
+        } catch (RemoteException ex) {
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
index 15ad1f1..3f87611 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
@@ -16,11 +16,12 @@
 
 package com.android.systemui.tv.pip;
 
-import android.app.Activity;
 import android.content.Context;
 import android.media.session.MediaController;
 import android.media.session.PlaybackState;
 import android.view.View;
+import android.view.Gravity;
+import android.view.LayoutInflater;
 import android.view.View.OnFocusChangeListener;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -40,28 +41,29 @@
 /**
  * A view containing PIP controls including fullscreen, close, and media controls.
  */
-public class PipControlsView extends LinearLayout implements PipManager.Listener {
+public class PipControlsView extends LinearLayout {
     /**
      * An interface to listen user action.
      */
-    public interface Listener {
+    public abstract static interface Listener {
         /**
          * Called when an user clicks close PIP button.
          */
-        void onClosed();
-    }
+        public abstract void onClosed();
+    };
 
-    private final PipManager mPipManager = PipManager.getInstance();
     private MediaController mMediaController;
-    private Listener mListener;
 
-    private View mFullButtonView;
-    private View mFullDescriptionView;
-    private View mPlayPauseView;
-    private ImageView mPlayPauseButtonImageView;
-    private TextView mPlayPauseDescriptionTextView;
-    private View mCloseButtonView;
-    private View mCloseDescriptionView;
+    final PipManager mPipManager = PipManager.getInstance();
+    Listener mListener;
+
+    View mFullButtonView;
+    View mFullDescriptionView;
+    View mPlayPauseView;
+    ImageView mPlayPauseButtonImageView;
+    TextView mPlayPauseDescriptionTextView;
+    View mCloseButtonView;
+    View mCloseDescriptionView;
 
     private boolean mHasFocus;
     private OnFocusChangeListener mOnChildFocusChangeListener;
@@ -73,6 +75,13 @@
         }
     };
 
+    private PipManager.MediaListener mPipMediaListener = new PipManager.MediaListener() {
+        @Override
+        public void onMediaControllerChanged() {
+            updateMediaController();
+        }
+    };
+
     public PipControlsView(Context context) {
         this(context, null, 0, 0);
     }
@@ -87,6 +96,12 @@
 
     public PipControlsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        LayoutInflater inflater = (LayoutInflater) getContext()
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.tv_pip_controls, this);
+
+        setOrientation(LinearLayout.HORIZONTAL);
+        setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
     }
 
     @Override
@@ -161,13 +176,13 @@
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
         updateMediaController();
-        mPipManager.addListener(this);
+        mPipManager.addMediaListener(mPipMediaListener);
     }
 
     @Override
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        mPipManager.removeListener(this);
+        mPipManager.removeMediaListener(mPipMediaListener);
         if (mMediaController != null) {
             mMediaController.unregisterCallback(mMediaControllerCallback);
         }
@@ -230,24 +245,4 @@
     public void setListener(Listener listener) {
         mListener = listener;
     }
-
-    @Override
-    public void onPipEntered() { }
-
-    @Override
-    public void onPipActivityClosed() { }
-
-    @Override
-    public void onShowPipMenu() { }
-
-    @Override
-    public void onMoveToFullscreen() { }
-
-    @Override
-    public void onMediaControllerChanged() {
-        updateMediaController();
-    }
-
-    @Override
-    public void onPipResizeAboutToStart() { }
 }
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 68e0883..fe54090 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -62,9 +62,27 @@
 
     private static final int MAX_RUNNING_TASKS_COUNT = 10;
 
+    /**
+     * State when there's no PIP.
+     */
     public static final int STATE_NO_PIP = 0;
+    /**
+     * State when PIP is shown with an overlay message on top of it.
+     * This is used as default PIP state.
+     */
     public static final int STATE_PIP_OVERLAY = 1;
+    /**
+     * State when PIP menu dialog is shown.
+     */
     public static final int STATE_PIP_MENU = 2;
+    /**
+     * State when PIP is shown in Recents.
+     */
+    public static final int STATE_PIP_RECENTS = 3;
+    /**
+     * State when PIP is shown in Recents and it's focused to allow an user to control.
+     */
+    public static final int STATE_PIP_RECENTS_FOCUSED = 4;
 
     private static final int TASK_ID_NO_PIP = -1;
     private static final int INVALID_RESOURCE_TYPE = -1;
@@ -90,11 +108,13 @@
     private int mSuspendPipResizingReason;
 
     private Context mContext;
+    private PipRecentsOverlayManager mPipRecentsOverlayManager;
     private IActivityManager mActivityManager;
     private MediaSessionManager mMediaSessionManager;
     private int mState = STATE_NO_PIP;
     private final Handler mHandler = new Handler();
     private List<Listener> mListeners = new ArrayList<>();
+    private List<MediaListener> mMediaListeners = new ArrayList<>();
     private Rect mCurrentPipBounds;
     private Rect mPipBounds;
     private Rect mMenuModePipBounds;
@@ -107,9 +127,6 @@
     private MediaController mPipMediaController;
     private boolean mOnboardingShown;
 
-    private boolean mIsRecentsShown;
-    private boolean mIsPipFocusedInRecent;
-
     private final Runnable mResizePinnedStackRunnable = new Runnable() {
         @Override
         public void run() {
@@ -178,6 +195,7 @@
         mOnboardingShown = Prefs.getBoolean(
                 mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, false);
 
+        mPipRecentsOverlayManager = new PipRecentsOverlayManager(context);
         mMediaSessionManager =
                 (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
     }
@@ -231,7 +249,7 @@
     /**
      * Moves the PIPed activity to the fullscreen and closes PIP system UI.
      */
-    public void movePipToFullscreen() {
+    void movePipToFullscreen() {
         mState = STATE_NO_PIP;
         mPipTaskId = TASK_ID_NO_PIP;
         for (int i = mListeners.size() - 1; i >= 0; --i) {
@@ -247,7 +265,6 @@
      */
     private void showPipOverlay() {
         if (DEBUG) Log.d(TAG, "showPipOverlay()");
-        mState = STATE_PIP_OVERLAY;
         PipOverlayActivity.showPipOverlay(mContext);
     }
 
@@ -279,8 +296,10 @@
      * Resize the Pip to the appropriate size for the input state.
      * @param state In Pip state also used to determine the new size for the Pip.
      */
-    public void resizePinnedStack(int state) {
+    void resizePinnedStack(int state) {
         if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state);
+        boolean wasRecentsShown =
+                (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED);
         mState = state;
         for (int i = mListeners.size() - 1; i >= 0; --i) {
             mListeners.get(i).onPipResizeAboutToStart();
@@ -291,7 +310,6 @@
                             mSuspendPipResizingReason);
             return;
         }
-        int animationDurationMs = -1;
         switch (mState) {
             case STATE_NO_PIP:
                 mCurrentPipBounds = null;
@@ -300,25 +318,24 @@
                 mCurrentPipBounds = mMenuModePipBounds;
                 break;
             case STATE_PIP_OVERLAY:
-                if (mIsRecentsShown) {
-                    if (mCurrentPipBounds == mRecentsFocusedPipBounds
-                            || mCurrentPipBounds == mRecentsFocusedPipBounds) {
-                        animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
-                    }
-                    if (mIsPipFocusedInRecent) {
-                        mCurrentPipBounds = mRecentsFocusedPipBounds;
-                    } else {
-                        mCurrentPipBounds = mRecentsPipBounds;
-                    }
-                } else {
-                    mCurrentPipBounds = mPipBounds;
-                }
+                mCurrentPipBounds = mPipBounds;
+                break;
+            case STATE_PIP_RECENTS:
+                mCurrentPipBounds = mRecentsPipBounds;
+                break;
+            case STATE_PIP_RECENTS_FOCUSED:
+                mCurrentPipBounds = mRecentsFocusedPipBounds;
                 break;
             default:
                 mCurrentPipBounds = mPipBounds;
                 break;
         }
         try {
+            int animationDurationMs = -1;
+            if (wasRecentsShown
+                    && (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED)) {
+                animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
+            }
             mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds,
                     true, true, true, animationDurationMs);
         } catch (RemoteException e) {
@@ -327,67 +344,18 @@
     }
 
     /**
-     * Returns the current PIP bound for activities to sync their UI with PIP.
+     * Returns the default PIP bound.
      */
     public Rect getPipBounds() {
-        return mCurrentPipBounds;
+        return mPipBounds;
     }
 
     /**
-     * Called when Recents is started.
-     * PIPed activity will be resized accordingly and overlay will show available buttons.
+     * Returns the focused PIP bound while Recents is shown.
+     * This is used to place PIP controls in Recents.
      */
-    public void onRecentsStarted() {
-        mIsRecentsShown = true;
-        mIsPipFocusedInRecent = false;
-        if (mState == STATE_NO_PIP) {
-            return;
-        }
-        resizePinnedStack(STATE_PIP_OVERLAY);
-    }
-
-    /**
-     * Called when Recents is stopped.
-     * PIPed activity will be resized accordingly and overlay will hide available buttons.
-     */
-    public void onRecentsStopped() {
-        mIsRecentsShown = false;
-        mIsPipFocusedInRecent = false;
-        if (mState == STATE_NO_PIP) {
-            return;
-        }
-        resizePinnedStack(STATE_PIP_OVERLAY);
-    }
-
-    /**
-     * Returns {@code true} if recents is shown.
-     */
-    boolean isRecentsShown() {
-        return mIsRecentsShown;
-    }
-
-    /**
-     * Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
-     * is focused.
-     * This only resizes pinned stack so it looks like it's in Recents.
-     * This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
-     */
-    public void onPipViewFocusChangedInRecents(boolean hasFocus) {
-        mIsPipFocusedInRecent = hasFocus;
-        if (mState != STATE_PIP_OVERLAY) {
-            Log.w(TAG, "There is no pinned stack to handle focus change.");
-            return;
-        }
-        resizePinnedStack(STATE_PIP_OVERLAY);
-    }
-
-    /**
-     * Returns {@code true} if the PIP view in
-     * {@link com.android.systemui.recents.tv.RecentsTvActivity} is focused in Recents.
-     * This API is valid only when {@link isRecentsShown()} returns {@code true}.
-     */
-    boolean isPipViewFocusdInRecents() {
-        return mIsPipFocusedInRecent;
+    public Rect getRecentsFocusedPipBounds() {
+        return mRecentsFocusedPipBounds;
     }
 
     /**
@@ -396,6 +364,10 @@
      */
     private void showPipMenu() {
         if (DEBUG) Log.d(TAG, "showPipMenu()");
+        if (mPipRecentsOverlayManager.isRecentsShown()) {
+            if (DEBUG) Log.d(TAG, "Ignore showing PIP menu");
+            return;
+        }
         mState = STATE_PIP_MENU;
         for (int i = mListeners.size() - 1; i >= 0; --i) {
             mListeners.get(i).onShowPipMenu();
@@ -405,14 +377,34 @@
         mContext.startActivity(intent);
     }
 
+    /**
+     * Adds a {@link Listener} to PipManager.
+     */
     public void addListener(Listener listener) {
         mListeners.add(listener);
     }
 
+    /**
+     * Removes a {@link Listener} from PipManager.
+     */
     public void removeListener(Listener listener) {
         mListeners.remove(listener);
     }
 
+    /**
+     * Adds a {@link MediaListener} to PipManager.
+     */
+    public void addMediaListener(MediaListener listener) {
+        mMediaListeners.add(listener);
+    }
+
+    /**
+     * Removes a {@link MediaListener} from PipManager.
+     */
+    public void removeMediaListener(MediaListener listener) {
+        mMediaListeners.remove(listener);
+    }
+
     private void launchPipOnboardingActivityIfNeeded() {
         if (DEBUG_FORCE_ONBOARDING || !mOnboardingShown) {
             mOnboardingShown = true;
@@ -485,8 +477,8 @@
         }
         if (mPipMediaController != mediaController) {
             mPipMediaController = mediaController;
-            for (int i = mListeners.size() - 1; i >= 0; i--) {
-                mListeners.get(i).onMediaControllerChanged();
+            for (int i = mMediaListeners.size() - 1; i >= 0; i--) {
+                mMediaListeners.get(i).onMediaControllerChanged();
             }
             if (mPipMediaController == null) {
                 mHandler.postDelayed(mClosePipRunnable,
@@ -530,7 +522,7 @@
         return PLAYBACK_STATE_UNAVAILABLE;
     }
 
-    TaskStackListener mTaskStackListener = new TaskStackListener() {
+    private TaskStackListener mTaskStackListener = new TaskStackListener() {
         @Override
         public void onTaskStackChanged() {
             if (mState != STATE_NO_PIP) {
@@ -582,10 +574,10 @@
             mMediaSessionManager.addOnActiveSessionsChangedListener(
                     mActiveMediaSessionListener, null);
             updateMediaController(mMediaSessionManager.getActiveSessions(null));
-            if (mIsRecentsShown) {
+            if (mPipRecentsOverlayManager.isRecentsShown()) {
                 // If an activity becomes PIPed again after the fullscreen, the Recents is shown
                 // behind so we need to resize the pinned stack and show the correct overlay.
-                resizePinnedStack(STATE_PIP_OVERLAY);
+                resizePinnedStack(STATE_PIP_RECENTS);
             }
             for (int i = mListeners.size() - 1; i >= 0; i--) {
                 mListeners.get(i).onPipEntered();
@@ -604,7 +596,18 @@
             if (DEBUG) Log.d(TAG, "onPinnedStackAnimationEnded()");
             switch (mState) {
                 case STATE_PIP_OVERLAY:
-                    showPipOverlay();
+                    if (!mPipRecentsOverlayManager.isRecentsShown()) {
+                        showPipOverlay();
+                        break;
+                    } else {
+                        // This happens only if an activity is PIPed after the Recents is shown.
+                        // See {@link PipRecentsOverlayManager.requestFocus} for more details.
+                        resizePinnedStack(mState);
+                        break;
+                    }
+                case STATE_PIP_RECENTS:
+                case STATE_PIP_RECENTS_FOCUSED:
+                    mPipRecentsOverlayManager.addPipRecentsOverlayView();
                     break;
                 case STATE_PIP_MENU:
                     showPipMenu();
@@ -621,17 +624,23 @@
          * Invoked when an activity is pinned and PIP manager is set corresponding information.
          * Classes must use this instead of {@link android.app.ITaskStackListener.onActivityPinned}
          * because there's no guarantee for the PIP manager be return relavent information
-         * correctly. (e.g. {@link isPipShown}, {@link getPipBounds})
+         * correctly. (e.g. {@link isPipShown}).
          */
         void onPipEntered();
         /** Invoked when a PIPed activity is closed. */
         void onPipActivityClosed();
         /** Invoked when the PIP menu gets shown. */
         void onShowPipMenu();
-        /** Invoked when the PIPed activity is returned back to the fullscreen. */
+        /** Invoked when the PIPed activity is about to return back to the fullscreen. */
         void onMoveToFullscreen();
         /** Invoked when we are above to start resizing the Pip. */
         void onPipResizeAboutToStart();
+    }
+
+    /**
+     * A listener interface to receive change in PIP's media controller
+     */
+    public interface MediaListener {
         /** Invoked when the MediaController on PIPed activity is changed. */
         void onMediaControllerChanged();
     }
@@ -645,4 +654,11 @@
         }
         return sPipManager;
     }
+
+    /**
+     * Gets an instance of {@link PipRecentsOverlayManager}.
+     */
+    public PipRecentsOverlayManager getPipRecentsOverlayManager() {
+        return mPipRecentsOverlayManager;
+    }
 }
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 ea9275f..854e09d 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -20,12 +20,6 @@
 import android.os.Bundle;
 
 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;
 
 /**
  * Activity to show the PIP menu to control PIP.
@@ -36,7 +30,7 @@
     private final PipManager mPipManager = PipManager.getInstance();
 
     private PipControlsView mPipControlsView;
-    private boolean mPipMovedToFullscreen;
+    private boolean mRestorePipSizeWhenClose;
 
     @Override
     protected void onCreate(Bundle bundle) {
@@ -45,10 +39,12 @@
         mPipManager.addListener(this);
 
         mPipControlsView = (PipControlsView) findViewById(R.id.pip_controls);
+        mRestorePipSizeWhenClose = true;
     }
 
     private void restorePipAndFinish() {
-        if (!mPipMovedToFullscreen) {
+        if (mRestorePipSizeWhenClose) {
+            // When PIP menu activity is closed, restore to the default position.
             mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
         }
         finish();
@@ -86,31 +82,16 @@
 
     @Override
     public void onMoveToFullscreen() {
-        mPipMovedToFullscreen = true;
+        // Moving PIP to fullscreen is implemented by resizing PINNED_STACK with null bounds.
+        // This conflicts with restoring PIP position, so disable it.
+        mRestorePipSizeWhenClose = false;
         finish();
     }
 
     @Override
-    public void onMediaControllerChanged() { }
-
-    @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 79daf3d..86ceff4 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
@@ -86,7 +86,4 @@
 
     @Override
     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 12cb4cd..e205ff5 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
@@ -36,12 +36,12 @@
     private static final long SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS = 4000;
 
     /**
-     * The single instance of PipOverlayActivity to prevent it from restarting.
+     * A flag to ensure the single instance of PipOverlayActivity to prevent it from restarting.
      * Note that {@link PipManager} moves the PIPed activity to fullscreen if the activity is
      * restarted. It's because the activity may be started by the Launcher or an intent again,
      * but we don't want do so for the PipOverlayActivity.
      */
-    private static PipOverlayActivity sPipOverlayActivity;
+    private static boolean sActivityCreated;
 
     private final PipManager mPipManager = PipManager.getInstance();
     private final Handler mHandler = new Handler();
@@ -55,10 +55,10 @@
     };
 
     /**
-     * Launches the PIP overlay. This should be only called on the main thread.
+     * Shows PIP overlay UI only if it's not there.
      */
-    public static void showPipOverlay(Context context) {
-        if (sPipOverlayActivity == null) {
+    static void showPipOverlay(Context context) {
+        if (!sActivityCreated) {
             Intent intent = new Intent(context, PipOverlayActivity.class);
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             final ActivityOptions options = ActivityOptions.makeBasic();
@@ -70,31 +70,15 @@
     @Override
     protected void onCreate(Bundle bundle) {
         super.onCreate(bundle);
+        sActivityCreated = true;
         setContentView(R.layout.tv_pip_overlay);
         mGuideOverlayView = findViewById(R.id.guide_overlay);
-        mGuideButtonsView = findViewById(R.id.guide_buttons);
-        mGuideButtonPlayPauseImageView = (ImageView) findViewById(R.id.guide_button_play_pause);
         mPipManager.addListener(this);
-
-        sPipOverlayActivity = this;
     }
 
     @Override
     protected void onResume() {
         super.onResume();
-        // TODO: Implement animation for this
-        if (mPipManager.isRecentsShown()) {
-            mGuideOverlayView.setVisibility(View.GONE);
-            if (mPipManager.isPipViewFocusdInRecents()) {
-                mGuideButtonsView.setVisibility(View.GONE);
-            } else {
-                mGuideButtonsView.setVisibility(View.VISIBLE);
-                updateGuideButtonsView();
-            }
-        } else {
-            mGuideOverlayView.setVisibility(View.VISIBLE);
-            mGuideButtonsView.setVisibility(View.GONE);
-        }
         mHandler.removeCallbacks(mHideGuideOverlayRunnable);
         mHandler.postDelayed(mHideGuideOverlayRunnable, SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS);
     }
@@ -109,7 +93,7 @@
     @Override
     protected void onDestroy() {
         super.onDestroy();
-        sPipOverlayActivity = null;
+        sActivityCreated = false;
         mHandler.removeCallbacksAndMessages(null);
         mPipManager.removeListener(this);
         mPipManager.resumePipResizing(
@@ -140,32 +124,4 @@
         mPipManager.suspendPipResizing(
                 PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH);
     }
-
-    @Override
-    public void onMediaControllerChanged() {
-        updateGuideButtonsView();
-    }
-
-    @Override
-    public void finish() {
-        sPipOverlayActivity = null;
-        super.finish();
-    }
-
-    private void updateGuideButtonsView() {
-        switch (mPipManager.getPlaybackState()) {
-            case PipManager.PLAYBACK_STATE_PLAYING:
-                mGuideButtonPlayPauseImageView.setVisibility(View.VISIBLE);
-                mGuideButtonPlayPauseImageView.setImageResource(R.drawable.ic_pause_white_24dp);
-                break;
-            case PipManager.PLAYBACK_STATE_PAUSED:
-                mGuideButtonPlayPauseImageView.setVisibility(View.VISIBLE);
-                mGuideButtonPlayPauseImageView.setImageResource(
-                        R.drawable.ic_play_arrow_white_24dp);
-                break;
-            case PipManager.PLAYBACK_STATE_UNAVAILABLE:
-                mGuideButtonPlayPauseImageView.setVisibility(View.GONE);
-                break;
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
new file mode 100644
index 0000000..8b8c105
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.tv.pip;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorSet;
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnFocusChangeListener;
+
+import com.android.systemui.R;
+
+import static com.android.systemui.tv.pip.PipManager.PLAYBACK_STATE_PLAYING;
+import static com.android.systemui.tv.pip.PipManager.PLAYBACK_STATE_PAUSED;
+import static com.android.systemui.tv.pip.PipManager.PLAYBACK_STATE_UNAVAILABLE;
+
+/**
+ * An extended version of {@link PipControlsView} that supports animation in Recents.
+ */
+public class PipRecentsControlsView extends PipControlsView {
+    /**
+     * An interface to listen user action.
+     */
+    public interface Listener extends PipControlsView.Listener {
+        /**
+         * Called when an user presses BACK key and up.
+         */
+        abstract void onBackPressed();
+    }
+
+    private AnimatorSet mFocusGainAnimatorSet;
+    private AnimatorSet mFocusLoseAnimatorSet;
+
+    public PipRecentsControlsView(Context context) {
+        this(context, null, 0, 0);
+    }
+
+    public PipRecentsControlsView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0, 0);
+    }
+
+    public PipRecentsControlsView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public PipRecentsControlsView(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    public void onFinishInflate() {
+        super.onFinishInflate();
+
+        int buttonsFocusGainAnim = R.anim.tv_pip_controls_buttons_in_recents_focus_gain_animation;
+        int textFocusGainAnim = R.anim.tv_pip_controls_text_in_recents_focus_gain_animation;
+        mFocusGainAnimatorSet = new AnimatorSet();
+        mFocusGainAnimatorSet.playTogether(
+                loadAnimator(this, R.anim.tv_pip_controls_in_recents_focus_gain_animation),
+                loadAnimator(mFullButtonView,buttonsFocusGainAnim),
+                loadAnimator(mPlayPauseButtonImageView, buttonsFocusGainAnim),
+                loadAnimator(mCloseButtonView, buttonsFocusGainAnim),
+                loadAnimator(mFullDescriptionView, textFocusGainAnim),
+                loadAnimator(mPlayPauseDescriptionTextView, textFocusGainAnim),
+                loadAnimator(mCloseDescriptionView, textFocusGainAnim));
+
+        int buttonsFocusLoseAnim = R.anim.tv_pip_controls_buttons_in_recents_focus_lose_animation;
+        int textFocusLoseAnim = R.anim.tv_pip_controls_text_in_recents_focus_lose_animation;
+        mFocusLoseAnimatorSet = new AnimatorSet();
+        mFocusLoseAnimatorSet.playTogether(
+                loadAnimator(this, R.anim.tv_pip_controls_in_recents_focus_lose_animation),
+                loadAnimator(mFullButtonView, buttonsFocusLoseAnim),
+                loadAnimator(mPlayPauseButtonImageView, buttonsFocusLoseAnim),
+                loadAnimator(mCloseButtonView, buttonsFocusLoseAnim),
+                loadAnimator(mFullDescriptionView, textFocusLoseAnim),
+                loadAnimator(mPlayPauseDescriptionTextView, textFocusLoseAnim),
+                loadAnimator(mCloseDescriptionView, textFocusLoseAnim));
+
+        Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
+        int pipControlsMarginTop = getContext().getResources().getDimensionPixelSize(
+                R.dimen.recents_tv_pip_controls_margin_top);
+        setPadding(0, pipBounds.bottom + pipControlsMarginTop, 0, 0);
+    }
+
+    private Animator loadAnimator(View view, int animatorResId) {
+        Animator animator = AnimatorInflater.loadAnimator(getContext(), animatorResId);
+        animator.setTarget(view);
+        return animator;
+    }
+
+    /**
+     * Starts focus gaining animation.
+     */
+    public void startFocusGainAnimation() {
+        if (mFocusLoseAnimatorSet.isStarted()) {
+            mFocusLoseAnimatorSet.cancel();
+        }
+        mFocusGainAnimatorSet.start();
+    }
+
+    /**
+     * Starts focus losing animation.
+     */
+    public void startFocusLoseAnimation() {
+        if (mFocusGainAnimatorSet.isStarted()) {
+            mFocusGainAnimatorSet.cancel();
+        }
+        mFocusLoseAnimatorSet.start();
+    }
+
+    /**
+     * Resets the view to the initial state. (i.e. end of the focus gain)
+     */
+    public void reset() {
+        if (mFocusGainAnimatorSet.isStarted()) {
+            mFocusGainAnimatorSet.cancel();
+        }
+        if (mFocusLoseAnimatorSet.isStarted()) {
+            mFocusLoseAnimatorSet.cancel();
+        }
+
+        // Reset to initial state (i.e. end of focused)
+        requestFocus();
+        setTranslationY(0);
+        setScaleXY(mFullButtonView, 1);
+        setScaleXY(mPlayPauseButtonImageView, 1);
+        setScaleXY(mCloseButtonView, 1);
+        mFullDescriptionView.setAlpha(1);
+        mPlayPauseDescriptionTextView.setAlpha(1);
+        mCloseDescriptionView.setAlpha(1);
+    }
+
+    private void setScaleXY(View view, float scale) {
+        view.setScaleX(scale);
+        view.setScaleY(scale);
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (!event.isCanceled()
+                && event.getKeyCode() == KeyEvent.KEYCODE_BACK
+                && event.getAction() == KeyEvent.ACTION_UP) {
+            if (mListener != null) {
+                ((PipRecentsControlsView.Listener) mListener).onBackPressed();
+            }
+            return true;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
new file mode 100644
index 0000000..47cd8e5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.tv.pip;
+
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorSet;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager.LayoutParams;
+import android.view.WindowManager;
+
+import com.android.systemui.R;
+
+import static com.android.systemui.tv.pip.PipManager.STATE_PIP_OVERLAY;
+import static com.android.systemui.tv.pip.PipManager.STATE_PIP_RECENTS;
+import static com.android.systemui.tv.pip.PipManager.STATE_PIP_RECENTS_FOCUSED;
+
+public class PipRecentsOverlayManager {
+    private static final String TAG = "PipRecentsOverlayManager";
+
+    public interface Callback {
+        void onClosed();
+        void onBackPressed();
+        void onRecentsFocused();
+    }
+
+    private final PipManager mPipManager = PipManager.getInstance();
+    private final WindowManager mWindowManager;
+    private final View mOverlayView;
+    private final PipRecentsControlsView mPipControlsView;
+    private final View mRecentsView;
+
+    private final LayoutParams mPipRecentsControlsViewLayoutParams;
+    private final LayoutParams mPipRecentsControlsViewFocusedLayoutParams;
+
+    private boolean mIsPipRecentsOverlayShown;
+    private boolean mIsRecentsShown;
+    private boolean mIsPipFocusedInRecent;
+    private Callback mCallback;
+    private PipRecentsControlsView.Listener mPipControlsViewListener =
+            new PipRecentsControlsView.Listener() {
+                @Override
+                public void onClosed() {
+                    if (mCallback != null) {
+                        mCallback.onClosed();
+                    }
+                }
+
+                @Override
+                public void onBackPressed() {
+                    if (mCallback != null) {
+                        mCallback.onBackPressed();
+                    }
+                }
+            };
+
+    PipRecentsOverlayManager(Context context) {
+        mWindowManager = (WindowManager) context.getSystemService(WindowManager.class);
+
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        mOverlayView = inflater.inflate(R.layout.tv_pip_recents_overlay, null);
+        mPipControlsView = (PipRecentsControlsView) mOverlayView.findViewById(R.id.pip_controls);
+        mRecentsView = mOverlayView.findViewById(R.id.recents);
+        mRecentsView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+            @Override
+            public void onFocusChange(View v, boolean hasFocus) {
+                if (hasFocus) {
+                    clearFocus();
+                }
+            }
+        });
+
+        mPipRecentsControlsViewLayoutParams = new WindowManager.LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
+                LayoutParams.TYPE_SYSTEM_DIALOG,
+                LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE,
+                PixelFormat.TRANSLUCENT);
+        mPipRecentsControlsViewFocusedLayoutParams = new WindowManager.LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
+                LayoutParams.TYPE_SYSTEM_DIALOG,
+                0,
+                PixelFormat.TRANSLUCENT);
+    }
+
+    /**
+     * Add Recents overlay view.
+     * This is expected to be called after the PIP animation is over.
+     */
+    void addPipRecentsOverlayView() {
+        if (mIsPipRecentsOverlayShown) {
+            return;
+        }
+        mIsPipRecentsOverlayShown = true;
+        mIsPipFocusedInRecent = true;
+        mPipControlsView.reset();
+        mWindowManager.addView(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
+    }
+
+    /**
+     * Remove Recents overlay view.
+     * This should be called when Recents or PIP is closed.
+     */
+    public void removePipRecentsOverlayView() {
+        if (!mIsPipRecentsOverlayShown) {
+            return;
+        }
+        mWindowManager.removeView(mOverlayView);
+        mIsPipRecentsOverlayShown = false;
+    }
+
+    /**
+     * Request focus to the PIP Recents overlay.
+     * Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
+     * is focused.
+     * This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
+     * @param allowRecentsFocusable {@code true} if Recents can have focus. (i.e. Has a recent task)
+     */
+    public void requestFocus(boolean allowRecentsFocusable) {
+        if (!mIsRecentsShown || mIsPipFocusedInRecent) {
+            return;
+        }
+        mIsPipFocusedInRecent = true;
+        mPipManager.resizePinnedStack(STATE_PIP_RECENTS_FOCUSED);
+
+        mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
+        mPipControlsView.requestFocus();
+        mPipControlsView.startFocusGainAnimation();
+        mRecentsView.setVisibility(allowRecentsFocusable ? View.VISIBLE : View.GONE);
+    }
+
+    /**
+     * Request focus to the PIP Recents overlay.
+     * Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
+     * is focused.
+     * This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
+     */
+    private void clearFocus() {
+        if (!mIsRecentsShown || !mIsPipFocusedInRecent) {
+            return;
+        }
+        mIsPipFocusedInRecent = false;
+        mPipManager.resizePinnedStack(STATE_PIP_RECENTS);
+        mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewLayoutParams);
+        mPipControlsView.startFocusLoseAnimation();
+        if (mCallback != null) {
+            mCallback.onRecentsFocused();
+        }
+    }
+
+    public void setCallback(Callback listener) {
+        mCallback = listener;
+        mPipControlsView.setListener(mCallback != null ? mPipControlsViewListener : null);
+    }
+
+    /**
+     * Called when Recents is resumed.
+     * PIPed activity will be resized accordingly and overlay will show available buttons.
+     */
+    public void onRecentsResumed() {
+        if (!mPipManager.isPipShown()) {
+            return;
+        }
+        mIsRecentsShown = true;
+        mIsPipFocusedInRecent = true;
+        mPipManager.resizePinnedStack(STATE_PIP_RECENTS_FOCUSED);
+        // Overlay view will be added after the resize animation ends, if any.
+    }
+
+    /**
+     * Called when Recents is paused.
+     * PIPed activity will be resized accordingly and overlay will hide available buttons.
+     */
+    public void onRecentsPaused() {
+        mIsRecentsShown = false;
+        mIsPipFocusedInRecent = false;
+        removePipRecentsOverlayView();
+
+        if (mPipManager.isPipShown()) {
+            mPipManager.resizePinnedStack(STATE_PIP_OVERLAY);
+        }
+    }
+
+    /**
+     * Returns {@code true} if recents is shown.
+     */
+    boolean isRecentsShown() {
+        return mIsRecentsShown;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
index f432808..c6e4356 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
@@ -35,11 +35,11 @@
     private static final Typeface MEDIUM = Typeface.create("sans-serif-medium", Typeface.NORMAL);
 
     private final Context mContext;
-    private final LayoutInflater mInflater;
+    protected final LayoutInflater mInflater;
     private final SpTexts mSpTexts;
 
     private Callback mCallback;
-    private Object mSelectedValue;
+    protected Object mSelectedValue;
 
     public SegmentedButtons(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -65,13 +65,21 @@
             final Object tag = c.getTag();
             final boolean selected = Objects.equals(mSelectedValue, tag);
             c.setSelected(selected);
-            c.setTypeface(selected ? MEDIUM : REGULAR);
+            setSelectedStyle(c, selected);
         }
         fireOnSelected(fromClick);
     }
 
+    protected void setSelectedStyle(TextView textView, boolean selected) {
+        textView.setTypeface(selected ? MEDIUM : REGULAR);
+    }
+
+    public Button inflateButton() {
+        return (Button) mInflater.inflate(R.layout.segmented_button, this, false);
+    }
+
     public void addButton(int labelResId, int contentDescriptionResId, Object value) {
-        final Button b = (Button) mInflater.inflate(R.layout.segmented_button, this, false);
+        final Button b = inflateButton();
         b.setTag(LABEL_RES_KEY, labelResId);
         b.setText(labelResId);
         b.setContentDescription(getResources().getString(contentDescriptionResId));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
index 6a81659..a30f507 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
@@ -198,7 +198,7 @@
     }
 
     private void waitForCallback(String callback) {
-        for (int i = 0; i < 25; i++) {
+        for (int i = 0; i < 50; i++) {
             if (mCallbacks.contains(callback)) {
                 mCallbacks.remove(callback);
                 return;
@@ -229,7 +229,7 @@
                 }
             });
             try {
-                lock.wait(5000);
+                lock.wait(10000);
             } catch (InterruptedException e) {
             }
         }
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 81f63ae..9ec6e8d 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -380,6 +380,7 @@
             Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e);
             throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e);
         }
+        guard.open("destroy");
     }
 
     Allocation(long id, RenderScript rs, Type t, int usage, MipmapControl mips) {
@@ -1915,6 +1916,7 @@
             if (type.getID(rs) == 0) {
                 throw new RSInvalidStateException("Bad Type");
             }
+            // TODO: What if there is an exception after this? The native allocation would leak.
             long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
             if (id == 0) {
                 throw new RSRuntimeException("Allocation creation failed.");
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
index 1372ab7..f95af16 100644
--- a/rs/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -16,6 +16,7 @@
 
 package android.renderscript;
 
+import dalvik.system.CloseGuard;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 /**
@@ -69,6 +70,7 @@
     }
 
     private long mID;
+    final CloseGuard guard = CloseGuard.get();
     private boolean mDestroyed;
     private String mName;
     RenderScript mRS;
@@ -119,6 +121,7 @@
         }
 
         if (shouldDestroy) {
+            guard.close();
             // must include nObjDestroy in the critical section
             ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock();
             rlock.lock();
@@ -133,8 +136,14 @@
     }
 
     protected void finalize() throws Throwable {
-        helpDestroy();
-        super.finalize();
+        try {
+            if (guard != null) {
+                guard.warnIfOpen();
+            }
+            helpDestroy();
+        } finally {
+            super.finalize();
+        }
     }
 
     /**
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index 6efb6d6..50226ac 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -808,6 +808,7 @@
             mSize += mElements[ct].mSize * mArraySizes[ct];
         }
         updateVisibleSubElements();
+        guard.open("destroy");
     }
 
     Element(long id, RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) {
@@ -827,6 +828,7 @@
         mKind = dk;
         mNormalized = norm;
         mVectorSize = size;
+        guard.open("destroy");
     }
 
     Element(long id, RenderScript rs) {
diff --git a/rs/java/android/renderscript/FileA3D.java b/rs/java/android/renderscript/FileA3D.java
index 9d8f162..278d309 100644
--- a/rs/java/android/renderscript/FileA3D.java
+++ b/rs/java/android/renderscript/FileA3D.java
@@ -170,6 +170,7 @@
     FileA3D(long id, RenderScript rs, InputStream stream) {
         super(id, rs);
         mInputStream = stream;
+        guard.open("destroy");
     }
 
     private void initEntries() {
diff --git a/rs/java/android/renderscript/Font.java b/rs/java/android/renderscript/Font.java
index 4318b9d..d5ca31e 100644
--- a/rs/java/android/renderscript/Font.java
+++ b/rs/java/android/renderscript/Font.java
@@ -150,6 +150,7 @@
 
     Font(long id, RenderScript rs) {
         super(id, rs);
+        guard.open("destroy");
     }
 
     /**
diff --git a/rs/java/android/renderscript/Mesh.java b/rs/java/android/renderscript/Mesh.java
index 13c8e1c..9e4f905 100644
--- a/rs/java/android/renderscript/Mesh.java
+++ b/rs/java/android/renderscript/Mesh.java
@@ -91,6 +91,7 @@
 
     Mesh(long id, RenderScript rs) {
         super(id, rs);
+        guard.open("destroy");
     }
 
     /**
diff --git a/rs/java/android/renderscript/Program.java b/rs/java/android/renderscript/Program.java
index 3eb9b75..772021c 100644
--- a/rs/java/android/renderscript/Program.java
+++ b/rs/java/android/renderscript/Program.java
@@ -76,6 +76,7 @@
 
     Program(long id, RenderScript rs) {
         super(id, rs);
+        guard.open("destroy");
     }
 
     /**
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 9beaba3..2650e5a 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -1031,7 +1031,6 @@
 
 
 
-    long     mDev;
     long     mContext;
     private boolean mDestroyed = false;
 
@@ -1426,8 +1425,8 @@
 
         RenderScript rs = new RenderScript(ctx);
 
-        rs.mDev = rs.nDeviceCreate();
-        rs.mContext = rs.nContextCreate(rs.mDev, flags, sdkVersion, ct.mID);
+        long device = rs.nDeviceCreate();
+        rs.mContext = rs.nContextCreate(device, flags, sdkVersion, ct.mID);
         rs.mContextType = ct;
         rs.mContextFlags = flags;
         rs.mContextSdkVersion = sdkVersion;
@@ -1635,9 +1634,6 @@
             }
 
             nContextDestroy();
-
-            nDeviceDestroy(mDev);
-            mDev = 0;
         }
     }
 
diff --git a/rs/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
index 6178994..be1f899 100644
--- a/rs/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -177,9 +177,9 @@
 
         mWidth = 0;
         mHeight = 0;
-        mDev = nDeviceCreate();
+        long device = nDeviceCreate();
         int dpi = ctx.getResources().getDisplayMetrics().densityDpi;
-        mContext = nContextCreateGL(mDev, 0, sdkVersion,
+        mContext = nContextCreateGL(device, 0, sdkVersion,
                                     mSurfaceConfig.mColorMin, mSurfaceConfig.mColorPref,
                                     mSurfaceConfig.mAlphaMin, mSurfaceConfig.mAlphaPref,
                                     mSurfaceConfig.mDepthMin, mSurfaceConfig.mDepthPref,
diff --git a/rs/java/android/renderscript/Sampler.java b/rs/java/android/renderscript/Sampler.java
index a4edbb5..5c4bae9 100644
--- a/rs/java/android/renderscript/Sampler.java
+++ b/rs/java/android/renderscript/Sampler.java
@@ -51,6 +51,7 @@
 
     Sampler(long id, RenderScript rs) {
         super(id, rs);
+        guard.open("destroy");
     }
 
     /**
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index f6f93cb..fc3280b 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -41,6 +41,7 @@
             mScript = s;
             mSlot = slot;
             mSig = sig;
+            guard.open("destroy");
         }
     }
 
@@ -118,6 +119,7 @@
             super(id, rs);
             mScript = s;
             mSlot = slot;
+            guard.open("destroy");
         }
     }
 
@@ -357,6 +359,19 @@
         super(id, rs);
 
         mInIdsBuffer = new long[1];
+
+        /* The constructors for the derived classes (including ScriptIntrinsic
+         * derived classes and ScriptC derived classes generated by Slang
+         * reflection) seem to be simple enough, so we just put the guard.open()
+         * call here, rather than in the end of the constructor for the derived
+         * class. This, of course, assumes the derived constructor would not
+         * throw any exception after calling this constructor.
+         *
+         * If new derived classes are added with more complicated constructors
+         * that throw exceptions, this call has to be (duplicated and) moved
+         * to the end of each derived class constructor.
+         */
+        guard.open("destroy");
     }
 
     /**
diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
index 9357c3bb..219f16b 100644
--- a/rs/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -148,6 +148,8 @@
                                         fieldIDs, values, sizes, depClosures, depFieldIDs);
 
             setID(id);
+
+            guard.open("destroy");
         }
 
         Closure(RenderScript rs, Script.InvokeID invokeID,
@@ -181,6 +183,8 @@
                                               values, sizes);
 
             setID(id);
+
+            guard.open("destroy");
         }
 
         private void retrieveValueAndDependenceInfo(RenderScript rs,
@@ -382,6 +386,7 @@
 
     ScriptGroup(long id, RenderScript rs) {
         super(id, rs);
+        guard.open("destroy");
     }
 
     ScriptGroup(RenderScript rs, String name, List<Closure> closures,
@@ -398,6 +403,7 @@
         }
         long id = rs.nScriptGroup2Create(name, RenderScript.getCachePath(), closureIDs);
         setID(id);
+        guard.open("destroy");
     }
 
     /**
diff --git a/rs/java/android/renderscript/Type.java b/rs/java/android/renderscript/Type.java
index dc23785..9252898 100644
--- a/rs/java/android/renderscript/Type.java
+++ b/rs/java/android/renderscript/Type.java
@@ -227,6 +227,7 @@
 
     Type(long id, RenderScript rs) {
         super(id, rs);
+        guard.open("destroy");
     }
 
     @Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 3e7466f..613f890 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -363,12 +363,6 @@
     private void enableFeatures() {
         resetStreamState();
 
-        if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
-            mMotionEventInjector = new MotionEventInjector(mContext.getMainLooper());
-            addFirstEventHandler(mMotionEventInjector);
-            mAms.setMotionEventInjector(mMotionEventInjector);
-        }
-
         if ((mEnabledFeatures & FLAG_FEATURE_AUTOCLICK) != 0) {
             mAutoclickController = new AutoclickController(mContext, mUserId);
             addFirstEventHandler(mAutoclickController);
@@ -384,6 +378,12 @@
             addFirstEventHandler(mMagnificationGestureHandler);
         }
 
+        if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
+            mMotionEventInjector = new MotionEventInjector(mContext.getMainLooper());
+            addFirstEventHandler(mMotionEventInjector);
+            mAms.setMotionEventInjector(mMotionEventInjector);
+        }
+
         if ((mEnabledFeatures & FLAG_FEATURE_FILTER_KEY_EVENTS) != 0) {
             mKeyboardInterceptor = new KeyboardInterceptor(mAms);
             addFirstEventHandler(mKeyboardInterceptor);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 4b96e7a..2741733 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1262,7 +1262,7 @@
             Service service = componentNameToServiceMap.get(componentName);
 
             // Ignore non-encryption-aware services until user is unlocked
-            if (!isUnlocked && !installedService.isEncryptionAware()) {
+            if (!isUnlocked && !installedService.isDirectBootAware()) {
                 Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName);
                 continue;
             }
@@ -1784,10 +1784,15 @@
                     userState.mEnabledServices.contains(userState.mServiceChangingSoftKeyboardMode);
 
             if (!serviceChangingSoftKeyboardModeIsEnabled) {
-                Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                        Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
-                        0,
-                        userState.mUserId);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                            Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                            0,
+                            userState.mUserId);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
                 userState.mSoftKeyboardShowMode = 0;
                 userState.mServiceChangingSoftKeyboardMode = null;
             }
@@ -2146,7 +2151,7 @@
     MagnificationController getMagnificationController() {
         synchronized (mLock) {
             if (mMagnificationController == null) {
-                mMagnificationController = new MagnificationController(mContext, this);
+                mMagnificationController = new MagnificationController(mContext, this, mLock);
                 mMagnificationController.register();
                 mMagnificationController.setUserId(mCurrentUserId);
             }
@@ -3491,6 +3496,8 @@
             reportedWindow.setLayer(window.layer);
             reportedWindow.setFocused(window.focused);
             reportedWindow.setBoundsInScreen(window.boundsInScreen);
+            reportedWindow.setTitle(window.title);
+            reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
 
             final int parentId = findWindowIdLocked(window.parentToken);
             if (parentId >= 0) {
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index e15b785..fb1ef37 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -72,7 +72,7 @@
      */
     private static final float MIN_PERSISTED_SCALE = 2.0f;
 
-    private final Object mLock = new Object();
+    private final Object mLock;
 
     /**
      * The current magnification spec. If an animation is running, this
@@ -97,12 +97,13 @@
 
     private int mUserId;
 
-    public MagnificationController(Context context, AccessibilityManagerService ams) {
+    public MagnificationController(Context context, AccessibilityManagerService ams, Object lock) {
         mAms = ams;
         mContentResolver = context.getContentResolver();
         mScreenStateObserver = new ScreenStateObserver(context, this);
         mWindowStateObserver = new WindowStateObserver(context, this);
         mSpecAnimationBridge = new SpecAnimationBridge(context);
+        mLock = lock;
     }
 
     /**
@@ -155,10 +156,10 @@
             final float offsetY = sentSpec.offsetY;
 
             // Compute the new center and update spec as needed.
-            final float centerX = (mMagnifiedBounds.width() / 2.0f
-                    + mMagnifiedBounds.left - offsetX) / scale;
-            final float centerY = (mMagnifiedBounds.height() / 2.0f
-                    + mMagnifiedBounds.top - offsetY) / scale;
+            final float centerX = (mMagnifiedBounds.width() / 2.0f - offsetX) / scale
+                    + mMagnifiedBounds.left;
+            final float centerY = (mMagnifiedBounds.height() / 2.0f - offsetY) / scale
+                    + mMagnifiedBounds.top;
             if (updateSpec) {
                 setScaleAndCenter(scale, centerX, centerY, false);
             } else {
@@ -255,7 +256,7 @@
     public float getCenterX() {
         synchronized (mLock) {
             return  (mMagnifiedBounds.width() / 2.0f
-                    + mMagnifiedBounds.left - getOffsetX()) / getScale();
+                   - getOffsetX()) / getScale() + mMagnifiedBounds.left;
         }
     }
 
@@ -278,7 +279,7 @@
     public float getCenterY() {
         synchronized (mLock) {
             return (mMagnifiedBounds.height() / 2.0f
-                    + mMagnifiedBounds.top - getOffsetY()) / getScale();
+                    - getOffsetY()) / getScale() + mMagnifiedBounds.top;
         }
     }
 
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 89b145e2..f93fb1b 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -164,7 +164,8 @@
                 onUserStopped(userId);
             } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                 reloadWidgetsMaskedStateForGroup(userId);
-            } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
+            } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
+                    || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
                 synchronized (mLock) {
                     reloadWidgetsMaskedState(userId);
                 }
@@ -288,7 +289,8 @@
                 userFilter, null, null);
 
         IntentFilter offModeFilter = new IntentFilter();
-        offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+        offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+        offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
                 offModeFilter, null, null);
 
@@ -594,27 +596,28 @@
         }
         final boolean showBadge;
         final Intent onClickIntent;
-        if (provider.maskedBySuspendedPackage) {
-            final long identity = Binder.clearCallingIdentity();
-            try {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            if (provider.maskedBySuspendedPackage) {
                 UserInfo userInfo = mUserManager.getUserInfo(providerUserId);
                 showBadge = userInfo.isManagedProfile();
                 onClickIntent = mDevicePolicyManagerInternal.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);
+                }
             }
-        } 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);
-            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
 
         for (int j = 0; j < widgetCount; j++) {
@@ -742,8 +745,8 @@
     }
 
     @Override
-    public int[] startListening(IAppWidgetHost callbacks, String callingPackage,
-            int hostId, List<RemoteViews> updatedViews) {
+    public ParceledListSlice<RemoteViews> startListening(IAppWidgetHost callbacks,
+            String callingPackage, int hostId, int[] appWidgetIds, int[] updatedIds) {
         final int userId = UserHandle.getCallingUserId();
 
         if (DEBUG) {
@@ -760,21 +763,21 @@
             // sure the caller can only access hosts it owns.
             HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
             Host host = lookupOrAddHostLocked(id);
-
             host.callbacks = callbacks;
 
-            updatedViews.clear();
-
-            ArrayList<Widget> instances = host.widgets;
-            int N = instances.size();
-            int[] updatedIds = new int[N];
+            int N = appWidgetIds.length;
+            ArrayList<RemoteViews> outViews = new ArrayList<>(N);
+            RemoteViews rv;
+            int added = 0;
             for (int i = 0; i < N; i++) {
-                Widget widget = instances.get(i);
-                updatedIds[i] = widget.appWidgetId;
-                updatedViews.add(cloneIfLocalBinder(widget.getEffectiveViewsLocked()));
+                rv = host.getPendingViewsForId(appWidgetIds[i]);
+                if (rv != null) {
+                    updatedIds[added] = appWidgetIds[i];
+                    outViews.add(rv);
+                    added++;
+                }
             }
-
-            return updatedIds;
+            return new ParceledListSlice<>(outViews);
         }
     }
 
@@ -1882,6 +1885,10 @@
     }
 
     private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
+        long requestTime = SystemClock.uptimeMillis();
+        if (widget != null) {
+            widget.lastUpdateTime = requestTime;
+        }
         if (widget == null || widget.provider == null || widget.provider.zombie
                 || widget.host.callbacks == null || widget.host.zombie) {
             return;
@@ -1891,6 +1898,7 @@
         args.arg1 = widget.host;
         args.arg2 = widget.host.callbacks;
         args.arg3 = updateViews;
+        args.arg4 = requestTime;
         args.argi1 = widget.appWidgetId;
 
         mCallbackHandler.obtainMessage(
@@ -1899,9 +1907,10 @@
     }
 
     private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks,
-            int appWidgetId, RemoteViews views) {
+            int appWidgetId, RemoteViews views, long requestTime) {
         try {
             callbacks.updateAppWidget(appWidgetId, views);
+            host.lastWidgetUpdateTime = requestTime;
         } catch (RemoteException re) {
             synchronized (mLock) {
                 Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -3398,10 +3407,11 @@
                     Host host = (Host) args.arg1;
                     IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
                     RemoteViews views = (RemoteViews) args.arg3;
+                    long requestTime = (Long) args.arg4;
                     final int appWidgetId = args.argi1;
                     args.recycle();
 
-                    handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views);
+                    handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views, requestTime);
                 } break;
 
                 case MSG_NOTIFY_PROVIDER_CHANGED: {
@@ -3769,6 +3779,7 @@
         boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
 
         int tag = TAG_UNDEFINED; // for use while saving state (the index)
+        long lastWidgetUpdateTime; // last time we were successfully able to send an update.
 
         public int getUserId() {
             return UserHandle.getUserId(id.uid);
@@ -3790,6 +3801,23 @@
             return false;
         }
 
+        /**
+         * Returns the RemoveViews for the provided widget id if an update is pending
+         * for that widget.
+         */
+        public RemoteViews getPendingViewsForId(int appWidgetId) {
+            long updateTime = lastWidgetUpdateTime;
+            int N = widgets.size();
+            for (int i = 0; i < N; i++) {
+                Widget widget = widgets.get(i);
+                if (widget.appWidgetId == appWidgetId
+                        && widget.lastUpdateTime > updateTime) {
+                    return cloneIfLocalBinder(widget.getEffectiveViewsLocked());
+                }
+            }
+            return null;
+        }
+
         @Override
         public String toString() {
             return "Host{" + id + (zombie ? " Z" : "") + '}';
@@ -3860,6 +3888,7 @@
         RemoteViews maskedViews;
         Bundle options;
         Host host;
+        long lastUpdateTime;
 
         @Override
         public String toString() {
diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java
index a0b5c15..e98b4aa 100644
--- a/services/core/java/com/android/server/AnyMotionDetector.java
+++ b/services/core/java/com/android/server/AnyMotionDetector.java
@@ -108,63 +108,71 @@
     public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm,
             DeviceIdleCallback callback, float thresholdAngle) {
         if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated.");
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
-        mWakeLock.setReferenceCounted(false);
-        mHandler = handler;
-        mSensorManager = sm;
-        mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
-        mMeasurementInProgress = false;
-        mState = STATE_INACTIVE;
-        mCallback = callback;
-        mThresholdAngle = thresholdAngle;
-        mRunningStats = new RunningSignalStats();
-        mNumSufficientSamples = (int) Math.ceil(
-                ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS));
-        if (DEBUG) Slog.d(TAG, "mNumSufficientSamples = " + mNumSufficientSamples);
+        synchronized (mLock) {
+            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+            mWakeLock.setReferenceCounted(false);
+            mHandler = handler;
+            mSensorManager = sm;
+            mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+            mMeasurementInProgress = false;
+            mState = STATE_INACTIVE;
+            mCallback = callback;
+            mThresholdAngle = thresholdAngle;
+            mRunningStats = new RunningSignalStats();
+            mNumSufficientSamples = (int) Math.ceil(
+                    ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS));
+            if (DEBUG) Slog.d(TAG, "mNumSufficientSamples = " + mNumSufficientSamples);
+        }
     }
 
     /*
      * Acquire accel data until we determine AnyMotion status.
      */
     public void checkForAnyMotion() {
-      if (DEBUG) Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
+        if (DEBUG) {
+            Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
+        }
         if (mState != STATE_ACTIVE) {
-            mState = STATE_ACTIVE;
-            if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
-            mCurrentGravityVector = null;
-            mPreviousGravityVector = null;
-            startOrientationMeasurement();
+            synchronized (mLock) {
+                mState = STATE_ACTIVE;
+                if (DEBUG) {
+                    Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
+                }
+                mCurrentGravityVector = null;
+                mPreviousGravityVector = null;
+                mWakeLock.acquire();
+                startOrientationMeasurementLocked();
+            }
         }
     }
 
     public void stop() {
         if (mState == STATE_ACTIVE) {
-            mState = STATE_INACTIVE;
-            if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
-            if (mMeasurementInProgress) {
-                mMeasurementInProgress = false;
-                mSensorManager.unregisterListener(mListener);
+            synchronized (mLock) {
+                mState = STATE_INACTIVE;
+                if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
+                if (mMeasurementInProgress) {
+                    mMeasurementInProgress = false;
+                    mSensorManager.unregisterListener(mListener);
+                }
+                mHandler.removeCallbacks(mMeasurementTimeout);
+                mHandler.removeCallbacks(mSensorRestart);
+                mCurrentGravityVector = null;
+                mPreviousGravityVector = null;
+                mWakeLock.release();
             }
-            mHandler.removeCallbacks(mMeasurementTimeout);
-            mHandler.removeCallbacks(mSensorRestart);
-            mWakeLock.release();
-            mCurrentGravityVector = null;
-            mPreviousGravityVector = null;
         }
     }
 
-    private void startOrientationMeasurement() {
-        if (DEBUG) Slog.d(TAG, "startOrientationMeasurement: mMeasurementInProgress=" +
+    private void startOrientationMeasurementLocked() {
+        if (DEBUG) Slog.d(TAG, "startOrientationMeasurementLocked: mMeasurementInProgress=" +
             mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));
-
         if (!mMeasurementInProgress && mAccelSensor != null) {
             if (mSensorManager.registerListener(mListener, mAccelSensor,
                     SAMPLING_INTERVAL_MILLIS * 1000)) {
-                mWakeLock.acquire();
                 mMeasurementInProgress = true;
                 mRunningStats.reset();
             }
-
             Message msg = Message.obtain(mHandler, mMeasurementTimeout);
             msg.setAsynchronous(true);
             mHandler.sendMessageDelayed(msg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);
@@ -178,7 +186,6 @@
         if (mMeasurementInProgress) {
             mSensorManager.unregisterListener(mListener);
             mHandler.removeCallbacks(mMeasurementTimeout);
-            mWakeLock.release();
             long detectionEndTime = SystemClock.elapsedRealtime();
             mMeasurementInProgress = false;
             mPreviousGravityVector = mCurrentGravityVector;
@@ -196,8 +203,10 @@
             status = getStationaryStatus();
             if (DEBUG) Slog.d(TAG, "getStationaryStatus() returned " + status);
             if (status != RESULT_UNKNOWN) {
-                if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " +
-                        status);
+                mWakeLock.release();
+                if (DEBUG) {
+                    Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " + status);
+                }
                 mState = STATE_INACTIVE;
             } else {
                 /*
@@ -275,7 +284,7 @@
         @Override
         public void run() {
             synchronized (mLock) {
-                startOrientationMeasurement();
+                startOrientationMeasurementLocked();
             }
         }
     };
@@ -442,4 +451,4 @@
             return msg;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index fd57af6..0a2153e 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -446,8 +446,12 @@
             int[] ops) {
         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return Collections.emptyList();
+        }
         synchronized (this) {
-            Ops pkgOps = getOpsLocked(uid, packageName, false);
+            Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false);
             if (pkgOps == null) {
                 return null;
             }
@@ -465,7 +469,7 @@
 
     private void pruneOp(Op op, int uid, String packageName) {
         if (op.time == 0 && op.rejectTime == 0) {
-            Ops ops = getOpsLocked(uid, packageName, false);
+            Ops ops = getOpsRawLocked(uid, packageName, false);
             if (ops != null) {
                 ops.remove(op.op);
                 if (ops.size() <= 0) {
@@ -879,8 +883,12 @@
     public int checkOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
         synchronized (this) {
-            if (isOpRestricted(uid, code, packageName)) {
+            if (isOpRestricted(uid, code, resolvedPackageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
             code = AppOpsManager.opToSwitch(code);
@@ -891,7 +899,7 @@
                     return uidMode;
                 }
             }
-            Op op = getOpLocked(code, uid, packageName, false);
+            Op op = getOpLocked(code, uid, resolvedPackageName, false);
             if (op == null) {
                 return AppOpsManager.opToDefaultMode(code);
             }
@@ -971,10 +979,12 @@
                 usageRestrictions.put(usage, r);
             }
         }
+        notifyWatchersOfChange(code);
     }
 
     @Override
     public int checkPackage(int uid, String packageName) {
+        Preconditions.checkNotNull(packageName);
         synchronized (this) {
             if (getOpsRawLocked(uid, packageName, true) != null) {
                 return AppOpsManager.MODE_ALLOWED;
@@ -988,26 +998,39 @@
     public int noteProxyOperation(int code, String proxyPackageName,
             int proxiedUid, String proxiedPackageName) {
         verifyIncomingOp(code);
-        final int proxyMode = noteOperationUnchecked(code, Binder.getCallingUid(),
-                proxyPackageName, -1, null);
+        final int proxyUid = Binder.getCallingUid();
+        String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
+        if (resolveProxyPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        final int proxyMode = noteOperationUnchecked(code, proxyUid,
+                resolveProxyPackageName, -1, null);
         if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
             return proxyMode;
         }
-        return noteOperationUnchecked(code, proxiedUid, proxiedPackageName,
-                Binder.getCallingUid(), proxyPackageName);
+        String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
+        if (resolveProxiedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
+                proxyMode, resolveProxyPackageName);
     }
 
     @Override
     public int noteOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
-        return noteOperationUnchecked(code, uid, packageName, 0, null);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null);
     }
 
     private int noteOperationUnchecked(int code, int uid, String packageName,
             int proxyUid, String proxyPackageName) {
         synchronized (this) {
-            Ops ops = getOpsLocked(uid, packageName, true);
+            Ops ops = getOpsRawLocked(uid, packageName, true);
             if (ops == null) {
                 if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName);
@@ -1024,7 +1047,9 @@
             op.duration = 0;
             final int switchCode = AppOpsManager.opToSwitch(code);
             UidState uidState = ops.uidState;
-            if (uidState.opModes != null) {
+            // If there is a non-default per UID policy (we set UID op mode only if
+            // non-default) it takes over, otherwise use the per package policy.
+            if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
                 final int uidMode = uidState.opModes.get(switchCode);
                 if (uidMode != AppOpsManager.MODE_ALLOWED) {
                     if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
@@ -1033,13 +1058,15 @@
                     op.rejectTime = System.currentTimeMillis();
                     return uidMode;
                 }
-            }
-            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
-            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
-                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
-                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
-                op.rejectTime = System.currentTimeMillis();
-                return switchOp.mode;
+            } else {
+                final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
+                if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
+                    if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
+                            + switchCode + " (" + code + ") uid " + uid + " package "
+                            + packageName);
+                    op.rejectTime = System.currentTimeMillis();
+                    return switchOp.mode;
+                }
             }
             if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
                     + " package " + packageName);
@@ -1055,16 +1082,20 @@
     public int startOperation(IBinder token, int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return  AppOpsManager.MODE_IGNORED;
+        }
         ClientState client = (ClientState)token;
         synchronized (this) {
-            Ops ops = getOpsLocked(uid, packageName, true);
+            Ops ops = getOpsRawLocked(uid, resolvedPackageName, true);
             if (ops == null) {
                 if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
-                        + " package " + packageName);
+                        + " package " + resolvedPackageName);
                 return AppOpsManager.MODE_ERRORED;
             }
             Op op = getOpLocked(ops, code, true);
-            if (isOpRestricted(uid, code, packageName)) {
+            if (isOpRestricted(uid, code, resolvedPackageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
             final int switchCode = AppOpsManager.opToSwitch(code);
@@ -1074,7 +1105,7 @@
                 if (uidMode != AppOpsManager.MODE_ALLOWED) {
                     if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
-                            + packageName);
+                            + resolvedPackageName);
                     op.rejectTime = System.currentTimeMillis();
                     return uidMode;
                 }
@@ -1082,12 +1113,13 @@
             final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
             if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
                 if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
-                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
+                        + switchCode + " (" + code + ") uid " + uid + " package "
+                        + resolvedPackageName);
                 op.rejectTime = System.currentTimeMillis();
                 return switchOp.mode;
             }
             if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
-                    + " package " + packageName);
+                    + " package " + resolvedPackageName);
             if (op.nesting == 0) {
                 op.time = System.currentTimeMillis();
                 op.rejectTime = 0;
@@ -1105,9 +1137,16 @@
     public void finishOperation(IBinder token, int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
-        ClientState client = (ClientState)token;
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return;
+        }
+        if (!(token instanceof ClientState)) {
+            return;
+        }
+        ClientState client = (ClientState) token;
         synchronized (this) {
-            Op op = getOpLocked(code, uid, packageName, true);
+            Op op = getOpLocked(code, uid, resolvedPackageName, true);
             if (op == null) {
                 return;
             }
@@ -1123,6 +1162,9 @@
 
     @Override
     public int permissionToOpCode(String permission) {
+        if (permission == null) {
+            return AppOpsManager.OP_NONE;
+        }
         return AppOpsManager.permissionToOpCode(permission);
     }
 
@@ -1172,15 +1214,6 @@
         return uidState;
     }
 
-    private Ops getOpsLocked(int uid, String packageName, boolean edit) {
-        if (uid == 0) {
-            packageName = "root";
-        } else if (uid == Process.SHELL_UID) {
-            packageName = "com.android.shell";
-        }
-        return getOpsRawLocked(uid, packageName, edit);
-    }
-
     private Ops getOpsRawLocked(int uid, String packageName, boolean edit) {
         UidState uidState = getUidStateLocked(uid, edit);
         if (uidState == null) {
@@ -1266,7 +1299,7 @@
     }
 
     private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
-        Ops ops = getOpsLocked(uid, packageName, edit);
+        Ops ops = getOpsRawLocked(uid, packageName, edit);
         if (ops == null) {
             return null;
         }
@@ -1324,7 +1357,7 @@
                 if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
                     // If we are the system, bypass user restrictions for certain codes
                     synchronized (this) {
-                        Ops ops = getOpsLocked(uid, packageName, true);
+                        Ops ops = getOpsRawLocked(uid, packageName, true);
                         if ((ops != null) && ops.isPrivileged) {
                             return false;
                         }
@@ -1589,7 +1622,7 @@
                         out.startTag(null, "uid");
                         out.attribute(null, "n", Integer.toString(pkg.getUid()));
                         synchronized (this) {
-                            Ops ops = getOpsLocked(pkg.getUid(), pkg.getPackageName(), false);
+                            Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), false);
                             // Should always be present as the list of PackageOps is generated
                             // from Ops.
                             if (ops != null) {
@@ -2181,6 +2214,7 @@
     @Override
     public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
         checkSystemUid("setUserRestrictions");
+        Preconditions.checkNotNull(restrictions);
         Preconditions.checkNotNull(token);
         final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
         for (int i = 0; i < opRestrictions.length; ++i) {
@@ -2251,6 +2285,10 @@
             pruneUserRestrictionsForToken(token, userHandle);
         }
 
+        notifyWatchersOfChange(code);
+    }
+
+    private void notifyWatchersOfChange(int code) {
         final ArrayList<Callback> clonedCallbacks;
         synchronized (this) {
             ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
@@ -2395,6 +2433,17 @@
         }
     }
 
+    private static String resolvePackageName(int uid, String packageName)  {
+        if (uid == 0) {
+            return "root";
+        } else if (uid == Process.SHELL_UID) {
+            return "com.android.shell";
+        } else if (uid == Process.SYSTEM_UID && packageName == null) {
+            return "android";
+        }
+        return packageName;
+    }
+
     private static String[] getPackagesForUid(int uid) {
         String[] packageNames = null;
         try {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 799a763..0a814ab 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -92,6 +92,7 @@
     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_GET_NAME_AND_ADDRESS = 200;
     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;
@@ -599,8 +600,8 @@
             sendEnableMsg(true);
         }
         return true;
-
     }
+
     public boolean enable() {
         if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
             (!checkIfCallerIsForegroundUser())) {
@@ -763,9 +764,8 @@
             sendEnableMsg(mQuietEnableExternal);
         } else if (!isNameAndAddressSet()) {
             if (DBG) Slog.d(TAG, "Getting adapter name and address");
-            enable();
-            waitForOnOff(true, false);
-            disable(true);
+            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
+            mHandler.sendMessage(getMsg);
         }
     }
 
@@ -1076,6 +1076,8 @@
     private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
 
     private class BluetoothHandler extends Handler {
+        boolean mGetNameAddressOnly = false;
+
         public BluetoothHandler(Looper looper) {
             super(looper);
         }
@@ -1084,6 +1086,37 @@
         public void handleMessage(Message msg) {
             if (DBG) Slog.d (TAG, "Message: " + msg.what);
             switch (msg.what) {
+                case MESSAGE_GET_NAME_AND_ADDRESS:
+                    if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
+                    synchronized(mConnection) {
+                        if ((mBluetooth == null) && (!mBinding)) {
+                            if (DBG) Slog.d(TAG, "Binding to service to get name and address");
+                            mGetNameAddressOnly = true;
+                            Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
+                            mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
+                            Intent i = new Intent(IBluetooth.class.getName());
+                            if (!doBind(i, mConnection,
+                                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
+                                UserHandle.CURRENT)) {
+                                mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+                            } else {
+                                mBinding = true;
+                            }
+                        } else if (mBluetooth != null) {
+                            try {
+                                storeNameAndAddress(mBluetooth.getName(),
+                                                    mBluetooth.getAddress());
+                            } catch (RemoteException re) {
+                                Slog.e(TAG, "Unable to grab names", re);
+                            }
+                            if (mGetNameAddressOnly && !mEnable) {
+                                unbindAndFinish();
+                            }
+                            mGetNameAddressOnly = false;
+                        }
+                    }
+                    break;
+
                 case MESSAGE_ENABLE:
                     if (DBG) {
                         Slog.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
@@ -1177,6 +1210,12 @@
                         mBluetoothBinder = service;
                         mBluetooth = IBluetooth.Stub.asInterface(service);
 
+                        if (!isNameAndAddressSet()) {
+                            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
+                            mHandler.sendMessage(getMsg);
+                            if (mGetNameAddressOnly) return;
+                        }
+
                         try {
                             boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver,
                                 Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1);
@@ -1187,15 +1226,6 @@
                             Slog.e(TAG,"Unable to call configHciSnoopLog", e);
                         }
 
-                        if (!isNameAndAddressSet()) {
-                            try {
-                                storeNameAndAddress(mBluetooth.getName(),
-                                                    mBluetooth.getAddress());
-                            } catch (RemoteException re) {
-                                Slog.e(TAG, "Unable to grab names", re);
-                            }
-                        }
-
                         //Register callback object
                         try {
                             mBluetooth.registerCallback(mBluetoothCallback);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 95d3cc3..966deb6 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -371,8 +371,6 @@
     private int mNetTransitionWakeLockTimeout;
     private final PowerManager.WakeLock mPendingIntentWakeLock;
 
-    private InetAddress mDefaultDns;
-
     // used in DBG mode to track inet condition reports
     private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
     private ArrayList mInetLog;
@@ -645,19 +643,6 @@
             }
         }
 
-        // read our default dns server ip
-        String dns = Settings.Global.getString(context.getContentResolver(),
-                Settings.Global.DEFAULT_DNS_SERVER);
-        if (dns == null || dns.length() == 0) {
-            dns = context.getResources().getString(
-                    com.android.internal.R.string.config_default_dns_server);
-        }
-        try {
-            mDefaultDns = NetworkUtils.numericToInetAddress(dns);
-        } catch (IllegalArgumentException e) {
-            loge("Error setting defaultDns using " + dns);
-        }
-
         mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
                 Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
 
@@ -1006,7 +991,16 @@
     @Override
     public Network getActiveNetwork() {
         enforceAccessPermission();
-        final int uid = Binder.getCallingUid();
+        return getActiveNetworkForUidInternal(Binder.getCallingUid());
+    }
+
+    @Override
+    public Network getActiveNetworkForUid(int uid) {
+        enforceConnectivityInternalPermission();
+        return getActiveNetworkForUidInternal(uid);
+    }
+
+    private Network getActiveNetworkForUidInternal(final int uid) {
         final int user = UserHandle.getUserId(uid);
         int vpnNetId = NETID_UNSET;
         synchronized (mVpns) {
@@ -4149,14 +4143,8 @@
 //        }
         updateTcpBufferSizes(networkAgent);
 
-        // TODO: deprecate and remove mDefaultDns when we can do so safely. See http://b/18327075
-        // In L, we used it only when the network had Internet access but provided no DNS servers.
-        // For now, just disable it, and if disabling it doesn't break things, remove it.
-        // final boolean useDefaultDns = networkAgent.networkCapabilities.hasCapability(
-        //        NET_CAPABILITY_INTERNET);
-        final boolean useDefaultDns = false;
-        final boolean flushDns = updateRoutes(newLp, oldLp, netId);
-        updateDnses(newLp, oldLp, netId, flushDns, useDefaultDns);
+        updateRoutes(newLp, oldLp, netId);
+        updateDnses(newLp, oldLp, netId);
 
         updateClat(newLp, oldLp, networkAgent);
         if (isDefaultNetwork(networkAgent)) {
@@ -4259,37 +4247,24 @@
         return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
     }
 
-    private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId,
-                             boolean flush, boolean useDefaultDns) {
-        if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) {
-            Collection<InetAddress> dnses = newLp.getDnsServers();
-            if (dnses.size() == 0 && mDefaultDns != null && useDefaultDns) {
-                dnses = new ArrayList();
-                dnses.add(mDefaultDns);
-                if (DBG) {
-                    loge("no dns provided for netId " + netId + ", so using defaults");
-                }
-            }
-            if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
-            try {
-                mNetd.setDnsServersForNetwork(netId, NetworkUtils.makeStrings(dnses),
-                    newLp.getDomains());
-            } catch (Exception e) {
-                loge("Exception in setDnsServersForNetwork: " + e);
-            }
-            final NetworkAgentInfo defaultNai = getDefaultNetwork();
-            if (defaultNai != null && defaultNai.network.netId == netId) {
-                setDefaultDnsSystemProperties(dnses);
-            }
-            flushVmDnsCache();
-        } else if (flush) {
-            try {
-                mNetd.flushNetworkDnsCache(netId);
-            } catch (Exception e) {
-                loge("Exception in flushNetworkDnsCache: " + e);
-            }
-            flushVmDnsCache();
+    private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
+        if (oldLp != null && newLp.isIdenticalDnses(oldLp)) {
+            return;  // no updating necessary
         }
+
+        Collection<InetAddress> dnses = newLp.getDnsServers();
+        if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
+        try {
+            mNetd.setDnsServersForNetwork(
+                    netId, NetworkUtils.makeStrings(dnses), newLp.getDomains());
+        } catch (Exception e) {
+            loge("Exception in setDnsServersForNetwork: " + e);
+        }
+        final NetworkAgentInfo defaultNai = getDefaultNetwork();
+        if (defaultNai != null && defaultNai.network.netId == netId) {
+            setDefaultDnsSystemProperties(dnses);
+        }
+        flushVmDnsCache();
     }
 
     private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 423f945..ccb4647 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -198,6 +198,7 @@
     private long mNextIdleDelay;
     private long mNextLightIdleDelay;
     private long mNextLightAlarmTime;
+    private long mNextSensingTimeoutAlarmTime;
     private long mCurIdleBudget;
     private long mMaintenanceStartTime;
 
@@ -339,6 +340,18 @@
         }
     };
 
+    private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener
+            = new AlarmManager.OnAlarmListener() {
+        @Override
+        public void onAlarm() {
+            if (mState == STATE_SENSING) {
+                synchronized (DeviceIdleController.this) {
+                    becomeInactiveIfAppropriateLocked();
+                }
+            }
+        }
+    };
+
     private final AlarmManager.OnAlarmListener mDeepAlarmListener
             = new AlarmManager.OnAlarmListener() {
         @Override
@@ -924,6 +937,11 @@
     @Override
     public void onAnyMotionResult(int result) {
         if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
+        if (result != AnyMotionDetector.RESULT_UNKNOWN) {
+            synchronized (this) {
+                cancelSensingTimeoutAlarmLocked();
+            }
+        }
         if (result == AnyMotionDetector.RESULT_MOVED) {
             if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
             synchronized (this) {
@@ -1746,6 +1764,7 @@
         mNextIdleDelay = 0;
         mNextLightIdleDelay = 0;
         cancelAlarmLocked();
+        cancelSensingTimeoutAlarmLocked();
         cancelLocatingLocked();
         stopMonitoringMotionLocked();
         mAnyMotionDetector.stop();
@@ -1866,15 +1885,16 @@
                 mState = STATE_SENSING;
                 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
                 EventLogTags.writeDeviceIdle(mState, reason);
-                scheduleAlarmLocked(mConstants.SENSING_TIMEOUT, false);
+                scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);
                 cancelLocatingLocked();
-                mAnyMotionDetector.checkForAnyMotion();
                 mNotMoving = false;
                 mLocated = false;
                 mLastGenericLocation = null;
                 mLastGpsLocation = null;
+                mAnyMotionDetector.checkForAnyMotion();
                 break;
             case STATE_SENSING:
+                cancelSensingTimeoutAlarmLocked();
                 mState = STATE_LOCATING;
                 if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
                 EventLogTags.writeDeviceIdle(mState, reason);
@@ -2161,6 +2181,13 @@
         }
     }
 
+    void cancelSensingTimeoutAlarmLocked() {
+        if (mNextSensingTimeoutAlarmTime != 0) {
+            mNextSensingTimeoutAlarmTime = 0;
+            mAlarmManager.cancel(mSensingTimeoutAlarmListener);
+        }
+    }
+
     void scheduleAlarmLocked(long delay, boolean idleUntil) {
         if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
         if (mMotionSensor == null) {
@@ -2194,6 +2221,13 @@
                 mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
     }
 
+    void scheduleSensingTimeoutAlarmLocked(long delay) {
+        if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
+        mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
+        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
+            "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
+    }
+
     private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
             ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
         outAppIds.clear();
diff --git a/services/core/java/com/android/server/DisplayThread.java b/services/core/java/com/android/server/DisplayThread.java
index aa0a805..9ef0259 100644
--- a/services/core/java/com/android/server/DisplayThread.java
+++ b/services/core/java/com/android/server/DisplayThread.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.os.Handler;
+import android.os.Trace;
 
 /**
  * Shared singleton foreground thread for the system.  This is a thread for
@@ -36,6 +37,7 @@
         if (sInstance == null) {
             sInstance = new DisplayThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/services/core/java/com/android/server/FgThread.java b/services/core/java/com/android/server/FgThread.java
index 03765db..5f85cba 100644
--- a/services/core/java/com/android/server/FgThread.java
+++ b/services/core/java/com/android/server/FgThread.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.os.Handler;
+import android.os.Trace;
 
 /**
  * Shared singleton foreground thread for the system.  This is a thread for regular
@@ -38,6 +39,7 @@
         if (sInstance == null) {
             sInstance = new FgThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index d6575e8..aa98648 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -34,6 +34,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.util.MutableBoolean;
 import android.util.Slog;
 import android.view.KeyEvent;
 
@@ -251,7 +252,8 @@
         return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources);
     }
 
-    public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) {
+    public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
+            MutableBoolean outLaunched) {
         boolean launched = false;
         boolean intercept = false;
         long doubleTapInterval;
@@ -276,6 +278,7 @@
             }
         }
         MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval);
+        outLaunched.value = launched;
         return intercept && launched;
     }
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index b8cbf16..ac7872a 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -15,6 +15,8 @@
 
 package com.android.server;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
@@ -37,6 +39,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
@@ -125,6 +128,7 @@
 import android.widget.RadioButton;
 import android.widget.Switch;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -132,6 +136,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -177,6 +182,12 @@
     private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
     private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
 
+    @Retention(SOURCE)
+    @IntDef({HardKeyboardBehavior.WIRELESS_AFFORDANCE, HardKeyboardBehavior.WIRED_AFFORDANCE})
+    private @interface  HardKeyboardBehavior {
+        int WIRELESS_AFFORDANCE = 0;
+        int WIRED_AFFORDANCE = 1;
+    }
 
     final Context mContext;
     final Resources mRes;
@@ -452,6 +463,7 @@
     private AlertDialog.Builder mDialogBuilder;
     private AlertDialog mSwitchingDialog;
     private View mSwitchingDialogTitleView;
+    private Toast mSubtypeSwitchedByShortCutToast;
     private InputMethodInfo[] mIms;
     private int[] mSubtypeIds;
     private LocaleList mLastSystemLocales;
@@ -460,6 +472,8 @@
     private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
     private final IPackageManager mIPackageManager;
     private final String mSlotIme;
+    @HardKeyboardBehavior
+    private final int mHardKeyboardBehavior;
 
     class SettingsObserver extends ContentObserver {
         int mUserId;
@@ -852,6 +866,8 @@
         mHasFeature = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_INPUT_METHODS);
         mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime);
+        mHardKeyboardBehavior = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_externalHardKeyboardBehavior);
 
         Bundle extras = new Bundle();
         extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
@@ -1710,11 +1726,13 @@
         if (isScreenLocked()) return false;
         if ((visibility & InputMethodService.IME_ACTIVE) == 0) return false;
         if (mWindowManagerInternal.isHardKeyboardAvailable()) {
-            // When physical keyboard is attached, we show the ime switcher (or notification if
-            // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently
-            // exists in the IME switcher dialog.  Might be OK to remove this condition once
-            // SHOW_IME_WITH_HARD_KEYBOARD settings finds a good place to live.
-            return true;
+            if (mHardKeyboardBehavior == HardKeyboardBehavior.WIRELESS_AFFORDANCE) {
+                // When physical keyboard is attached, we show the ime switcher (or notification if
+                // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently
+                // exists in the IME switcher dialog.  Might be OK to remove this condition once
+                // SHOW_IME_WITH_HARD_KEYBOARD settings finds a good place to live.
+                return true;
+            }
         } else if ((visibility & InputMethodService.IME_VISIBLE) == 0) {
             return false;
         }
@@ -2952,6 +2970,27 @@
                 return;
             }
             setInputMethodLocked(nextSubtype.mImi.getId(), nextSubtype.mSubtypeId);
+            if (mSubtypeSwitchedByShortCutToast != null) {
+                mSubtypeSwitchedByShortCutToast.cancel();
+                mSubtypeSwitchedByShortCutToast = null;
+            }
+            if ((mImeWindowVis & InputMethodService.IME_VISIBLE) != 0) {
+                // IME window is shown.  The user should be able to visually understand that the
+                // subtype is changed in most of cases.  To avoid UI overlap, we do not show a toast
+                // in this case.
+                return;
+            }
+            final InputMethodInfo newInputMethodInfo = mMethodMap.get(mCurMethodId);
+            if (newInputMethodInfo == null) {
+                return;
+            }
+            final CharSequence toastText = InputMethodUtils.getImeAndSubtypeDisplayName(mContext,
+                    newInputMethodInfo, mCurrentSubtype);
+            if (!TextUtils.isEmpty(toastText)) {
+                mSubtypeSwitchedByShortCutToast = Toast.makeText(mContext, toastText.toString(),
+                        Toast.LENGTH_SHORT);
+                mSubtypeSwitchedByShortCutToast.show();
+            }
         }
     }
 
@@ -3823,6 +3862,22 @@
         }
     }
 
+    private static String imeWindowStatusToString(final int imeWindowVis) {
+        final StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        if ((imeWindowVis & InputMethodService.IME_ACTIVE) != 0) {
+            sb.append("Active");
+            first = false;
+        }
+        if ((imeWindowVis & InputMethodService.IME_VISIBLE) != 0) {
+            if (!first) {
+                sb.append("|");
+            }
+            sb.append("Visible");
+        }
+        return sb.toString();
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -3870,6 +3925,7 @@
             method = mCurMethod;
             p.println("  mCurMethod=" + mCurMethod);
             p.println("  mEnabledSession=" + mEnabledSession);
+            p.println("  mImeWindowVis=" + imeWindowStatusToString(mImeWindowVis));
             p.println("  mShowRequested=" + mShowRequested
                     + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
                     + " mShowForced=" + mShowForced
diff --git a/services/core/java/com/android/server/IoThread.java b/services/core/java/com/android/server/IoThread.java
index 0f29857..ad4c194 100644
--- a/services/core/java/com/android/server/IoThread.java
+++ b/services/core/java/com/android/server/IoThread.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.os.Handler;
+import android.os.Trace;
 
 /**
  * Shared singleton I/O thread for the system.  This is a thread for non-background
@@ -35,6 +36,7 @@
         if (sInstance == null) {
             sInstance = new IoThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index ed16af51..4ac75ca 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -56,6 +56,9 @@
 import android.provider.Settings.Secure;
 import android.provider.Settings.SettingNotFoundException;
 import android.security.KeyStore;
+import android.security.keystore.AndroidKeyStoreProvider;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
 import android.service.gatekeeper.GateKeeperResponse;
 import android.service.gatekeeper.IGateKeeperService;
 import android.text.TextUtils;
@@ -68,15 +71,33 @@
 import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.server.LockSettingsStorage.CredentialHash;
 
+import libcore.util.HexEncoding;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
 /**
  * Keeps the lock pattern/password data and related settings for each user.
  * Used by LockPatternUtils. Needs to be a service because Settings app also needs
@@ -90,6 +111,12 @@
     private static final int FBE_ENCRYPTED_NOTIFICATION = 0;
     private static final boolean DEBUG = false;
 
+    private static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
+    private static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
+    private static final int PROFILE_KEY_IV_SIZE = 12;
+    private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
+    private final Object mSeparateChallengeLock = new Object();
+
     private final Context mContext;
     private final LockSettingsStorage mStorage;
     private final LockSettingsStrongAuth mStrongAuth;
@@ -125,6 +152,7 @@
 
         @Override
         public void onStart() {
+            AndroidKeyStoreProvider.install();
             mLockSettingsService = new LockSettingsService(getContext());
             publishBinderService("lock_settings", mLockSettingsService);
         }
@@ -149,6 +177,46 @@
         }
     }
 
+    /**
+     * Tie managed profile to primary profile if it is in unified mode and not tied before.
+     *
+     * @param managedUserId Managed profile user Id
+     * @param managedUserPassword Managed profile original password (when it has separated lock).
+     *            NULL when it does not have a separated lock before.
+     */
+    public void tieManagedProfileLockIfNecessary(int managedUserId, String managedUserPassword) {
+        if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
+        // Only for managed profile
+        if (!UserManager.get(mContext).getUserInfo(managedUserId).isManagedProfile()) {
+            return;
+        }
+        // Do not tie managed profile when work challenge is enabled
+        if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
+            return;
+        }
+        // Do not tie managed profile to parent when it's done already
+        if (mStorage.hasChildProfileLock(managedUserId)) {
+            return;
+        }
+        // Do not tie it to parent when parent does not have a screen lock
+        final int parentId = mUserManager.getProfileParent(managedUserId).id;
+        if (!mStorage.hasPassword(parentId) && !mStorage.hasPattern(parentId)) {
+            if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock");
+            return;
+        }
+        if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
+        byte[] randomLockSeed = new byte[] {};
+        try {
+            randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
+            String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed));
+            setLockPasswordInternal(newPassword, managedUserPassword, managedUserId);
+            tieProfileLockToParent(managedUserId, newPassword);
+        } catch (NoSuchAlgorithmException | RemoteException e) {
+            Slog.e(TAG, "Fail to tie managed profile", e);
+            // Nothing client can do to fix this issue, so we do not throw exception out
+        }
+    }
+
     public LockSettingsService(Context context) {
         mContext = context;
         mStrongAuth = new LockSettingsStrongAuth(context);
@@ -254,7 +322,7 @@
                         com.android.internal.R.color.system_notification_accent_color))
                 .setContentTitle(title)
                 .setContentText(message)
-                .setContentInfo(detail)
+                .setSubText(detail)
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
                 .setContentIntent(intent)
                 .build();
@@ -271,6 +339,7 @@
     }
 
     public void onUnlockUser(int userId) {
+        tieManagedProfileLockIfNecessary(userId, null);
         hideEncryptionNotification(new UserHandle(userId));
 
         // Now we have unlocked the parent user we should show notifications
@@ -294,8 +363,7 @@
                 // Notify keystore that a new user was added.
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 final KeyStore ks = KeyStore.getInstance();
-                final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
-                final UserInfo parentInfo = um.getProfileParent(userHandle);
+                final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
                 final int parentHandle = parentInfo != null ? parentInfo.id : -1;
                 ks.onUserAdded(userHandle, parentHandle);
             } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
@@ -343,9 +411,8 @@
 
             // These Settings changed after multi-user was enabled, hence need to be moved per user.
             if (getString("migrated_user_specific", null, 0) == null) {
-                final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
                 final ContentResolver cr = mContext.getContentResolver();
-                List<UserInfo> users = um.getUsers();
+                List<UserInfo> users = mUserManager.getUsers();
                 for (int user = 0; user < users.size(); user++) {
                     // Migrate owner info
                     final int userId = users.get(user).id;
@@ -380,8 +447,7 @@
 
             // Migrates biometric weak such that the fallback mechanism becomes the primary.
             if (getString("migrated_biometric_weak", null, 0) == null) {
-                final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
-                List<UserInfo> users = um.getUsers();
+                List<UserInfo> users = mUserManager.getUsers();
                 for (int i = 0; i < users.size(); i++) {
                     int userId = users.get(i).id;
                     long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
@@ -407,9 +473,7 @@
             // user was present on the system, so if we're upgrading to M and there is more than one
             // user we disable the flag to remain consistent.
             if (getString("migrated_lockscreen_disabled", null, 0) == null) {
-                final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
-
-                final List<UserInfo> users = um.getUsers();
+                final List<UserInfo> users = mUserManager.getUsers();
                 final int userCount = users.size();
                 int switchableUsers = 0;
                 for (int i = 0; i < userCount; i++) {
@@ -469,6 +533,27 @@
     }
 
     @Override
+    public boolean getSeparateProfileChallengeEnabled(int userId) throws RemoteException {
+        synchronized (mSeparateChallengeLock) {
+            return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
+        }
+    }
+
+    @Override
+    public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
+            String managedUserPassword) throws RemoteException {
+        synchronized (mSeparateChallengeLock) {
+            setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
+            if (enabled) {
+                mStorage.removeChildProfileLock(userId);
+                removeKeystoreProfileKey(userId);
+            } else {
+                tieManagedProfileLockIfNecessary(userId, managedUserPassword);
+            }
+        }
+    }
+
+    @Override
     public void setBoolean(String key, boolean value, int userId) throws RemoteException {
         checkWritePermission(userId);
         setStringUnchecked(key, userId, value ? "1" : "0");
@@ -536,61 +621,65 @@
     @Override
     public boolean havePassword(int userId) throws RemoteException {
         // Do we need a permissions check here?
-
         return mStorage.hasPassword(userId);
     }
 
     @Override
     public boolean havePattern(int userId) throws RemoteException {
         // Do we need a permissions check here?
-
         return mStorage.hasPattern(userId);
     }
 
     private void setKeystorePassword(String password, int userHandle) {
-        final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
         final KeyStore ks = KeyStore.getInstance();
-
-        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);
-                }
-            }
-        }
+        ks.onUserPasswordChanged(userHandle, password);
     }
 
     private void unlockKeystore(String password, int userHandle) {
-        final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
+        if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
         final KeyStore ks = KeyStore.getInstance();
+        ks.unlock(userHandle, password);
+    }
 
-        if (um.getUserInfo(userHandle).isManagedProfile()) {
-            if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
-                ks.unlock(userHandle, password);
+    private String getDecryptedPasswordForTiedProfile(int userId)
+            throws KeyStoreException, UnrecoverableKeyException,
+            NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
+            InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
+            CertificateException, IOException {
+        if (DEBUG) Slog.v(TAG, "Unlock keystore for child profile");
+        byte[] storedData = mStorage.readChildProfileLock(userId);
+        if (storedData == null) {
+            throw new FileNotFoundException("Child profile lock file not found");
+        }
+        byte[] iv = Arrays.copyOfRange(storedData, 0, PROFILE_KEY_IV_SIZE);
+        byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE,
+                storedData.length);
+        byte[] decryptionResult;
+        java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+        keyStore.load(null);
+        SecretKey decryptionKey = (SecretKey) keyStore.getKey(
+                PROFILE_KEY_NAME_DECRYPT + userId, null);
+
+        Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+                + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
+
+        cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
+        decryptionResult = cipher.doFinal(encryptedPassword);
+        return new String(decryptionResult, StandardCharsets.UTF_8);
+    }
+
+    private void unlockChildProfile(int profileHandle) throws RemoteException {
+        try {
+            doVerifyPassword(getDecryptedPasswordForTiedProfile(profileHandle), false,
+                    0 /* no challenge */, profileHandle);
+        } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+                | NoSuchAlgorithmException | NoSuchPaddingException
+                | InvalidAlgorithmParameterException | IllegalBlockSizeException
+                | BadPaddingException | CertificateException | IOException e) {
+            if (e instanceof FileNotFoundException) {
+                Slog.i(TAG, "Child profile key not found");
             } 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);
-                }
+                Slog.e(TAG, "Failed to decrypt child profile key", e);
             }
         }
     }
@@ -627,6 +716,21 @@
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
         }
+        try {
+            if (!mUserManager.getUserInfo(userId).isManagedProfile()) {
+                final List<UserInfo> profiles = mUserManager.getProfiles(userId);
+                for (UserInfo pi : profiles) {
+                    // Unlock managed profile with unified lock
+                    if (pi.isManagedProfile()
+                            && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
+                            && mStorage.hasChildProfileLock(pi.id)) {
+                        unlockChildProfile(pi.id);
+                    }
+                }
+            }
+        } catch (RemoteException e) {
+            Log.d(TAG, "Failed to unlock child profile", e);
+        }
     }
 
     private byte[] getCurrentHandle(int userId) {
@@ -661,10 +765,57 @@
         return currentHandle;
     }
 
+    private void onUserLockChanged(int userId) throws RemoteException {
+        if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+            return;
+        }
+        final boolean isSecure = mStorage.hasPassword(userId) || mStorage.hasPattern(userId);
+        final List<UserInfo> profiles = mUserManager.getProfiles(userId);
+        final int size = profiles.size();
+        for (int i = 0; i < size; i++) {
+            final UserInfo profile = profiles.get(i);
+            if (profile.isManagedProfile()) {
+                final int managedUserId = profile.id;
+                if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
+                    continue;
+                }
+                if (isSecure) {
+                    tieManagedProfileLockIfNecessary(managedUserId, null);
+                } else {
+                    getGateKeeperService().clearSecureUserId(managedUserId);
+                    mStorage.writePatternHash(null, managedUserId);
+                    setKeystorePassword(null, managedUserId);
+                    clearUserKeyProtection(managedUserId);
+                    mStorage.removeChildProfileLock(managedUserId);
+                    removeKeystoreProfileKey(managedUserId);
+                }
+            }
+        }
+    }
 
+    private boolean isManagedProfileWithUnifiedLock(int userId) {
+        return mUserManager.getUserInfo(userId).isManagedProfile()
+                && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
+    }
+
+    private boolean isManagedProfileWithSeparatedLock(int userId) {
+        return mUserManager.getUserInfo(userId).isManagedProfile()
+                && mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
+    }
+
+    // This method should be called by LockPatternUtil only, all internal methods in this class
+    // should call setLockPatternInternal.
     @Override
     public void setLockPattern(String pattern, String savedCredential, int userId)
             throws RemoteException {
+        synchronized (mSeparateChallengeLock) {
+            setLockPatternInternal(pattern, savedCredential, userId);
+            setSeparateProfileChallengeEnabled(userId, true, null);
+        }
+    }
+
+    public void setLockPatternInternal(String pattern, String savedCredential, int userId)
+            throws RemoteException {
         byte[] currentHandle = getCurrentHandle(userId);
 
         if (pattern == null) {
@@ -672,55 +823,157 @@
             mStorage.writePatternHash(null, userId);
             setKeystorePassword(null, userId);
             clearUserKeyProtection(userId);
+            onUserLockChanged(userId);
             return;
         }
 
-        if (currentHandle == null) {
-            if (savedCredential != null) {
-                Slog.w(TAG, "Saved credential provided, but none stored");
+        if (isManagedProfileWithUnifiedLock(userId)) {
+            // get credential from keystore when managed profile has unified lock
+            try {
+                savedCredential = getDecryptedPasswordForTiedProfile(userId);
+            } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+                    | NoSuchAlgorithmException | NoSuchPaddingException
+                    | InvalidAlgorithmParameterException | IllegalBlockSizeException
+                    | BadPaddingException | CertificateException | IOException e) {
+                if (e instanceof FileNotFoundException) {
+                    Slog.i(TAG, "Child profile key not found");
+                } else {
+                    Slog.e(TAG, "Failed to decrypt child profile key", e);
+                }
             }
-            savedCredential = null;
+        } else {
+            if (currentHandle == null) {
+                if (savedCredential != null) {
+                    Slog.w(TAG, "Saved credential provided, but none stored");
+                }
+                savedCredential = null;
+            }
         }
 
         byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, pattern, userId);
         if (enrolledHandle != null) {
             mStorage.writePatternHash(enrolledHandle, userId);
             setUserKeyProtection(userId, pattern, verifyPattern(pattern, 0, userId));
+            onUserLockChanged(userId);
         } else {
             throw new RemoteException("Failed to enroll pattern");
         }
     }
 
-
+    // This method should be called by LockPatternUtil only, all internal methods in this class
+    // should call setLockPasswordInternal.
     @Override
     public void setLockPassword(String password, String savedCredential, int userId)
             throws RemoteException {
-        byte[] currentHandle = getCurrentHandle(userId);
+        synchronized (mSeparateChallengeLock) {
+            setLockPasswordInternal(password, savedCredential, userId);
+            setSeparateProfileChallengeEnabled(userId, true, null);
+        }
+    }
 
+    public void setLockPasswordInternal(String password, String savedCredential, int userId)
+            throws RemoteException {
+        byte[] currentHandle = getCurrentHandle(userId);
         if (password == null) {
             getGateKeeperService().clearSecureUserId(userId);
             mStorage.writePasswordHash(null, userId);
             setKeystorePassword(null, userId);
             clearUserKeyProtection(userId);
+            onUserLockChanged(userId);
             return;
         }
 
-        if (currentHandle == null) {
-            if (savedCredential != null) {
-                Slog.w(TAG, "Saved credential provided, but none stored");
+        if (isManagedProfileWithUnifiedLock(userId)) {
+            // get credential from keystore when managed profile has unified lock
+            try {
+                savedCredential = getDecryptedPasswordForTiedProfile(userId);
+            } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+                    | NoSuchAlgorithmException | NoSuchPaddingException
+                    | InvalidAlgorithmParameterException | IllegalBlockSizeException
+                    | BadPaddingException | CertificateException | IOException e) {
+                if (e instanceof FileNotFoundException) {
+                    Slog.i(TAG, "Child profile key not found");
+                } else {
+                    Slog.e(TAG, "Failed to decrypt child profile key", e);
+                }
             }
-            savedCredential = null;
+        } else {
+            if (currentHandle == null) {
+                if (savedCredential != null) {
+                    Slog.w(TAG, "Saved credential provided, but none stored");
+                }
+                savedCredential = null;
+            }
         }
 
         byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, password, userId);
         if (enrolledHandle != null) {
             mStorage.writePasswordHash(enrolledHandle, userId);
             setUserKeyProtection(userId, password, verifyPassword(password, 0, userId));
+            onUserLockChanged(userId);
         } else {
             throw new RemoteException("Failed to enroll password");
         }
     }
 
+    private void tieProfileLockToParent(int userId, String password) {
+        if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
+        byte[] randomLockSeed = password.getBytes(StandardCharsets.UTF_8);
+        byte[] encryptionResult;
+        byte[] iv;
+        try {
+            KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
+            keyGenerator.init(new SecureRandom());
+            SecretKey secretKey = keyGenerator.generateKey();
+
+            java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+            keyStore.load(null);
+            keyStore.setEntry(
+                    PROFILE_KEY_NAME_ENCRYPT + userId,
+                    new java.security.KeyStore.SecretKeyEntry(secretKey),
+                    new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
+                            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                            .build());
+            keyStore.setEntry(
+                    PROFILE_KEY_NAME_DECRYPT + userId,
+                    new java.security.KeyStore.SecretKeyEntry(secretKey),
+                    new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
+                            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                            .setUserAuthenticationRequired(true)
+                            .setUserAuthenticationValidityDurationSeconds(30)
+                            .build());
+
+            // Key imported, obtain a reference to it.
+            SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
+                    PROFILE_KEY_NAME_ENCRYPT + userId, null);
+            // The original key can now be discarded.
+
+            Cipher cipher = Cipher.getInstance(
+                    KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
+                            + KeyProperties.ENCRYPTION_PADDING_NONE);
+            cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
+            encryptionResult = cipher.doFinal(randomLockSeed);
+            iv = cipher.getIV();
+        } catch (CertificateException | UnrecoverableKeyException
+                | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
+                | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
+            throw new RuntimeException("Failed to encrypt key", e);
+        }
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        try {
+            if (iv.length != PROFILE_KEY_IV_SIZE) {
+                throw new RuntimeException("Invalid iv length: " + iv.length);
+            }
+            outputStream.write(iv);
+            outputStream.write(encryptionResult);
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to concatenate byte arrays", e);
+        }
+        mStorage.writeChildProfileLock(userId, outputStream.toByteArray());
+    }
+
     private byte[] enrollCredential(byte[] enrolledHandle,
             String enrolledCredential, String toEnroll, int userId)
             throws RemoteException {
@@ -820,7 +1073,7 @@
                    @Override
                    public void setCredential(String pattern, String oldPattern, int userId)
                            throws RemoteException {
-                       setLockPattern(pattern, oldPattern, userId);
+                        setLockPatternInternal(pattern, oldPattern, userId);
                    }
 
                    @Override
@@ -838,7 +1091,7 @@
 
        if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK
                && shouldReEnrollBaseZero) {
-           setLockPattern(pattern, patternToVerify, userId);
+            setLockPatternInternal(pattern, patternToVerify, userId);
        }
 
        return response;
@@ -857,6 +1110,37 @@
         return doVerifyPassword(password, true, challenge, userId);
     }
 
+    @Override
+    public VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern,
+            long challenge, int userId) throws RemoteException {
+        checkPasswordReadPermission(userId);
+        if (!isManagedProfileWithUnifiedLock(userId)) {
+            throw new RemoteException("User id must be managed profile with unified lock");
+        }
+        final int parentProfileId = mUserManager.getProfileParent(userId).id;
+        // Unlock parent by using parent's challenge
+        final VerifyCredentialResponse parentResponse = isPattern
+                ? doVerifyPattern(password, true, challenge, parentProfileId)
+                : doVerifyPassword(password, true, challenge, parentProfileId);
+        if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
+            // Failed, just return parent's response
+            return parentResponse;
+        }
+
+        try {
+            // Unlock work profile, and work profile with unified lock must use password only
+            return doVerifyPassword(getDecryptedPasswordForTiedProfile(userId), true,
+                    challenge,
+                    userId);
+        } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+                | NoSuchAlgorithmException | NoSuchPaddingException
+                | InvalidAlgorithmParameterException | IllegalBlockSizeException
+                | BadPaddingException | CertificateException | IOException e) {
+            Slog.e(TAG, "Failed to decrypt child profile key", e);
+            throw new RemoteException("Unable to get tied profile token");
+        }
+    }
+
     private VerifyCredentialResponse doVerifyPassword(String password, boolean hasChallenge,
             long challenge, int userId) throws RemoteException {
        checkPasswordReadPermission(userId);
@@ -866,7 +1150,7 @@
                    @Override
                    public void setCredential(String password, String oldPassword, int userId)
                            throws RemoteException {
-                       setLockPassword(password, oldPassword, userId);
+                        setLockPasswordInternal(password, oldPassword, userId);
                    }
 
                    @Override
@@ -947,8 +1231,7 @@
                 " with token length " + response.getPayload().length);
             unlockUser(userId, response.getPayload(), secretFromCredential(credential));
 
-            UserInfo info = UserManager.get(mContext).getUserInfo(userId);
-            if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+            if (isManagedProfileWithSeparatedLock(userId)) {
                 TrustManager trustManager =
                         (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
                 trustManager.setDeviceLockedForUser(userId, false);
@@ -1027,6 +1310,23 @@
         } catch (RemoteException ex) {
             Slog.w(TAG, "unable to clear GK secure user id");
         }
+        if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+            removeKeystoreProfileKey(userId);
+        }
+    }
+
+    private void removeKeystoreProfileKey(int targetUserId) {
+        if (DEBUG) Slog.v(TAG, "Remove keystore profile key for user: " + targetUserId);
+        try {
+            java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+            keyStore.load(null);
+            keyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + targetUserId);
+            keyStore.deleteEntry(PROFILE_KEY_NAME_DECRYPT + targetUserId);
+        } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
+                | IOException e) {
+            // We have tried our best to remove all keys
+            Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index 816c791..d136f1a 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -17,7 +17,6 @@
 package com.android.server;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.widget.LockPatternUtils;
 
 import android.content.ContentValues;
 import android.content.Context;
@@ -30,6 +29,7 @@
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
+import android.util.SparseArray;
 
 import java.io.File;
 import java.io.IOException;
@@ -44,6 +44,7 @@
 
     private static final String TAG = "LockSettingsStorage";
     private static final String TABLE = "locksettings";
+    private static final boolean DEBUG = false;
 
     private static final String COLUMN_KEY = "name";
     private static final String COLUMN_USERID = "user";
@@ -62,6 +63,7 @@
     private static final String LEGACY_LOCK_PATTERN_FILE = "gesture.key";
     private static final String LOCK_PASSWORD_FILE = "gatekeeper.password.key";
     private static final String LEGACY_LOCK_PASSWORD_FILE = "password.key";
+    private static final String CHILD_PROFILE_LOCK_FILE = "gatekeeper.profile.key";
 
     private static final Object DEFAULT = new Object();
 
@@ -70,8 +72,7 @@
     private final Cache mCache = new Cache();
     private final Object mFileWriteLock = new Object();
 
-    private int mStoredCredentialType;
-    private LockPatternUtils mLockPatternUtils;
+    private SparseArray<Integer> mStoredCredentialType;
 
     class CredentialHash {
         static final int TYPE_NONE = -1;
@@ -101,7 +102,7 @@
     public LockSettingsStorage(Context context, Callback callback) {
         mContext = context;
         mOpenHelper = new DatabaseHelper(context, callback);
-        mLockPatternUtils = new LockPatternUtils(context);
+        mStoredCredentialType = new SparseArray<Integer>();
     }
 
     public void writeKeyValue(String key, String value, int userId) {
@@ -182,32 +183,34 @@
     }
 
     public int getStoredCredentialType(int userId) {
-        if (mStoredCredentialType != 0) {
-            return mStoredCredentialType;
+        final Integer cachedStoredCredentialType = mStoredCredentialType.get(userId);
+        if (cachedStoredCredentialType != null) {
+            return cachedStoredCredentialType.intValue();
         }
 
+        int storedCredentialType;
         CredentialHash pattern = readPatternHash(userId);
         if (pattern == null) {
             if (readPasswordHash(userId) != null) {
-                mStoredCredentialType = CredentialHash.TYPE_PASSWORD;
+                storedCredentialType = CredentialHash.TYPE_PASSWORD;
             } else {
-                mStoredCredentialType = CredentialHash.TYPE_NONE;
+                storedCredentialType = CredentialHash.TYPE_NONE;
             }
         } else {
             CredentialHash password = readPasswordHash(userId);
             if (password != null) {
                 // Both will never be GateKeeper
                 if (password.version == CredentialHash.VERSION_GATEKEEPER) {
-                    mStoredCredentialType = CredentialHash.TYPE_PASSWORD;
+                    storedCredentialType = CredentialHash.TYPE_PASSWORD;
                 } else {
-                    mStoredCredentialType = CredentialHash.TYPE_PATTERN;
+                    storedCredentialType = CredentialHash.TYPE_PATTERN;
                 }
             } else {
-                mStoredCredentialType = CredentialHash.TYPE_PATTERN;
+                storedCredentialType = CredentialHash.TYPE_PATTERN;
             }
         }
-
-        return mStoredCredentialType;
+        mStoredCredentialType.put(userId, storedCredentialType);
+        return storedCredentialType;
     }
 
 
@@ -244,6 +247,27 @@
         return null;
     }
 
+    public void removeChildProfileLock(int userId) {
+        if (DEBUG)
+            Slog.e(TAG, "Remove child profile lock for user: " + userId);
+        try {
+            deleteFile(getChildProfileLockFile(userId));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void writeChildProfileLock(int userId, byte[] lock) {
+        writeFile(getChildProfileLockFile(userId), lock);
+    }
+
+    public byte[] readChildProfileLock(int userId) {
+        return readFile(getChildProfileLockFile(userId));
+    }
+
+    public boolean hasChildProfileLock(int userId) {
+        return hasFile(getChildProfileLockFile(userId));
+    }
 
     public boolean hasPassword(int userId) {
         return hasFile(getLockPasswordFilename(userId)) ||
@@ -321,16 +345,19 @@
     }
 
     private void deleteFile(String name) {
-        File f = new File(name);
-        if (f != null) {
-            f.delete();
+        if (DEBUG) Slog.e(TAG, "Delete file " + name);
+        synchronized (mFileWriteLock) {
+            File file = new File(name);
+            if (file.exists()) {
+                file.delete();
+                mCache.putFile(name, null);
+            }
         }
     }
 
     public void writePatternHash(byte[] hash, int userId) {
-        mStoredCredentialType = hash == null
-            ? CredentialHash.TYPE_NONE
-            : CredentialHash.TYPE_PATTERN;
+        mStoredCredentialType.put(userId, hash == null ? CredentialHash.TYPE_NONE
+                : CredentialHash.TYPE_PATTERN);
         writeFile(getLockPatternFilename(userId), hash);
         clearPasswordHash(userId);
     }
@@ -340,9 +367,8 @@
     }
 
     public void writePasswordHash(byte[] hash, int userId) {
-        mStoredCredentialType = hash == null
-            ? CredentialHash.TYPE_NONE
-            : CredentialHash.TYPE_PASSWORD;
+        mStoredCredentialType.put(userId, hash == null ? CredentialHash.TYPE_NONE
+                : CredentialHash.TYPE_PASSWORD);
         writeFile(getLockPasswordFilename(userId), hash);
         clearPatternHash(userId);
     }
@@ -375,8 +401,11 @@
         return getLockCredentialFilePathForUser(userId, BASE_ZERO_LOCK_PATTERN_FILE);
     }
 
+    private String getChildProfileLockFile(int userId) {
+        return getLockCredentialFilePathForUser(userId, CHILD_PROFILE_LOCK_FILE);
+    }
+
     private String getLockCredentialFilePathForUser(int userId, String basename) {
-        userId = getUserParentOrSelfId(userId);
         String dataSystemDirectory =
                 android.os.Environment.getDataDirectory().getAbsolutePath() +
                         SYSTEM_DIRECTORY;
@@ -388,23 +417,6 @@
         }
     }
 
-    private int getUserParentOrSelfId(int userId) {
-        // Device supports per user encryption, so lock is applied to the given user.
-        if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
-            return userId;
-        }
-        // Device uses Block Based Encryption, and the parent user's lock is used for the whole
-        // device.
-        if (userId != 0) {
-            final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
-            final UserInfo pi = um.getProfileParent(userId);
-            if (pi != null) {
-                return pi.id;
-            }
-        }
-        return userId;
-    }
-
     public void removeUser(int userId) {
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
 
@@ -427,6 +439,9 @@
                     mCache.putFile(name, null);
                 }
             }
+        } else {
+            // Manged profile
+            removeChildProfileLock(userId);
         }
 
         try {
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 440d8b7..fd9a94d 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1984,6 +1984,28 @@
                 mHandler.obtainMessage(H_RESET).sendToTarget();
             }
         }
+
+        if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
+                | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
+            final String value;
+            if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
+                value = "force_on";
+            } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
+                value = "force_off";
+            } else {
+                value = "";
+            }
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
+
+                // Reset storage to kick new setting into place
+                mHandler.obtainMessage(H_RESET).sendToTarget();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index c6d536d..bf4df94 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1937,16 +1937,6 @@
     }
 
     @Override
-    public void flushNetworkDnsCache(int netId) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        try {
-            mConnector.execute("resolver", "flushnet", netId);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-    }
-
-    @Override
     public void setFirewallEnabled(boolean enabled) {
         enforceSystemUid();
         try {
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 879bb6f..2a78f90 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -18,10 +18,12 @@
 
 import android.Manifest.permission;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.net.INetworkScoreCache;
 import android.net.INetworkScoreService;
@@ -30,6 +32,7 @@
 import android.net.NetworkScorerAppManager.NetworkScorerAppData;
 import android.net.ScoredNetwork;
 import android.os.Binder;
+import android.os.IBinder;
 import android.os.PatternMatcher;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -55,17 +58,17 @@
  */
 public class NetworkScoreService extends INetworkScoreService.Stub {
     private static final String TAG = "NetworkScoreService";
+    private static final boolean DBG = false;
 
     private final Context mContext;
-
     private final Map<Integer, INetworkScoreCache> mScoreCaches;
-
     /** Lock used to update mReceiver when scorer package changes occur. */
-    private Object mReceiverLock = new Object[0];
+    private final Object mReceiverLock = new Object[0];
 
     /** Clears scores when the active scorer package is no longer valid. */
     @GuardedBy("mReceiverLock")
     private ScorerChangedReceiver mReceiver;
+    private ScoringServiceConnection mServiceConnection;
 
     private class ScorerChangedReceiver extends BroadcastReceiver {
         final String mRegisteredPackage;
@@ -77,14 +80,23 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-            if ((Intent.ACTION_PACKAGE_CHANGED.equals(action) ||
-                    Intent.ACTION_PACKAGE_REPLACED.equals(action) ||
-                    Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) &&
-                    NetworkScorerAppManager.getActiveScorer(mContext) == null) {
-                // Package change has invalidated a scorer.
-                Log.i(TAG, "Package " + mRegisteredPackage +
-                        " is no longer valid, disabling scoring");
-                setScorerInternal(null);
+            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
+                    || Intent.ACTION_PACKAGE_REPLACED.equals(action)
+                    || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
+                NetworkScorerAppData activeScorer =
+                        NetworkScorerAppManager.getActiveScorer(mContext);
+                if (activeScorer == null) {
+                    // Package change has invalidated a scorer.
+                    Log.i(TAG, "Package " + mRegisteredPackage +
+                            " is no longer valid, disabling scoring.");
+                    setScorerInternal(null);
+                } else if (activeScorer.mScoringServiceClassName == null) {
+                    // The scoring service is not available, make sure it's unbound.
+                    unbindFromScoringServiceIfNeeded();
+                } else {
+                    // The scoring service may have changed or been added.
+                    bindToScoringServiceIfNeeded(activeScorer);
+                }
             }
         }
     }
@@ -96,6 +108,7 @@
 
     /** Called when the system is ready to run third-party code but before it actually does so. */
     void systemReady() {
+        if (DBG) Log.d(TAG, "systemReady");
         ContentResolver cr = mContext.getContentResolver();
         if (Settings.Global.getInt(cr, Settings.Global.NETWORK_SCORING_PROVISIONED, 0) == 0) {
             // On first run, we try to initialize the scorer to the one configured at build time.
@@ -111,7 +124,14 @@
         registerPackageReceiverIfNeeded();
     }
 
+    /** Called when the system is ready for us to start third-party code. */
+    void systemRunning() {
+        if (DBG) Log.d(TAG, "systemRunning");
+        bindToScoringServiceIfNeeded();
+    }
+
     private void registerPackageReceiverIfNeeded() {
+        if (DBG) Log.d(TAG, "registerPackageReceiverIfNeeded");
         NetworkScorerAppData scorer = NetworkScorerAppManager.getActiveScorer(mContext);
         synchronized (mReceiverLock) {
             // Unregister the receiver if the current scorer has changed since last registration.
@@ -142,6 +162,41 @@
         }
     }
 
+    private void bindToScoringServiceIfNeeded() {
+        if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded");
+        NetworkScorerAppData scorerData = NetworkScorerAppManager.getActiveScorer(mContext);
+        bindToScoringServiceIfNeeded(scorerData);
+    }
+
+    private void bindToScoringServiceIfNeeded(NetworkScorerAppData scorerData) {
+        if (DBG) Log.d(TAG, "bindToScoringServiceIfNeeded(" + scorerData + ")");
+        if (scorerData != null && scorerData.mScoringServiceClassName != null) {
+            ComponentName componentName =
+                    new ComponentName(scorerData.mPackageName, scorerData.mScoringServiceClassName);
+            // If we're connected to a different component then drop it.
+            if (mServiceConnection != null
+                    && !mServiceConnection.mComponentName.equals(componentName)) {
+                unbindFromScoringServiceIfNeeded();
+            }
+
+            // If we're not connected at all then create a new connection.
+            if (mServiceConnection == null) {
+                mServiceConnection = new ScoringServiceConnection(componentName);
+            }
+
+            // Make sure the connection is connected (idempotent)
+            mServiceConnection.connect(mContext);
+        }
+    }
+
+    private void unbindFromScoringServiceIfNeeded() {
+        if (DBG) Log.d(TAG, "unbindFromScoringServiceIfNeeded");
+        if (mServiceConnection != null) {
+            mServiceConnection.disconnect(mContext);
+        }
+        mServiceConnection = null;
+    }
+
     @Override
     public boolean updateScores(ScoredNetwork[] networks) {
         if (!NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid())) {
@@ -228,8 +283,10 @@
 
     /** Set the active scorer. Callers are responsible for checking permissions as appropriate. */
     private boolean setScorerInternal(String packageName) {
+        if (DBG) Log.d(TAG, "setScorerInternal(" + packageName + ")");
         long token = Binder.clearCallingIdentity();
         try {
+            unbindFromScoringServiceIfNeeded();
             // Preemptively clear scores even though the set operation could fail. We do this for
             // safety as scores should never be compared across apps; in practice, Settings should
             // only be allowing valid apps to be set as scorers, so failure here should be rare.
@@ -237,8 +294,13 @@
             // Get the scorer that is about to be replaced, if any, so we can notify it directly.
             NetworkScorerAppData prevScorer = NetworkScorerAppManager.getActiveScorer(mContext);
             boolean result = NetworkScorerAppManager.setActiveScorer(mContext, packageName);
+            // Unconditionally attempt to bind to the current scorer. If setActiveScorer() failed
+            // then we'll attempt to restore the previous binding (if any), otherwise an attempt
+            // will be made to bind to the new scorer.
+            bindToScoringServiceIfNeeded();
             if (result) { // new scorer successfully set
                 registerPackageReceiverIfNeeded();
+
                 Intent intent = new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED);
                 if (prevScorer != null) { // Directly notify the old scorer.
                     intent.setPackage(prevScorer.mPackageName);
@@ -295,7 +357,6 @@
             return;
         }
         writer.println("Current scorer: " + currentScorer.mPackageName);
-        writer.flush();
 
         for (INetworkScoreCache scoreCache : getScoreCaches()) {
             try {
@@ -307,6 +368,12 @@
                 }
             }
         }
+        if (mServiceConnection != null) {
+            mServiceConnection.dump(fd, writer, args);
+        } else {
+            writer.println("ScoringServiceConnection: null");
+        }
+        writer.flush();
     }
 
     /**
@@ -320,4 +387,50 @@
             return new HashSet<>(mScoreCaches.values());
         }
     }
+
+    private static class ScoringServiceConnection implements ServiceConnection {
+        private final ComponentName mComponentName;
+        private boolean mBound = false;
+
+        ScoringServiceConnection(ComponentName componentName) {
+            mComponentName = componentName;
+        }
+
+        void connect(Context context) {
+            disconnect(context);
+            Intent service = new Intent();
+            service.setComponent(mComponentName);
+            mBound = context.bindServiceAsUser(service, this,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                    UserHandle.SYSTEM);
+            if (!mBound) {
+                Log.w(TAG, "Bind call failed for " + service);
+            }
+        }
+
+        void disconnect(Context context) {
+            try {
+                if (mBound) {
+                    mBound = false;
+                    context.unbindService(this);
+                }
+            } catch (RuntimeException e) {
+                Log.e(TAG, "Unbind failed.", e);
+            }
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (DBG) Log.d(TAG, "ScoringServiceConnection: " + name.flattenToString());
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            if (DBG) Log.d(TAG, "ScoringServiceConnection, disconnected: " + name.flattenToString());
+        }
+
+        public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+            writer.println("ScoringServiceConnection: " + mComponentName + ", bound: " + mBound);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/UiThread.java b/services/core/java/com/android/server/UiThread.java
index 0beb77f..c06afc2 100644
--- a/services/core/java/com/android/server/UiThread.java
+++ b/services/core/java/com/android/server/UiThread.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.os.Handler;
+import android.os.Trace;
 
 /**
  * Shared singleton thread for showing UI.  This is a foreground thread, and in
@@ -35,6 +36,7 @@
         if (sInstance == null) {
             sInstance = new UiThread();
             sInstance.start();
+            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             sHandler = new Handler(sInstance.getLooper());
         }
     }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index bb32303..8a0a62a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -782,7 +782,12 @@
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
-            return readUserDataInternal(accounts, account, key);
+            synchronized (accounts.cacheLock) {
+                if (!accountExistsCacheLocked(accounts, account)) {
+                    return null;
+                }
+                return readUserDataInternalLocked(accounts, account, key);
+            }
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -1869,44 +1874,57 @@
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
-            setUserdataInternal(accounts, account, key, value);
+            synchronized (accounts.cacheLock) {
+                if (!accountExistsCacheLocked(accounts, account)) {
+                    return;
+                }
+                setUserdataInternalLocked(accounts, account, key, value);
+            }
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
 
-    private void setUserdataInternal(UserAccounts accounts, Account account, String key,
+    private boolean accountExistsCacheLocked(UserAccounts accounts, Account account) {
+        if (accounts.accountCache.containsKey(account.type)) {
+            for (Account acc : accounts.accountCache.get(account.type)) {
+                if (acc.name.equals(account.name)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private void setUserdataInternalLocked(UserAccounts accounts, Account account, String key,
             String value) {
         if (account == null || key == null) {
             return;
         }
-        synchronized (accounts.cacheLock) {
-            final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
-            db.beginTransaction();
-            try {
-                long accountId = getAccountIdLocked(db, account);
-                if (accountId < 0) {
+        final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+        db.beginTransaction();
+        try {
+            long accountId = getAccountIdLocked(db, account);
+            if (accountId < 0) {
+                return;
+            }
+            long extrasId = getExtrasIdLocked(db, accountId, key);
+            if (extrasId < 0) {
+                extrasId = insertExtraLocked(db, accountId, key, value);
+                if (extrasId < 0) {
                     return;
                 }
-                long extrasId = getExtrasIdLocked(db, accountId, key);
-                if (extrasId < 0 ) {
-                    extrasId = insertExtraLocked(db, accountId, key, value);
-                    if (extrasId < 0) {
-                        return;
-                    }
-                } else {
-                    ContentValues values = new ContentValues();
-                    values.put(EXTRAS_VALUE, value);
-                    if (1 != db.update(CE_TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
-                        return;
-                    }
-
+            } else {
+                ContentValues values = new ContentValues();
+                values.put(EXTRAS_VALUE, value);
+                if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
+                    return;
                 }
-                writeUserDataIntoCacheLocked(accounts, db, account, key, value);
-                db.setTransactionSuccessful();
-            } finally {
-                db.endTransaction();
             }
+            writeUserDataIntoCacheLocked(accounts, db, account, key, value);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
         }
     }
 
@@ -2500,21 +2518,31 @@
                     userId);
             return;
         }
-
         final int pid = Binder.getCallingPid();
         final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
         options.putInt(AccountManager.KEY_CALLER_UID, uid);
         options.putInt(AccountManager.KEY_CALLER_PID, pid);
 
+        // Check to see if the Password should be included to the caller.
+        String callerPkg = optionsIn.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
+        boolean isPasswordForwardingAllowed = isPermitted(
+                callerPkg, uid, Manifest.permission.GET_PASSWORD_PRIVILEGED);
+
         int usrId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(usrId);
             logRecordWithUid(accounts, DebugDbHelper.ACTION_CALLED_START_ACCOUNT_ADD,
                     TABLE_ACCOUNTS, uid);
-            new StartAccountSession(accounts, response, accountType, expectActivityLaunch,
-                    null /* accountName */, false /* authDetailsRequired */,
-                    true /* updateLastAuthenticationTime */) {
+            new StartAccountSession(
+                    accounts,
+                    response,
+                    accountType,
+                    expectActivityLaunch,
+                    null /* accountName */,
+                    false /* authDetailsRequired */,
+                    true /* updateLastAuthenticationTime */,
+                    isPasswordForwardingAllowed) {
                 @Override
                 public void run() throws RemoteException {
                     mAuthenticator.startAddAccountSession(this, mAccountType, authTokenType,
@@ -2537,12 +2565,21 @@
     /** Session that will encrypt the KEY_ACCOUNT_SESSION_BUNDLE in result. */
     private abstract class StartAccountSession extends Session {
 
-        public StartAccountSession(UserAccounts accounts, IAccountManagerResponse response,
-                String accountType, boolean expectActivityLaunch, String accountName,
-                boolean authDetailsRequired, boolean updateLastAuthenticationTime) {
+        private final boolean mIsPasswordForwardingAllowed;
+
+        public StartAccountSession(
+                UserAccounts accounts,
+                IAccountManagerResponse response,
+                String accountType,
+                boolean expectActivityLaunch,
+                String accountName,
+                boolean authDetailsRequired,
+                boolean updateLastAuthenticationTime,
+                boolean isPasswordForwardingAllowed) {
             super(accounts, response, accountType, expectActivityLaunch,
                     true /* stripAuthTokenFromResult */, accountName, authDetailsRequired,
                     updateLastAuthenticationTime);
+            mIsPasswordForwardingAllowed = isPasswordForwardingAllowed;
         }
 
         @Override
@@ -2555,6 +2592,10 @@
                 checkKeyIntent(
                         Binder.getCallingUid(),
                         intent);
+                // Omit passwords if the caller isn't permitted to see them.
+                if (!mIsPasswordForwardingAllowed) {
+                    result.remove(AccountManager.KEY_PASSWORD);
+                }
             }
             IAccountManagerResponse response;
             if (mExpectActivityLaunch && result != null
@@ -2901,6 +2942,12 @@
         }
 
         int userId = UserHandle.getCallingUserId();
+
+        // Check to see if the Password should be included to the caller.
+        String callerPkg = loginOptions.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
+        boolean isPasswordForwardingAllowed = isPermitted(
+                callerPkg, uid, Manifest.permission.GET_PASSWORD_PRIVILEGED);
+
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -2911,7 +2958,8 @@
                     expectActivityLaunch,
                     account.name,
                     false /* authDetailsRequired */,
-                    true /* updateLastCredentialTime */) {
+                    true /* updateLastCredentialTime */,
+                    isPasswordForwardingAllowed) {
                 @Override
                 public void run() throws RemoteException {
                     mAuthenticator.startUpdateCredentialsSession(this, account, authTokenType,
@@ -5262,17 +5310,16 @@
         }
     }
 
-    protected String readUserDataInternal(UserAccounts accounts, Account account, String key) {
-        synchronized (accounts.cacheLock) {
-            HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
-            if (userDataForAccount == null) {
-                // need to populate the cache for this account
-                final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked();
-                userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
-                accounts.userDataCache.put(account, userDataForAccount);
-            }
-            return userDataForAccount.get(key);
+    protected String readUserDataInternalLocked(
+            UserAccounts accounts, Account account, String key) {
+        HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
+        if (userDataForAccount == null) {
+            // need to populate the cache for this account
+            final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
+            userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
+            accounts.userDataCache.put(account, userDataForAccount);
         }
+        return userDataForAccount.get(key);
     }
 
     protected HashMap<String, String> readUserDataForAccountFromDatabaseLocked(
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d741c49..5d1cb8a 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -343,6 +343,25 @@
             return null;
         }
 
+        if (!r.startRequested) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                // Before going further -- if this app is not allowed to run in the
+                // background, then at this point we aren't going to let it period.
+                final int allowed = mAm.checkAllowBackgroundLocked(
+                        r.appInfo.uid, r.packageName, callingPid, true);
+                if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
+                    Slog.w(TAG, "Background start not allowed: service "
+                            + service + " to " + r.name.flattenToShortString()
+                            + " from pid=" + callingPid + " uid=" + callingUid
+                            + " pkg=" + callingPackage);
+                    return null;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
         NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
                 callingUid, r.packageName, service, service.getFlags(), null, r.userId);
 
@@ -1274,23 +1293,6 @@
                 }
                 r = smap.mServicesByName.get(name);
                 if (r == null && createIfNeeded) {
-                    final long token = Binder.clearCallingIdentity();
-                    try {
-                        // Before going further -- if this app is not allowed to run in the
-                        // background, then at this point we aren't going to let it period.
-                        final int allowed = mAm.checkAllowBackgroundLocked(
-                                sInfo.applicationInfo.uid, sInfo.packageName, callingPid, true);
-                        if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
-                            Slog.w(TAG, "Background execution not allowed: service "
-                                    + service + " to " + name.flattenToShortString()
-                                    + " from pid=" + callingPid + " uid=" + callingUid
-                                    + " pkg=" + callingPackage);
-                            return null;
-                        }
-                    } finally {
-                        Binder.restoreCallingIdentity(token);
-                    }
-
                     Intent.FilterComparison filter
                             = new Intent.FilterComparison(service.cloneFilter());
                     ServiceRestarter res = new ServiceRestarter();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e82c6c7..4852788 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1105,20 +1105,20 @@
     ComponentName mTopComponent;
     String mTopAction = Intent.ACTION_MAIN;
     String mTopData;
-    boolean mProcessesReady = false;
-    boolean mSystemReady = false;
-    boolean mBooting = false;
-    boolean mCallFinishBooting = false;
-    boolean mBootAnimationComplete = false;
-    boolean mOnBattery = false;
-    boolean mLaunchWarningShown = false;
+
+    volatile boolean mProcessesReady = false;
+    volatile boolean mSystemReady = false;
+    volatile boolean mOnBattery = false;
+    volatile int mFactoryTest;
+
+    @GuardedBy("this") boolean mBooting = false;
+    @GuardedBy("this") boolean mCallFinishBooting = false;
+    @GuardedBy("this") boolean mBootAnimationComplete = false;
+    @GuardedBy("this") boolean mLaunchWarningShown = false;
+    @GuardedBy("this") boolean mCheckedForSetup = false;
 
     Context mContext;
 
-    int mFactoryTest;
-
-    boolean mCheckedForSetup;
-
     /**
      * The time at which we will allow normal application switches again,
      * after a call to {@link #stopAppSwitches()}.
@@ -9827,7 +9827,8 @@
     public void updateLockTaskPackages(int userId, String[] packages) {
         final int callingUid = Binder.getCallingUid();
         if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
-            throw new SecurityException("updateLockTaskPackage called from non-system process");
+            enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
+                    "updateLockTaskPackages()");
         }
         synchronized (this) {
             if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Whitelisting " + userId + ":" +
@@ -10589,14 +10590,14 @@
     private boolean requestTargetProviderPermissionsReviewIfNeededLocked(ProviderInfo cpi,
             ProcessRecord r, final int userId) {
         if (getPackageManagerInternalLocked().isPermissionsReviewRequired(
-                cpi.packageName, r.userId)) {
+                cpi.packageName, userId)) {
 
-            final boolean callerForeground = r != null ? r.setSchedGroup
-                    != ProcessList.SCHED_GROUP_BACKGROUND : true;
+            final boolean callerForeground = r == null || r.setSchedGroup
+                    != ProcessList.SCHED_GROUP_BACKGROUND;
 
             // Show a permission review UI only for starting from a foreground app
             if (!callerForeground) {
-                Slog.w(TAG, "u" + r.userId + " Instantiating a provider in package"
+                Slog.w(TAG, "u" + userId + " Instantiating a provider in package"
                         + cpi.packageName + " requires a permissions review");
                 return false;
             }
@@ -10607,7 +10608,7 @@
             intent.putExtra(Intent.EXTRA_PACKAGE_NAME, cpi.packageName);
 
             if (DEBUG_PERMISSIONS_REVIEW) {
-                Slog.i(TAG, "u" + r.userId + " Launching permission review "
+                Slog.i(TAG, "u" + userId + " Launching permission review "
                         + "for package " + cpi.packageName);
             }
 
@@ -13226,10 +13227,11 @@
                     // Merge several logcat streams, and take the last N lines
                     InputStreamReader input = null;
                     try {
-                        java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
-                                "-v", "time", "-b", "events", "-b", "system", "-b", "main",
-                                "-b", "crash",
-                                "-t", String.valueOf(lines)).redirectErrorStream(true).start();
+                        java.lang.Process logcat = new ProcessBuilder(
+                                "/system/bin/timeout", "-k", "15s", "10s",
+                                "/system/bin/logcat", "-v", "time", "-b", "events", "-b", "system",
+                                "-b", "main", "-b", "crash", "-t", String.valueOf(lines))
+                                        .redirectErrorStream(true).start();
 
                         try { logcat.getOutputStream().close(); } catch (IOException e) {}
                         try { logcat.getErrorStream().close(); } catch (IOException e) {}
@@ -15455,8 +15457,9 @@
                     }
 
                     for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
-                        if (oomAdj <= DUMP_MEM_OOM_ADJ[oomIndex]
-                                || oomIndex == (oomPss.length-1)) {
+                        if (oomIndex == (oomPss.length - 1)
+                                || (oomAdj >= DUMP_MEM_OOM_ADJ[oomIndex]
+                                        && oomAdj < DUMP_MEM_OOM_ADJ[oomIndex + 1])) {
                             oomPss[oomIndex] += myTotalPss;
                             oomSwapPss[oomIndex] += myTotalSwapPss;
                             if (oomProcs[oomIndex] == null) {
@@ -18044,6 +18047,9 @@
             ActivityRecord starting, boolean initLocale, boolean persistent, int userId) {
         int changes = 0;
 
+        if (mWindowManager != null) {
+            mWindowManager.deferSurfaceLayout();
+        }
         if (values != null) {
             Configuration newConfig = new Configuration(mConfiguration);
             changes = newConfig.updateFrom(values);
@@ -18144,6 +18150,20 @@
                             null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
                 }
             }
+            // Update the configuration with WM first and check if any of the stacks need to be
+            // resized due to the configuration change. If so, resize the stacks now and do any
+            // relaunches if necessary. This way we don't need to relaunch again below in
+            // ensureActivityConfigurationLocked().
+            if (mWindowManager != null) {
+                final int[] resizedStacks = mWindowManager.setNewConfiguration(mConfiguration);
+                if (resizedStacks != null) {
+                    for (int stackId : resizedStacks) {
+                        final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId);
+                        mStackSupervisor.resizeStackLocked(
+                                stackId, newBounds, null, null, false, false);
+                    }
+                }
+            }
         }
 
         boolean kept = true;
@@ -18165,11 +18185,9 @@
                         !PRESERVE_WINDOWS);
             }
         }
-
-        if (values != null && mWindowManager != null) {
-            mWindowManager.setNewConfiguration(mConfiguration);
+        if (mWindowManager != null) {
+            mWindowManager.continueSurfaceLayout();
         }
-
         return kept;
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index d570be9..9be6b43 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -23,8 +23,6 @@
 import android.os.UserHandle;
 import android.util.DebugUtils;
 
-import com.android.internal.util.ArrayUtils;
-
 import java.io.PrintWriter;
 
 class ActivityManagerShellCommand extends ShellCommand {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0d70e99..7b2a370 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1984,6 +1984,8 @@
         mTmpConfigs.clear();
         mTmpInsetBounds.clear();
         final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+        final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
+        final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds;
         for (int i = tasks.size() - 1; i >= 0; i--) {
             final TaskRecord task = tasks.get(i);
             if (task.isResizeable()) {
@@ -1995,9 +1997,7 @@
                     fitWithinBounds(tempRect2, bounds);
                     task.updateOverrideConfiguration(tempRect2);
                 } else {
-                    task.updateOverrideConfiguration(
-                            tempTaskBounds != null ? tempTaskBounds : bounds,
-                            tempTaskInsetBounds != null ? tempTaskInsetBounds : bounds);
+                    task.updateOverrideConfiguration(taskBounds, insetBounds);
                 }
             }
 
@@ -2043,8 +2043,10 @@
             resizeStackUncheckedLocked(stack, dockedBounds, tempDockedTaskBounds,
                     tempDockedTaskInsetBounds);
 
-            if (stack.mFullscreen) {
-                // The dock stack went fullscreen which is kinda like dismissing it.
+            // TODO: Checking for isAttached might not be needed as if the user passes in null
+            // dockedBounds then they want the docked stack to be dismissed.
+            if (stack.mFullscreen || (dockedBounds == null && !stack.isAttached())) {
+                // The dock stack either was dismissed or went fullscreen, which is kinda the same.
                 // In this case we make all other static stacks fullscreen and move all
                 // docked stack tasks to the fullscreen stack.
                 for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
@@ -2072,13 +2074,10 @@
                 mWindowManager.getStackDockedModeBounds(
                         HOME_STACK_ID, tempRect, true /* ignoreVisibility */);
                 for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
-                    if (StackId.isResizeableByDockedStack(i)) {
-                        ActivityStack otherStack = getStack(i);
-                        if (otherStack != null) {
-                            resizeStackLocked(i, tempRect, tempOtherTaskBounds,
-                                    tempOtherTaskInsetBounds, preserveWindows,
-                                    true /* allowResizeInDockedMode */);
-                        }
+                    if (StackId.isResizeableByDockedStack(i) && getStack(i) != null) {
+                        resizeStackLocked(i, tempRect, tempOtherTaskBounds,
+                                tempOtherTaskInsetBounds, preserveWindows,
+                                true /* allowResizeInDockedMode */);
                     }
                 }
             }
@@ -2738,12 +2737,21 @@
 
     // Called when WindowManager has finished animating the launchingBehind activity to the back.
     void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
-        r.mLaunchTaskBehind = false;
         final TaskRecord task = r.task;
-        task.setLastThumbnailLocked(task.stack.screenshotActivitiesLocked(r));
+        final ActivityStack stack = task.stack;
+
+        r.mLaunchTaskBehind = false;
+        task.setLastThumbnailLocked(stack.screenshotActivitiesLocked(r));
         mRecentTasks.addLocked(task);
         mService.notifyTaskStackChangedLocked();
         mWindowManager.setAppVisibility(r.appToken, false);
+
+        // When launching tasks behind, update the last active time of the top task after the new
+        // task has been shown briefly
+        final ActivityRecord top = stack.topActivity();
+        if (top != null) {
+            top.task.touchActiveTime();
+        }
     }
 
     void scheduleLaunchTaskBehindComplete(IBinder token) {
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 6cd7561..68bd2fd 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -724,9 +724,7 @@
             final boolean crashSilenced = mAppsNotReportingCrashes != null &&
                     mAppsNotReportingCrashes.contains(proc.info.packageName);
             if (mService.canShowErrorDialogs() && !crashSilenced) {
-                Dialog d = new AppErrorDialog(mContext, mService, data);
-                d.show();
-                proc.crashDialog = d;
+                proc.crashDialog = new AppErrorDialog(mContext, mService, data);
             } else {
                 // The device is asleep, so just pretend that the user
                 // saw a crash dialog and hit "force quit".
@@ -735,6 +733,10 @@
                 }
             }
         }
+        // If we've created a crash dialog, show it without the lock held
+        if(data.proc.crashDialog != null) {
+            data.proc.crashDialog.show();
+        }
     }
 
     void stopReportingCrashesLocked(ProcessRecord proc) {
@@ -924,6 +926,7 @@
     }
 
     void handleShowAnrUi(Message msg) {
+        Dialog d = null;
         synchronized (mService) {
             HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
             ProcessRecord proc = (ProcessRecord)data.get("app");
@@ -944,10 +947,9 @@
                     null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
 
             if (mService.canShowErrorDialogs()) {
-                Dialog d = new AppNotRespondingDialog(mService,
+                d = new AppNotRespondingDialog(mService,
                         mContext, proc, (ActivityRecord)data.get("activity"),
                         msg.arg1 != 0);
-                d.show();
                 proc.anrDialog = d;
             } else {
                 MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
@@ -956,6 +958,10 @@
                 mService.killAppAtUsersRequest(proc, null);
             }
         }
+        // If we've created a crash dialog, show it without the lock held
+        if (d != null) {
+            d.show();
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index b157070..e32d1d1 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -285,6 +285,7 @@
         mCallingPackage = info.packageName;
         setIntent(_intent, info);
         setMinDimensions(info);
+        touchActiveTime();
     }
 
     TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
@@ -315,6 +316,7 @@
         taskType = APPLICATION_ACTIVITY_TYPE;
         mTaskToReturnTo = HOME_ACTIVITY_TYPE;
         lastTaskDescription = _taskDescription;
+        touchActiveTime();
     }
 
     private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index aef454e..bea26c7 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -237,7 +237,22 @@
                         AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
             }
 
-            maybeUnlockUser(userId);
+            // We need to delay unlocking managed profiles until the parent user
+            // is also unlocked.
+            if (getUserManager().isManagedProfile(userId)) {
+                final UserInfo parent = getUserManager().getProfileParent(userId);
+                if (parent != null
+                        && isUserRunningLocked(parent.id, ActivityManager.FLAG_AND_UNLOCKED)) {
+                    Slog.d(TAG, "User " + userId + " (parent " + parent.id
+                            + "): attempting unlock because parent is unlocked");
+                    maybeUnlockUser(userId);
+                } else {
+                    Slog.d(TAG, "User " + userId + " (parent " + parent.id
+                            + "): delaying unlock because parent is locked");
+                }
+            } else {
+                maybeUnlockUser(userId);
+            }
         }
     }
 
@@ -260,6 +275,9 @@
                 mUserManager.onBeforeUnlockUser(userId);
                 progress.setProgress(20);
 
+                // Dispatch unlocked to system services
+                mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
+
                 // Send PRE_BOOT broadcasts if fingerprint changed
                 final UserInfo info = getUserInfo(userId);
                 if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) {
@@ -302,9 +320,6 @@
                 // Remember that we logged in
                 mUserManager.onUserLoggedIn(userId);
 
-                // Dispatch unlocked to system services
-                mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
-
                 // Dispatch unlocked to external apps
                 final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
                 unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
@@ -903,6 +918,18 @@
         synchronized (mService) {
             final UserState uss = mStartedUsers.get(userId);
             finishUserUnlocking(uss, progress);
+
+            // We just unlocked a user, so let's now attempt to unlock any
+            // managed profiles under that user.
+            for (int i = 0; i < mStartedUsers.size(); i++) {
+                final int testUserId = mStartedUsers.keyAt(i);
+                final UserInfo parent = getUserManager().getProfileParent(testUserId);
+                if (parent != null && parent.id == userId && testUserId != userId) {
+                    Slog.d(TAG, "User " + testUserId + " (parent " + parent.id
+                            + "): attempting unlock because parent was just unlocked");
+                    maybeUnlockUser(testUserId);
+                }
+            }
         }
 
         return true;
diff --git a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
index 7cac227..f91db78 100644
--- a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
+++ b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
@@ -18,18 +18,21 @@
 
 import com.android.server.SystemService;
 
+import android.app.PendingIntent;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.net.ConnectivityMetricsEvent;
 import android.net.ConnectivityMetricsLogger;
 import android.net.IConnectivityMetricsLogger;
-import android.net.IConnectivityMetricsLoggerSubscriber;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.ArrayMap;
+import android.os.Binder;
+import android.os.Parcel;
+import android.text.format.DateUtils;
 import android.util.Log;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.List;
 
 /** {@hide} */
 public class MetricsLoggerService extends SystemService {
@@ -43,134 +46,307 @@
 
     @Override
     public void onStart() {
+        resetThrottlingCounters(System.currentTimeMillis());
     }
 
     @Override
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
-            Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
+            if (DBG) Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
             publishBinderService(ConnectivityMetricsLogger.CONNECTIVITY_METRICS_LOGGER_SERVICE,
                     mBinder);
         }
     }
 
-    private final int MAX_NUMBER_OF_EVENTS = 100;
-    private final int MAX_TIME_OFFSET = 15*60*1000; // 15 minutes
-    private final List<ConnectivityMetricsEvent> mEvents = new ArrayList<>();
-    private long mLastSentEventTimeMillis = System.currentTimeMillis();
+    // TODO: read from system property
+    private final int MAX_NUMBER_OF_EVENTS = 1000;
 
-    private final void enforceConnectivityInternalPermission() {
+    // TODO: read from system property
+    private final int EVENTS_NOTIFICATION_THRESHOLD = 300;
+
+    // TODO: read from system property
+    private final int THROTTLING_TIME_INTERVAL_MILLIS = 60 * 60 * 1000; // 1 hour
+
+    // TODO: read from system property
+    private final int THROTTLING_MAX_NUMBER_OF_MESSAGES_PER_COMPONENT = 1000;
+
+    private int mEventCounter = 0;
+
+    /**
+     * Reference of the last event in the list of cached events.
+     *
+     * When client of this service retrieves events by calling getEvents, it is passing
+     * ConnectivityMetricsEvent.Reference object. After getEvents returns, that object will
+     * contain this reference. The client can save it and use next time it calls getEvents.
+     * This way only new events will be returned.
+     */
+    private long mLastEventReference = 0;
+
+    private final int mThrottlingCounters[] =
+            new int[ConnectivityMetricsLogger.NUMBER_OF_COMPONENTS];
+
+    private long mThrottlingIntervalBoundaryMillis;
+
+    private final ArrayDeque<ConnectivityMetricsEvent> mEvents = new ArrayDeque<>();
+
+    private void enforceConnectivityInternalPermission() {
         getContext().enforceCallingOrSelfPermission(
                 android.Manifest.permission.CONNECTIVITY_INTERNAL,
                 "MetricsLoggerService");
     }
 
+    private void enforceDumpPermission() {
+        getContext().enforceCallingOrSelfPermission(
+                android.Manifest.permission.DUMP,
+                "MetricsLoggerService");
+    }
+
+    private void resetThrottlingCounters(long currentTimeMillis) {
+        for (int i = 0; i < mThrottlingCounters.length; i++) {
+            mThrottlingCounters[i] = 0;
+        }
+        mThrottlingIntervalBoundaryMillis =
+                currentTimeMillis + THROTTLING_TIME_INTERVAL_MILLIS;
+    }
+
+    private void addEvent(ConnectivityMetricsEvent e) {
+        if (VDBG) {
+            Log.v(TAG, "writeEvent(" + e.toString() + ")");
+        }
+
+        while (mEvents.size() >= MAX_NUMBER_OF_EVENTS) {
+            mEvents.removeFirst();
+        }
+
+        mEvents.addLast(e);
+    }
+
     /**
      * Implementation of the IConnectivityMetricsLogger interface.
      */
     private final IConnectivityMetricsLogger.Stub mBinder = new IConnectivityMetricsLogger.Stub() {
 
-        private final ArrayMap<IConnectivityMetricsLoggerSubscriber,
-                IBinder.DeathRecipient> mSubscribers = new ArrayMap<>();
+        private final ArrayList<PendingIntent> mPendingIntents = new ArrayList<>();
 
-
-        private ConnectivityMetricsEvent[] prepareEventsToSendIfReady() {
-            ConnectivityMetricsEvent[] eventsToSend = null;
-            final long currentTimeMillis = System.currentTimeMillis();
-            final long timeOffset = currentTimeMillis - mLastSentEventTimeMillis;
-            if (timeOffset >= MAX_TIME_OFFSET
-                    || timeOffset < 0 // system time has changed
-                    || mEvents.size() >= MAX_NUMBER_OF_EVENTS) {
-                // batch events
-                mLastSentEventTimeMillis = currentTimeMillis;
-                eventsToSend = new ConnectivityMetricsEvent[mEvents.size()];
-                mEvents.toArray(eventsToSend);
-                mEvents.clear();
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump ConnectivityMetricsLoggerService " +
+                        "from from pid=" + Binder.getCallingPid() + ", uid=" +
+                        Binder.getCallingUid());
+                return;
             }
-            return eventsToSend;
-        }
 
-        private void maybeSendEventsToSubscribers(ConnectivityMetricsEvent[] eventsToSend) {
-            if (eventsToSend == null || eventsToSend.length == 0) return;
-            synchronized (mSubscribers) {
-                for (IConnectivityMetricsLoggerSubscriber s : mSubscribers.keySet()) {
-                    try {
-                        s.onEvents(eventsToSend);
-                    } catch (RemoteException ex) {
-                        Log.e(TAG, "RemoteException " + ex);
-                    }
-                }
-            }
-        }
+            boolean dumpSerializedSize = false;
+            boolean dumpEvents = false;
+            for (String arg : args) {
+                switch (arg) {
+                    case "--events":
+                        dumpEvents = true;
+                        break;
 
-        public void logEvent(ConnectivityMetricsEvent event) {
-            ConnectivityMetricsEvent[] events = new ConnectivityMetricsEvent[]{event};
-            logEvents(events);
-        }
+                    case "--size":
+                        dumpSerializedSize = true;
+                        break;
 
-        public void logEvents(ConnectivityMetricsEvent[] events) {
-            enforceConnectivityInternalPermission();
-            ConnectivityMetricsEvent[] eventsToSend;
-
-            if (VDBG) {
-                for (ConnectivityMetricsEvent e : events) {
-                    Log.v(TAG, "writeEvent(" + e.toString() + ")");
+                    case "--all":
+                        dumpEvents = true;
+                        dumpSerializedSize = true;
+                        break;
                 }
             }
 
             synchronized (mEvents) {
-                for (ConnectivityMetricsEvent e : events) {
-                    mEvents.add(e);
+                pw.println("Number of events: " + mEvents.size());
+                pw.println("Time span: " +
+                        DateUtils.formatElapsedTime(
+                                (System.currentTimeMillis() - mEvents.peekFirst().timestamp)
+                                        / 1000));
+
+                if (dumpSerializedSize) {
+                    long dataSize = 0;
+                    Parcel p = Parcel.obtain();
+                    for (ConnectivityMetricsEvent e : mEvents) {
+                        dataSize += 16; // timestamp and 2 stamps
+
+                        p.writeParcelable(e.data, 0);
+                    }
+                    dataSize += p.dataSize();
+                    p.recycle();
+                    pw.println("Serialized data size: " + dataSize);
                 }
 
-                eventsToSend = prepareEventsToSendIfReady();
+                if (dumpEvents) {
+                    pw.println();
+                    pw.println("Events:");
+                    for (ConnectivityMetricsEvent e : mEvents) {
+                        pw.println(e.toString());
+                    }
+                }
             }
 
-            maybeSendEventsToSubscribers(eventsToSend);
+            if (!mPendingIntents.isEmpty()) {
+                pw.println();
+                pw.println("Pending intents:");
+                for (PendingIntent pi : mPendingIntents) {
+                    pw.println(pi.toString());
+                }
+            }
         }
 
-        public boolean subscribe(IConnectivityMetricsLoggerSubscriber subscriber) {
-            enforceConnectivityInternalPermission();
-            if (VDBG) Log.v(TAG, "subscribe");
+        public long logEvent(ConnectivityMetricsEvent event) {
+            ConnectivityMetricsEvent[] events = new ConnectivityMetricsEvent[]{event};
+            return logEvents(events);
+        }
 
-            synchronized (mSubscribers) {
-                if (mSubscribers.containsKey(subscriber)) {
-                    Log.e(TAG, "subscriber is already subscribed");
-                    return false;
+        /**
+         * @param events
+         *
+         * Note: All events must belong to the same component.
+         *
+         * @return 0 on success
+         *        <0 if error happened
+         *        >0 timestamp after which new events will be accepted
+         */
+        public long logEvents(ConnectivityMetricsEvent[] events) {
+            enforceConnectivityInternalPermission();
+
+            if (events == null || events.length == 0) {
+                Log.wtf(TAG, "No events passed to logEvents()");
+                return -1;
+            }
+
+            int componentTag = events[0].componentTag;
+            if (componentTag < 0 ||
+                    componentTag >= ConnectivityMetricsLogger.NUMBER_OF_COMPONENTS) {
+                Log.wtf(TAG, "Unexpected tag: " + componentTag);
+                return -1;
+            }
+
+            synchronized (mThrottlingCounters) {
+                long currentTimeMillis = System.currentTimeMillis();
+                if (currentTimeMillis > mThrottlingIntervalBoundaryMillis) {
+                    resetThrottlingCounters(currentTimeMillis);
                 }
-                final IConnectivityMetricsLoggerSubscriber s = subscriber;
-                IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
-                    @Override
-                    public void binderDied() {
-                        if (VDBG) Log.v(TAG, "subscriber died");
-                        synchronized (mSubscribers) {
-                            mSubscribers.remove(s);
+
+                mThrottlingCounters[componentTag] += events.length;
+
+                if (mThrottlingCounters[componentTag] >
+                        THROTTLING_MAX_NUMBER_OF_MESSAGES_PER_COMPONENT) {
+                    Log.w(TAG, "Too many events from #" + componentTag +
+                            ". Block until " + mThrottlingIntervalBoundaryMillis);
+
+                    return mThrottlingIntervalBoundaryMillis;
+                }
+            }
+
+            boolean sendPendingIntents = false;
+
+            synchronized (mEvents) {
+                for (ConnectivityMetricsEvent e : events) {
+                    if (e.componentTag != componentTag) {
+                        Log.wtf(TAG, "Unexpected tag: " + e.componentTag);
+                        return -1;
+                    }
+
+                    addEvent(e);
+                }
+
+                mLastEventReference += events.length;
+
+                mEventCounter += events.length;
+                if (mEventCounter >= EVENTS_NOTIFICATION_THRESHOLD) {
+                    mEventCounter = 0;
+                    sendPendingIntents = true;
+                }
+            }
+
+            if (sendPendingIntents) {
+                synchronized (mPendingIntents) {
+                    for (PendingIntent pi : mPendingIntents) {
+                        if (VDBG) Log.v(TAG, "Send pending intent");
+                        try {
+                            pi.send(getContext(), 0, null, null, null);
+                        } catch (PendingIntent.CanceledException e) {
+                            Log.e(TAG, "Pending intent canceled: " + pi);
+                            mPendingIntents.remove(pi);
                         }
                     }
-                };
-
-                try {
-                    subscriber.asBinder().linkToDeath(dr, 0);
-                    mSubscribers.put(subscriber, dr);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "subscribe failed: " + e);
-                    return false;
                 }
             }
 
+            return 0;
+        }
+
+        /**
+         * Retrieve events
+         *
+         * @param reference of the last event previously returned. The function will return
+         *                  events following it.
+         *                  If 0 then all events will be returned.
+         *                  After the function call it will contain reference of the
+         *                  last returned event.
+         * @return events
+         */
+        public ConnectivityMetricsEvent[] getEvents(ConnectivityMetricsEvent.Reference reference) {
+            enforceDumpPermission();
+            long ref = reference.value;
+            if (VDBG) Log.v(TAG, "getEvents(" + ref + ")");
+
+            ConnectivityMetricsEvent[] result;
+            synchronized (mEvents) {
+                if (ref > mLastEventReference) {
+                    Log.e(TAG, "Invalid reference");
+                    reference.value = mLastEventReference;
+                    return null;
+                }
+                if (ref < mLastEventReference - mEvents.size()) {
+                    ref = mLastEventReference - mEvents.size();
+                }
+
+                int numEventsToSkip =
+                        mEvents.size() // Total number of events
+                        - (int)(mLastEventReference - ref); // Number of events to return
+
+                result = new ConnectivityMetricsEvent[mEvents.size() - numEventsToSkip];
+                int i = 0;
+                for (ConnectivityMetricsEvent e : mEvents) {
+                    if (numEventsToSkip > 0) {
+                        numEventsToSkip--;
+                    } else {
+                        result[i++] = e;
+                    }
+                }
+            }
+
+            reference.value = mLastEventReference;
+
+            return result;
+        }
+
+        public boolean register(PendingIntent newEventsIntent) {
+            enforceDumpPermission();
+            if (VDBG) Log.v(TAG, "register(" + newEventsIntent + ")");
+
+            synchronized (mPendingIntents) {
+                if (mPendingIntents.remove(newEventsIntent)) {
+                    Log.w(TAG, "Replacing registered pending intent");
+                }
+                mPendingIntents.add(newEventsIntent);
+            }
+
             return true;
         }
 
-        public void unsubscribe(IConnectivityMetricsLoggerSubscriber subscriber) {
-            enforceConnectivityInternalPermission();
-            if (VDBG) Log.v(TAG, "unsubscribe");
-            synchronized (mSubscribers) {
-                IBinder.DeathRecipient dr = mSubscribers.remove(subscriber);
-                if (dr == null) {
-                    Log.e(TAG, "subscriber is not subscribed");
-                    return;
+        public void unregister(PendingIntent newEventsIntent) {
+            enforceDumpPermission();
+            if (VDBG) Log.v(TAG, "unregister(" + newEventsIntent + ")");
+
+            synchronized (mPendingIntents) {
+                if (!mPendingIntents.remove(newEventsIntent)) {
+                    Log.e(TAG, "Pending intent is not registered");
                 }
-                subscriber.asBinder().unlinkToDeath(dr, 0);
             }
         }
     };
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index d10df02..2cba93fd 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1211,6 +1211,11 @@
                     Log.e(TAG, "Error Tethering: " + e.toString());
                     setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
 
+                    try {
+                        mNMService.untetherInterface(mIfaceName);
+                    } catch (Exception ee) {
+                        Log.e(TAG, "Error untethering after failure!" + ee.toString());
+                    }
                     transitionTo(mInitialState);
                     return;
                 }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 3b0b79a..a111bf9 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -264,7 +264,12 @@
             return true;
         }
 
-        // Check if the caller is authorized.
+        // Stop an existing always-on VPN from being dethroned by other apps.
+        if (getAlwaysOnPackage() != null) {
+            return false;
+        }
+
+        // Check that the caller is authorized.
         enforceControlPermission();
 
         prepareInternal(newPackage);
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 7f7ea9d..6e7ea99 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -42,10 +42,10 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.FactoryTest;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
@@ -59,6 +59,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
+import com.android.server.SystemService;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -72,7 +73,31 @@
  * {@hide}
  */
 public final class ContentService extends IContentService.Stub {
-    private static final String TAG = "ContentService";
+    static final String TAG = "ContentService";
+    static final boolean DEBUG = false;
+
+    public static class Lifecycle extends SystemService {
+        private ContentService mContentService;
+
+        public Lifecycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            final boolean factoryTest = (FactoryTest
+                    .getMode() == FactoryTest.FACTORY_TEST_LOW_LEVEL);
+            mContentService = new ContentService(getContext(), factoryTest);
+            publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mContentService);
+        }
+
+        @Override
+        public void onCleanupUser(int userHandle) {
+            synchronized (mContentService.mCache) {
+                mContentService.mCache.remove(userHandle);
+            }
+        }
+    }
 
     private Context mContext;
     private boolean mFactoryTest;
@@ -94,12 +119,18 @@
     private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            final Uri data = intent.getData();
-            if (data != null) {
-                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
-                        UserHandle.USER_NULL);
-                final String packageName = data.getSchemeSpecificPart();
-                invalidateCacheLocked(userId, packageName, null);
+            synchronized (mCache) {
+                if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
+                    mCache.clear();
+                } else {
+                    final Uri data = intent.getData();
+                    if (data != null) {
+                        final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                                UserHandle.USER_NULL);
+                        final String packageName = data.getSchemeSpecificPart();
+                        invalidateCacheLocked(userId, packageName, null);
+                    }
+                }
             }
         }
     };
@@ -227,6 +258,11 @@
         packageFilter.addDataScheme("package");
         mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL,
                 packageFilter, null, null);
+
+        final IntentFilter localeFilter = new IntentFilter();
+        localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
+        mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL,
+                localeFilter, null, null);
     }
 
     public void systemReady() {
@@ -304,12 +340,10 @@
      */
     @Override
     public void notifyChange(Uri uri, IContentObserver observer,
-                             boolean observerWantsSelfNotifications, boolean syncToNetwork,
+                             boolean observerWantsSelfNotifications, int flags,
                              int userHandle) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
-                    + " from observer " + observer + ", syncToNetwork " + syncToNetwork);
-        }
+        if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle
+                + " from observer " + observer + ", flags " + Integer.toHexString(flags));
 
         final int uid = Binder.getCallingUid();
         final int pid = Binder.getCallingPid();
@@ -338,16 +372,15 @@
             ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
             synchronized (mRootNode) {
                 mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
-                        userHandle, calls);
+                        flags, userHandle, calls);
             }
             final int numCalls = calls.size();
             for (int i=0; i<numCalls; i++) {
                 ObserverCall oc = calls.get(i);
                 try {
                     oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
-                    }
+                    if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
+                            + uri);
                 } catch (RemoteException ex) {
                     synchronized (mRootNode) {
                         Log.w(TAG, "Found dead observer, removing");
@@ -366,7 +399,7 @@
                     }
                 }
             }
-            if (syncToNetwork) {
+            if ((flags&ContentResolver.NOTIFY_SYNC_TO_NETWORK) != 0) {
                 SyncManager syncManager = getSyncManager();
                 if (syncManager != null) {
                     syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid,
@@ -385,7 +418,8 @@
 
     public void notifyChange(Uri uri, IContentObserver observer,
                              boolean observerWantsSelfNotifications, boolean syncToNetwork) {
-        notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
+        notifyChange(uri, observer, observerWantsSelfNotifications,
+                syncToNetwork ? ContentResolver.NOTIFY_SYNC_TO_NETWORK : 0,
                 UserHandle.getCallingUserId());
     }
 
@@ -1029,14 +1063,14 @@
             for (int i = 0; i < packageCache.size();) {
                 final Pair<String, Uri> key = packageCache.keyAt(i);
                 if (key.second != null && key.second.toString().startsWith(uri.toString())) {
-                    Slog.d(TAG, "Invalidating cache for key " + key);
+                    if (DEBUG) Slog.d(TAG, "Invalidating cache for key " + key);
                     packageCache.removeAt(i);
                 } else {
                     i++;
                 }
             }
         } else {
-            Slog.d(TAG, "Invalidating cache for package " + providerPackageName);
+            if (DEBUG) Slog.d(TAG, "Invalidating cache for package " + providerPackageName);
             packageCache.clear();
         }
     }
@@ -1080,12 +1114,6 @@
         }
     }
 
-    public static ContentService main(Context context, boolean factoryTest) {
-        ContentService service = new ContentService(context, factoryTest);
-        ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
-        return service;
-    }
-
     /**
      * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL
      * permission, if the userHandle is not for the caller.
@@ -1281,8 +1309,8 @@
         }
 
         private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
-                                              boolean observerWantsSelfNotifications, int targetUserHandle,
-                                              ArrayList<ObserverCall> calls) {
+                                              boolean observerWantsSelfNotifications, int flags,
+                                              int targetUserHandle, ArrayList<ObserverCall> calls) {
             int N = mObservers.size();
             IBinder observerBinder = observer == null ? null : observer.asBinder();
             for (int i = 0; i < N; i++) {
@@ -1300,9 +1328,29 @@
                         || entry.userHandle == UserHandle.USER_ALL
                         || targetUserHandle == entry.userHandle) {
                     // Make sure the observer is interested in the notification
-                    if (leaf || (!leaf && entry.notifyForDescendants)) {
-                        calls.add(new ObserverCall(this, entry.observer, selfChange));
+                    if (leaf) {
+                        // If we are at the leaf: we always report, unless the sender has asked
+                        // to skip observers that are notifying for descendants (since they will
+                        // be sending another more specific URI for them).
+                        if ((flags&ContentResolver.NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS) != 0
+                                && entry.notifyForDescendants) {
+                            if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer
+                                    + ": skip notify for descendants");
+                            continue;
+                        }
+                    } else {
+                        // If we are not at the leaf: we report if the observer says it wants
+                        // to be notified for all descendants.
+                        if (!entry.notifyForDescendants) {
+                            if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer
+                                    + ": not monitor descendants");
+                            continue;
+                        }
                     }
+                    if (DEBUG) Slog.d(TAG, "Reporting to " + entry.observer + ": leaf=" + leaf
+                            + " flags=" + Integer.toHexString(flags)
+                            + " desc=" + entry.notifyForDescendants);
+                    calls.add(new ObserverCall(this, entry.observer, selfChange));
                 }
             }
         }
@@ -1311,19 +1359,22 @@
          * targetUserHandle is either a hard user handle or is USER_ALL
          */
         public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
-                                           boolean observerWantsSelfNotifications, int targetUserHandle,
-                                           ArrayList<ObserverCall> calls) {
+                                           boolean observerWantsSelfNotifications, int flags,
+                                           int targetUserHandle, ArrayList<ObserverCall> calls) {
             String segment = null;
             int segmentCount = countUriSegments(uri);
             if (index >= segmentCount) {
                 // This is the leaf node, notify all observers
+                if (DEBUG) Slog.d(TAG, "Collecting leaf observers @ #" + index + ", node " + mName);
                 collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
-                        targetUserHandle, calls);
+                        flags, targetUserHandle, calls);
             } else if (index < segmentCount){
                 segment = getUriSegment(uri, index);
+                if (DEBUG) Slog.d(TAG, "Collecting non-leaf observers @ #" + index + " / "
+                        + segment);
                 // Notify any observers at this level who are interested in descendants
                 collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
-                        targetUserHandle, calls);
+                        flags, targetUserHandle, calls);
             }
 
             int N = mChildren.size();
@@ -1331,8 +1382,8 @@
                 ObserverNode node = mChildren.get(i);
                 if (segment == null || node.mName.equals(segment)) {
                     // We found the child,
-                    node.collectObserversLocked(uri, index + 1,
-                            observer, observerWantsSelfNotifications, targetUserHandle, calls);
+                    node.collectObserversLocked(uri, index + 1, observer,
+                            observerWantsSelfNotifications, flags, targetUserHandle, calls);
                     if (segment != null) {
                         break;
                     }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index e5342ce..db41a54 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1402,12 +1402,24 @@
         }
     }
 
+    private void restoreLostPeriodicSyncsIfNeeded(int userId) {
+        List<SyncOperation> periodicSyncs = new ArrayList<SyncOperation>();
+        for (SyncOperation sync : getAllPendingSyncs()) {
+            if (sync.isPeriodic && sync.target.userId == userId) {
+                periodicSyncs.add(sync);
+            }
+        }
+        mSyncStorageEngine.restorePeriodicSyncsIfNeededForUser(userId, periodicSyncs);
+    }
+
     private void onUserUnlocked(int userId) {
         // Make sure that accounts we're about to use are valid.
         AccountManagerService.getSingleton().validateAccounts(userId);
 
         mSyncAdapters.invalidateCache(userId);
 
+        restoreLostPeriodicSyncsIfNeeded(userId);
+
         EndPoint target = new EndPoint(null, null, userId);
         updateRunningAccounts(target);
 
@@ -2578,9 +2590,11 @@
                 }
             }
 
+            // Cancel all jobs from non-existent accounts.
+            AccountAndUser[] allAccounts = AccountManagerService.getSingleton().getAllAccounts();
             List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
-                if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) {
+                if (!containsAccountAndUser(allAccounts, op.target.account, op.target.userId)) {
                     getJobScheduler().cancel(op.jobId);
                 }
             }
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index bc3fc6a..fb23265 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -826,6 +826,35 @@
         return true;
     }
 
+    /**
+     * STOPSHIP This is a temporary workaround and should be removed before shipping: b/28052438
+     */
+    void restorePeriodicSyncsIfNeededForUser(int userHandle, List<SyncOperation> periodicSyncs) {
+        if (mPeriodicSyncAddedListener == null) {
+            return;
+        }
+        synchronized (mAuthorities) {
+            for (int i = 0; i < mAuthorities.size(); i++) {
+                AuthorityInfo authority = mAuthorities.valueAt(i);
+                if (authority.target.userId == userHandle && authority.enabled) {
+                    boolean periodicSyncAlreadyExists = false;
+                    for (SyncOperation sync : periodicSyncs) {
+                        if (authority.target.matchesSpec(sync.target)) {
+                            periodicSyncAlreadyExists = true;
+                            break;
+                        }
+                    }
+                    // The periodic sync must have been lost due to previous bug.
+                    if (!periodicSyncAlreadyExists) {
+                        mPeriodicSyncAddedListener.onPeriodicSyncAdded(authority.target,
+                                new Bundle(), DEFAULT_POLL_FREQUENCY_SECONDS,
+                                calculateDefaultFlexTime(DEFAULT_POLL_FREQUENCY_SECONDS));
+                    }
+                }
+            }
+        }
+    }
+
     public void setMasterSyncAutomatically(boolean flag, int userId) {
         synchronized (mAuthorities) {
             Boolean auto = mMasterSyncAutomatically.get(userId);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1ed7070..8f8afd5 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -103,7 +103,6 @@
     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
 
     // Brightness animation ramp rate in brightness units per second.
-    private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
     private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
 
     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
@@ -244,6 +243,9 @@
     private boolean mAppliedDimming;
     private boolean mAppliedLowPower;
 
+    // Brightness ramp rate fast.
+    private final int mBrightnessRampRateFast;
+
     // The controller for the automatic brightness level.
     private AutomaticBrightnessController mAutomaticBrightnessController;
 
@@ -303,6 +305,9 @@
         mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
 
+        mBrightnessRampRateFast = resources.getInteger(
+                com.android.internal.R.integer.config_brightness_ramp_rate_fast);
+
         int lightSensorRate = resources.getInteger(
                 com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
         long brighteningLightDebounce = resources.getInteger(
@@ -698,7 +703,7 @@
         if (!mPendingScreenOff) {
             if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
                 animateScreenBrightness(brightness,
-                        slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
+                        slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast);
             } else {
                 animateScreenBrightness(brightness, 0);
             }
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 7b134ca..3d8bf51 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -107,6 +107,7 @@
     private static final int FINGERPRINT_ACQUIRED_GOOD = 0;
     private final String mKeyguardPackage;
     private int mCurrentUserId = UserHandle.USER_CURRENT;
+    private int mUserIdForRemove = UserHandle.USER_NULL;
 
     Handler mHandler = new Handler() {
         @Override
@@ -205,10 +206,12 @@
     protected void handleRemoved(long deviceId, int fingerId, int groupId) {
         final ClientMonitor client = mRemoveClient;
         if (fingerId != 0) {
-            removeTemplateForUser(mRemoveClient, fingerId);
+            removeTemplateForUser(mUserIdForRemove, fingerId);
+        } else {
+            mUserIdForRemove = UserHandle.USER_NULL;
         }
         if (client != null && client.sendRemoved(fingerId, groupId)) {
-            removeClient(mRemoveClient);
+            removeClient(client);
         }
     }
 
@@ -325,8 +328,8 @@
         return false;
     }
 
-    private void removeTemplateForUser(ClientMonitor clientMonitor, int fingerId) {
-        mFingerprintUtils.removeFingerprintIdForUser(mContext, fingerId, clientMonitor.userId);
+    private void removeTemplateForUser(int userId, int fingerId) {
+        mFingerprintUtils.removeFingerprintIdForUser(mContext, fingerId, userId);
     }
 
     private void addTemplateForUser(ClientMonitor clientMonitor, int fingerId) {
@@ -488,6 +491,7 @@
 
         stopPendingOperations(true);
         mRemoveClient = new ClientMonitor(token, receiver, userId, restricted, token.toString());
+        mUserIdForRemove = mCurrentUserId;
         // The fingerprint template ids will be removed when we get confirmation from the HAL
         try {
             final int result = daemon.remove(fingerId, userId);
@@ -943,10 +947,6 @@
                 if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
                 return;
             }
-
-            // Group ID is arbitrarily set to parent profile user ID. It just represents
-            // the default fingerprints for the user.
-            final int effectiveGroupId = getEffectiveUserId(groupId);
             final int realUserId = Binder.getCallingUid();
 
             final boolean restricted = isRestricted();
@@ -954,7 +954,7 @@
                 @Override
                 public void run() {
                     MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
-                    startAuthentication(token, opId, realUserId, effectiveGroupId, receiver,
+                    startAuthentication(token, opId, realUserId, groupId, receiver,
                             flags, restricted, opPackageName);
                 }
             });
@@ -989,14 +989,10 @@
                 final IFingerprintServiceReceiver receiver) {
             checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
             final boolean restricted = isRestricted();
-
-            // Group ID is arbitrarily set to parent profile user ID. It just represents
-            // the default fingerprints for the user.
-            final int effectiveGroupId = getEffectiveUserId(groupId);
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    startRemove(token, fingerId, effectiveGroupId, receiver, restricted);
+                    startRemove(token, fingerId, groupId, receiver, restricted);
                 }
             });
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index a36e671..69c012e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -165,15 +165,13 @@
     @ServiceThreadOnly
     protected void onStandby(boolean initiatedByCec, int standbyAction) {
         assertRunOnServiceThread();
-        if (!mService.isControlEnabled() || initiatedByCec) {
+        if (!mService.isControlEnabled() || initiatedByCec || !mAutoTvOff) {
             return;
         }
         switch (standbyAction) {
             case HdmiControlService.STANDBY_SCREEN_OFF:
-                if (mAutoTvOff) {
-                    mService.sendCecCommand(
-                            HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
-                }
+                mService.sendCecCommand(
+                        HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
                 break;
             case HdmiControlService.STANDBY_SHUTDOWN:
                 // ACTION_SHUTDOWN is taken as a signal to power off all the devices.
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index 0b201710..537df81 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -21,6 +21,7 @@
 import android.os.SystemClock;
 import android.util.Pair;
 import android.util.Slog;
+import android.util.Log;
 
 import java.util.HashMap;
 
@@ -42,6 +43,7 @@
     // Logging duration for same error message.
     private static final long ERROR_LOG_DURATTION_MILLIS = 20 * 1000;  // 20s
 
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
 
     private static final ThreadLocal<HdmiLogger> sLogger = new ThreadLocal<>();
@@ -83,10 +85,9 @@
     }
 
     private void debugInternal(String logMessage) {
-        if (true || IS_USER_BUILD) {
-            return;
+        if (DEBUG) {
+            Slog.d(TAG, logMessage);
         }
-        Slog.d(TAG, logMessage);
     }
 
     private static final String toLogString(String logMessage, Object[] objs) {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index e73beaa..c7c765bb 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -200,6 +200,7 @@
     private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
             int policyFlags);
+    private static native void nativeToggleCapsLock(long ptr, int deviceId);
     private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
     private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
     private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
@@ -2279,5 +2280,10 @@
             mHandler.obtainMessage(MSG_INPUT_METHOD_SUBTYPE_CHANGED, userId, 0, someArgs)
                     .sendToTarget();
         }
+
+        @Override
+        public void toggleCapsLock(int deviceId) {
+            nativeToggleCapsLock(mPtr, deviceId);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index fa8620f..b235002 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -304,7 +304,7 @@
 
             toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
             if (toCancel != null) {
-                cancelJobImpl(toCancel);
+                cancelJobImpl(toCancel, jobStatus);
             }
             startTrackingJob(jobStatus, toCancel);
         }
@@ -331,7 +331,7 @@
         }
         for (int i=0; i<jobsForUser.size(); i++) {
             JobStatus toRemove = jobsForUser.get(i);
-            cancelJobImpl(toRemove);
+            cancelJobImpl(toRemove, null);
         }
     }
 
@@ -360,7 +360,7 @@
                 } catch (RemoteException e) {
                 }
             }
-            cancelJobImpl(toRemove);
+            cancelJobImpl(toRemove, null);
         }
     }
 
@@ -377,13 +377,13 @@
             toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
         }
         if (toCancel != null) {
-            cancelJobImpl(toCancel);
+            cancelJobImpl(toCancel, null);
         }
     }
 
-    private void cancelJobImpl(JobStatus cancelled) {
+    private void cancelJobImpl(JobStatus cancelled, JobStatus incomingJob) {
         if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
-        stopTrackingJob(cancelled, true /* writeBack */);
+        stopTrackingJob(cancelled, incomingJob, true /* writeBack */);
         synchronized (mLock) {
             // Remove from pending queue.
             mPendingJobs.remove(cancelled);
@@ -549,7 +549,7 @@
                 for (int i = 0; i < mControllers.size(); i++) {
                     StateController controller = mControllers.get(i);
                     if (update) {
-                        controller.maybeStopTrackingJobLocked(jobStatus, true);
+                        controller.maybeStopTrackingJobLocked(jobStatus, null, true);
                     }
                     controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
                 }
@@ -561,14 +561,15 @@
      * Called when we want to remove a JobStatus object that we've finished executing. Returns the
      * object removed.
      */
-    private boolean stopTrackingJob(JobStatus jobStatus, boolean writeBack) {
+    private boolean stopTrackingJob(JobStatus jobStatus, JobStatus incomingJob,
+            boolean writeBack) {
         synchronized (mLock) {
             // Remove from store as well as controllers.
             final boolean removed = mJobs.remove(jobStatus, writeBack);
             if (removed && mReadyToRock) {
                 for (int i=0; i<mControllers.size(); i++) {
                     StateController controller = mControllers.get(i);
-                    controller.maybeStopTrackingJobLocked(jobStatus, false);
+                    controller.maybeStopTrackingJobLocked(jobStatus, incomingJob, false);
                 }
             }
             return removed;
@@ -696,7 +697,7 @@
         }
         // Do not write back immediately if this is a periodic job. The job may get lost if system
         // shuts down before it is added back.
-        if (!stopTrackingJob(jobStatus, !jobStatus.getJob().isPeriodic())) {
+        if (!stopTrackingJob(jobStatus, null, !jobStatus.getJob().isPeriodic())) {
             if (DEBUG) {
                 Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
             }
@@ -780,7 +781,7 @@
                     }
                     break;
                 case MSG_STOP_JOB:
-                    cancelJobImpl((JobStatus)message.obj);
+                    cancelJobImpl((JobStatus)message.obj, null);
                     break;
             }
             maybeRunPendingJobsH();
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index 2114fc3..d8490d4 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -77,7 +77,7 @@
     }
 
     @Override
-    public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
+    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
         mTrackedTasks.remove(jobStatus);
     }
 
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index ac9f425..0772364 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -87,7 +87,7 @@
     }
 
     @Override
-    public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
+    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) {
         if (taskStatus.hasChargingConstraint()) {
             mTrackedTasks.remove(taskStatus);
         }
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 6ef425a..5ad8189 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
+    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
         if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
             mTrackedJobs.remove(jobStatus);
         }
diff --git a/services/core/java/com/android/server/job/controllers/ContentObserverController.java b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
index c5cf30f..b2f1958 100644
--- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
@@ -84,17 +84,8 @@
             boolean havePendingUris = false;
             // If there is a previous job associated with the new job, propagate over
             // any pending content URI trigger reports.
-            if (lastJob != null && lastJob.contentObserverJobInstance != null
-                    && lastJob.contentObserverJobInstance
-                    != taskStatus.contentObserverJobInstance
-                    && lastJob.contentObserverJobInstance.mChangedAuthorities != null) {
+            if (taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
                 havePendingUris = true;
-                taskStatus.contentObserverJobInstance.mChangedAuthorities
-                        = lastJob.contentObserverJobInstance.mChangedAuthorities;
-                taskStatus.contentObserverJobInstance.mChangedUris
-                        = lastJob.contentObserverJobInstance.mChangedUris;
-                lastJob.contentObserverJobInstance.mChangedAuthorities = null;
-                lastJob.contentObserverJobInstance.mChangedUris = null;
             }
             // If we have previously reported changed authorities/uris, then we failed
             // to complete the job with them so will re-record them to report again.
@@ -138,15 +129,34 @@
     }
 
     @Override
-    public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
+    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob,
+            boolean forUpdate) {
         if (taskStatus.hasContentTriggerConstraint()) {
-            if (!forUpdate) {
-                // We won't do this reset if being called for an update, because
-                // we know it will be immediately followed by maybeStartTrackingJobLocked...
-                // and we don't want to lose any content changes in-between.
-                if (taskStatus.contentObserverJobInstance != null) {
-                    taskStatus.contentObserverJobInstance.detach();
-                    taskStatus.contentObserverJobInstance = null;
+            if (taskStatus.contentObserverJobInstance != null) {
+                if (incomingJob != null && taskStatus.contentObserverJobInstance != null
+                        && taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
+                    // We are stopping this job, but it is going to be replaced by this given
+                    // incoming job.  We want to propagate our state over to it, so we don't
+                    // lose any content changes that had happend since the last one started.
+                    // If there is a previous job associated with the new job, propagate over
+                    // any pending content URI trigger reports.
+                    if (incomingJob.contentObserverJobInstance == null) {
+                        incomingJob.contentObserverJobInstance = new JobInstance(incomingJob);
+                    }
+                    incomingJob.contentObserverJobInstance.mChangedAuthorities
+                            = taskStatus.contentObserverJobInstance.mChangedAuthorities;
+                    incomingJob.contentObserverJobInstance.mChangedUris
+                            = taskStatus.contentObserverJobInstance.mChangedUris;
+                    taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
+                    taskStatus.contentObserverJobInstance.mChangedUris = null;
+                } else {
+                    // We won't do this reset if being called for an update, because
+                    // we know it will be immediately followed by maybeStartTrackingJobLocked...
+                    // and we don't want to lose any content changes in-between.
+                    if (taskStatus.contentObserverJobInstance != null) {
+                        taskStatus.contentObserverJobInstance.detach();
+                        taskStatus.contentObserverJobInstance = null;
+                    }
                 }
             }
             mTrackedTasks.remove(taskStatus);
diff --git a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index d2ef6a2..64887e8 100644
--- a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -166,7 +166,7 @@
     }
 
     @Override
-    public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
+    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
         mTrackedTasks.remove(jobStatus);
     }
 
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index d9eb45c..50aa882 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -75,7 +75,7 @@
     }
 
     @Override
-    public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
+    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) {
         mTrackedTasks.remove(taskStatus);
     }
 
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index ac7f4c3..0139039 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -56,7 +56,8 @@
     /**
      * Remove task - this will happen if the task is cancelled, completed, etc.
      */
-    public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate);
+    public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
+            boolean forUpdate);
     /**
      * Called when a new job is being created to reschedule an old failed job.
      */
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
index 3543249..ab6768e 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -74,7 +74,7 @@
     @Override
     public void maybeStartTrackingJobLocked(JobStatus job, JobStatus lastJob) {
         if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) {
-            maybeStopTrackingJobLocked(job, false);
+            maybeStopTrackingJobLocked(job, null, false);
             boolean isInsert = false;
             ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
             while (it.hasPrevious()) {
@@ -101,7 +101,7 @@
      * Really an == comparison should be enough, but why play with fate? We'll do <=.
      */
     @Override
-    public void maybeStopTrackingJobLocked(JobStatus job, boolean forUpdate) {
+    public void maybeStopTrackingJobLocked(JobStatus job, JobStatus incomingJob, boolean forUpdate) {
         if (mTrackedJobs.remove(job)) {
             checkExpiredDelaysAndResetAlarm();
             checkExpiredDeadlinesAndResetAlarm();
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index 257c7da..5953dde 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -18,12 +18,17 @@
 
 import com.android.server.SystemService;
 import com.android.server.vr.VrManagerInternal;
+import com.android.server.vr.VrManagerService;
 import com.android.server.vr.VrStateListener;
 
 import android.content.Context;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
+import android.os.RemoteException;
 import android.os.Trace;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
 import android.util.Slog;
 
 public class LightsService extends SystemService {
@@ -164,13 +169,19 @@
     @Override
     public void onBootPhase(int phase) {
         if (phase == PHASE_SYSTEM_SERVICES_READY) {
-            getLocalService(VrManagerInternal.class).registerListener(mVrStateListener);
+            IVrManager vrManager =
+                    (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
+            try {
+                vrManager.registerListener(mVrStateCallbacks);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+            }
         }
     }
 
-    private final VrStateListener mVrStateListener = new VrStateListener() {
+    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
         @Override
-        public void onVrStateChanged(boolean enabled) {
+        public void onVrStateChanged(boolean enabled) throws RemoteException {
             LightImpl l = mLights[LightsManager.LIGHT_ID_BACKLIGHT];
             if (enabled) {
                 if (DEBUG) Slog.v(TAG, "VR mode enabled, setting brightness to low persistence");
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index e08fad4..6b916be 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -39,7 +39,7 @@
 import android.location.IGnssStatusListener;
 import android.location.IGnssStatusProvider;
 import android.location.GnssMeasurementsEvent;
-import android.location.GnssNavigationMessageEvent;
+import android.location.GnssNavigationMessage;
 import android.location.IGpsGeofenceHardware;
 import android.location.ILocationManager;
 import android.location.INetInitiatedListener;
@@ -1662,7 +1662,7 @@
     /**
      * called from native code - GPS navigation message callback
      */
-    private void reportNavigationMessage(GnssNavigationMessageEvent event) {
+    private void reportNavigationMessage(GnssNavigationMessage event) {
         mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
     }
 
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index 734a8d4..caf1d6c 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -64,15 +64,15 @@
         int status;
         switch (result) {
             case RESULT_SUCCESS:
-                status = GnssMeasurementsEvent.STATUS_READY;
+                status = GnssMeasurementsEvent.Callback.STATUS_READY;
                 break;
             case RESULT_NOT_AVAILABLE:
             case RESULT_NOT_SUPPORTED:
             case RESULT_INTERNAL_ERROR:
-                status = GnssMeasurementsEvent.STATUS_NOT_SUPPORTED;
+                status = GnssMeasurementsEvent.Callback.STATUS_NOT_SUPPORTED;
                 break;
             case RESULT_GPS_LOCATION_DISABLED:
-                status = GnssMeasurementsEvent.STATUS_GNSS_LOCATION_DISABLED;
+                status = GnssMeasurementsEvent.Callback.STATUS_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 fdef31f..8d21928 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -16,7 +16,7 @@
 
 package com.android.server.location;
 
-import android.location.GnssNavigationMessageEvent;
+import android.location.GnssNavigationMessage;
 import android.location.IGnssNavigationMessageListener;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -37,7 +37,7 @@
         super(handler, TAG);
     }
 
-    public void onNavigationMessageAvailable(final GnssNavigationMessageEvent event) {
+    public void onNavigationMessageAvailable(final GnssNavigationMessage event) {
         ListenerOperation<IGnssNavigationMessageListener> operation =
                 new ListenerOperation<IGnssNavigationMessageListener>() {
                     @Override
@@ -65,16 +65,15 @@
         int status;
         switch (result) {
             case RESULT_SUCCESS:
-                status = GnssNavigationMessageEvent.STATUS_READY;
+                status = GnssNavigationMessage.Callback.STATUS_READY;
                 break;
             case RESULT_NOT_AVAILABLE:
             case RESULT_NOT_SUPPORTED:
             case RESULT_INTERNAL_ERROR:
-                status = GnssNavigationMessageEvent.STATUS_NOT_SUPPORTED;
+                status = GnssNavigationMessage.Callback.STATUS_NOT_SUPPORTED;
                 break;
             case RESULT_GPS_LOCATION_DISABLED:
-                status = GnssNavigationMessageEvent
-                        .STATUS_GNSS_LOCATION_DISABLED;
+                status = GnssNavigationMessage.Callback.STATUS_LOCATION_DISABLED;
                 break;
             case RESULT_UNKNOWN:
                 return null;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index 9cfb590..d339f69 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -24,7 +24,6 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -35,7 +34,6 @@
 import android.net.NetworkTemplate;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
-import android.os.Binder;
 import android.os.RemoteException;
 import android.os.ShellCommand;
 import android.util.Log;
@@ -88,12 +86,10 @@
         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");
         pw.println("    Gets the global restrict background usage status.");
-        pw.println("  list metered-networks [BOOLEAN]");
-        pw.println("    Lists all non-mobile networks and whether they are metered or not.");
+        pw.println("  list wifi-networks [BOOLEAN]");
+        pw.println("    Lists all saved wifi networks and whether they are metered or not.");
         pw.println("    If a boolean argument is passed, filters just the metered (or unmetered)");
         pw.println("    networks.");
         pw.println("  list restrict-background-whitelist");
@@ -105,7 +101,7 @@
         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("    Toggles whether the given wi-fi network is metered.");
         pw.println("  set restrict-background BOOLEAN");
         pw.println("    Sets the global restrict background usage status.");
     }
@@ -118,8 +114,6 @@
             return -1;
         }
         switch(type) {
-            case "metered-network":
-                return getMeteredWifiNetwork();
             case "restrict-background":
                 return getRestrictBackground();
         }
@@ -152,8 +146,8 @@
             return -1;
         }
         switch(type) {
-            case "metered-networks":
-                return listMeteredWifiNetworks();
+            case "wifi-networks":
+                return listWifiNetworks();
             case "restrict-background-whitelist":
                 return listRestrictBackgroundWhitelist();
             case "restrict-background-blacklist":
@@ -284,7 +278,7 @@
         return 0;
     }
 
-    private int listMeteredWifiNetworks() throws RemoteException {
+    private int listWifiNetworks() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         final String arg = getNextArg();
         final Boolean filter = arg == null ? null : Boolean.valueOf(arg);
@@ -299,23 +293,6 @@
         return 0;
     }
 
-    private int getMeteredWifiNetwork() throws RemoteException {
-        final PrintWriter pw = getOutPrintWriter();
-        final String id = getNextArg();
-        if (id == null) {
-            pw.println("Error: didn't specify ID");
-            return -1;
-        }
-        final List<NetworkPolicy> policies = getWifiPolicies();
-        for (NetworkPolicy policy: policies) {
-            if (id.equals(getNetworkId(policy))) {
-                pw.println(policy.metered);
-                return 0;
-            }
-        }
-        return 0;
-    }
-
     private int setMeteredWifiNetwork() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         final String id = getNextArg();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 022b10f..99c41ea 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -120,6 +120,7 @@
 import android.widget.Toast;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
@@ -226,7 +227,7 @@
     private VrManagerInternal mVrManagerInternal;
 
     final IBinder mForegroundToken = new Binder();
-    private WorkerHandler mHandler;
+    private Handler mHandler;
     private final HandlerThread mRankingThread = new HandlerThread("ranker",
             Process.THREAD_PRIORITY_BACKGROUND);
 
@@ -572,33 +573,9 @@
         public void clearEffects() {
             synchronized (mNotificationList) {
                 if (DBG) Slog.d(TAG, "clearEffects");
-
-                // sound
-                mSoundNotificationKey = null;
-
-                long identity = Binder.clearCallingIdentity();
-                try {
-                    final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
-                    if (player != null) {
-                        player.stopAsync();
-                    }
-                } catch (RemoteException e) {
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-
-                // vibrate
-                mVibrateNotificationKey = null;
-                identity = Binder.clearCallingIdentity();
-                try {
-                    mVibrator.cancel();
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-
-                // light
-                mLights.clear();
-                updateLightsLocked();
+                clearSoundLocked();
+                clearVibrateLocked();
+                clearLightsLocked();
             }
         }
 
@@ -658,6 +635,36 @@
         }
     };
 
+    private void clearSoundLocked() {
+        mSoundNotificationKey = null;
+        long identity = Binder.clearCallingIdentity();
+        try {
+            final IRingtonePlayer player = mAudioManager.getRingtonePlayer();
+            if (player != null) {
+                player.stopAsync();
+            }
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private void clearVibrateLocked() {
+        mVibrateNotificationKey = null;
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mVibrator.cancel();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private void clearLightsLocked() {
+        // light
+        mLights.clear();
+        updateLightsLocked();
+    }
+
     private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -764,10 +771,9 @@
                     cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle,
                             REASON_USER_STOPPED, null);
                 }
-            } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED)) {
-                boolean inQuietMode = intent.getBooleanExtra(Intent.EXTRA_QUIET_MODE, false);
+            } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
                 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
-                if (inQuietMode && userHandle >= 0) {
+                if (userHandle >= 0) {
                     cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle,
                             REASON_PROFILE_TURNED_OFF, null);
                 }
@@ -863,6 +869,26 @@
         super(context);
     }
 
+    @VisibleForTesting
+    void setAudioManager(AudioManager audioMananger) {
+        mAudioManager = audioMananger;
+    }
+
+    @VisibleForTesting
+    void setVibrator(Vibrator vibrator) {
+        mVibrator = vibrator;
+    }
+
+    @VisibleForTesting
+    void setSystemReady(boolean systemReady) {
+        mSystemReady = systemReady;
+    }
+
+    @VisibleForTesting
+    void setHandler(Handler handler) {
+        mHandler = handler;
+    }
+
     @Override
     public void onStart() {
         Resources resources = getContext().getResources();
@@ -981,7 +1007,7 @@
         filter.addAction(Intent.ACTION_USER_ADDED);
         filter.addAction(Intent.ACTION_USER_REMOVED);
         filter.addAction(Intent.ACTION_USER_UNLOCKED);
-        filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
         getContext().registerReceiver(mIntentReceiver, filter);
 
         IntentFilter pkgFilter = new IntentFilter();
@@ -2492,12 +2518,14 @@
         return false;
     }
 
-    private void buzzBeepBlinkLocked(NotificationRecord record) {
+    @VisibleForTesting
+    void buzzBeepBlinkLocked(NotificationRecord record) {
         boolean buzz = false;
         boolean beep = false;
         boolean blink = false;
 
         final Notification notification = record.sbn.getNotification();
+        final String key = record.getKey();
 
         // Should this notification make noise, vibe, or use the LED?
         final boolean aboveThreshold = record.getImportance() >= IMPORTANCE_DEFAULT;
@@ -2521,9 +2549,15 @@
         if (disableEffects != null) {
             ZenLog.traceDisableEffects(record, disableEffects);
         }
+
+        // Remember if this notification already owns the notification channels.
+        boolean wasBeep = key != null && key.equals(mSoundNotificationKey);
+        boolean wasBuzz = key != null && key.equals(mVibrateNotificationKey);
+
+        // These are set inside the conditional if the notification is allowed to make noise.
+        boolean hasValidVibrate = false;
+        boolean hasValidSound = false;
         if (disableEffects == null
-                && (!(record.isUpdate
-                    && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                 && (record.getUserId() == UserHandle.USER_ALL ||
                     record.getUserId() == currentUser ||
                     mUserProfiles.isCurrentProfile(record.getUserId()))
@@ -2532,10 +2566,6 @@
                 && mAudioManager != null) {
             if (DBG) Slog.v(TAG, "Interrupting!");
 
-            sendAccessibilityEvent(notification, record.sbn.getPackageName());
-
-            // sound
-
             // should we use the default notification sound? (indicated either by
             // DEFAULT_SOUND or because notification.sound is pointing at
             // Settings.System.NOTIFICATION_SOUND)
@@ -2545,8 +2575,6 @@
                                    .equals(notification.sound);
 
             Uri soundUri = null;
-            boolean hasValidSound = false;
-
             if (useDefaultSound) {
                 soundUri = Settings.System.DEFAULT_NOTIFICATION_URI;
 
@@ -2559,88 +2587,105 @@
                 hasValidSound = (soundUri != null);
             }
 
-            if (hasValidSound) {
-                boolean looping =
-                        (notification.flags & Notification.FLAG_INSISTENT) != 0;
-                AudioAttributes audioAttributes = audioAttributesForNotification(notification);
-                mSoundNotificationKey = record.getKey();
-                // do not play notifications if stream volume is 0 (typically because
-                // ringer mode is silent) or if there is a user of exclusive audio focus
-                if ((mAudioManager.getStreamVolume(
-                        AudioAttributes.toLegacyStreamType(audioAttributes)) != 0)
-                            && !mAudioManager.isAudioFocusExclusive()) {
-                    final long identity = Binder.clearCallingIdentity();
-                    try {
-                        final IRingtonePlayer player =
-                                mAudioManager.getRingtonePlayer();
-                        if (player != null) {
-                            if (DBG) Slog.v(TAG, "Playing sound " + soundUri
-                                    + " with attributes " + audioAttributes);
-                            player.playAsync(soundUri, record.sbn.getUser(), looping,
-                                    audioAttributes);
-                            beep = true;
-                        }
-                    } catch (RemoteException e) {
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
-                    }
-                }
-            }
-
-            // vibrate
             // Does the notification want to specify its own vibration?
             final boolean hasCustomVibrate = notification.vibrate != null;
 
             // new in 4.2: if there was supposed to be a sound and we're in vibrate
             // mode, and no other vibration is specified, we fall back to vibration
             final boolean convertSoundToVibration =
-                       !hasCustomVibrate
-                    && hasValidSound
-                    && (mAudioManager.getRingerModeInternal()
-                               == AudioManager.RINGER_MODE_VIBRATE);
+                    !hasCustomVibrate
+                            && hasValidSound
+                            && (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE);
 
             // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.
             final boolean useDefaultVibrate =
                     (notification.defaults & Notification.DEFAULT_VIBRATE) != 0;
 
-            if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate)
-                    && !(mAudioManager.getRingerModeInternal()
-                            == AudioManager.RINGER_MODE_SILENT)) {
-                mVibrateNotificationKey = record.getKey();
+            hasValidVibrate = useDefaultVibrate || convertSoundToVibration ||
+                    hasCustomVibrate;
 
-                if (useDefaultVibrate || convertSoundToVibration) {
-                    // Escalate privileges so we can use the vibrator even if the
-                    // notifying app does not have the VIBRATE permission.
-                    long identity = Binder.clearCallingIdentity();
-                    try {
-                        mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
-                            useDefaultVibrate ? mDefaultVibrationPattern
-                                : mFallbackVibrationPattern,
-                            ((notification.flags & Notification.FLAG_INSISTENT) != 0)
-                                ? 0: -1, audioAttributesForNotification(notification));
-                        buzz = true;
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
+            // We can alert, and we're allowed to alert, but if the developer asked us to only do
+            // it once, and we already have, then don't.
+            if (!(record.isUpdate
+                    && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)) {
+
+                sendAccessibilityEvent(notification, record.sbn.getPackageName());
+
+                if (hasValidSound) {
+                    boolean looping =
+                            (notification.flags & Notification.FLAG_INSISTENT) != 0;
+                    AudioAttributes audioAttributes = audioAttributesForNotification(notification);
+                    mSoundNotificationKey = key;
+                    // do not play notifications if stream volume is 0 (typically because
+                    // ringer mode is silent) or if there is a user of exclusive audio focus
+                    if ((mAudioManager.getStreamVolume(
+                            AudioAttributes.toLegacyStreamType(audioAttributes)) != 0)
+                            && !mAudioManager.isAudioFocusExclusive()) {
+                        final long identity = Binder.clearCallingIdentity();
+                        try {
+                            final IRingtonePlayer player =
+                                    mAudioManager.getRingtonePlayer();
+                            if (player != null) {
+                                if (DBG) Slog.v(TAG, "Playing sound " + soundUri
+                                        + " with attributes " + audioAttributes);
+                                player.playAsync(soundUri, record.sbn.getUser(), looping,
+                                        audioAttributes);
+                                beep = true;
+                            }
+                        } catch (RemoteException e) {
+                        } finally {
+                            Binder.restoreCallingIdentity(identity);
+                        }
                     }
-                } else if (notification.vibrate.length > 1) {
-                    // If you want your own vibration pattern, you need the VIBRATE
-                    // permission
-                    mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
-                            notification.vibrate,
-                        ((notification.flags & Notification.FLAG_INSISTENT) != 0)
-                                ? 0: -1, audioAttributesForNotification(notification));
-                    buzz = true;
+                }
+
+                if (hasValidVibrate && !(mAudioManager.getRingerModeInternal()
+                        == AudioManager.RINGER_MODE_SILENT)) {
+                    mVibrateNotificationKey = key;
+
+                    if (useDefaultVibrate || convertSoundToVibration) {
+                        // Escalate privileges so we can use the vibrator even if the
+                        // notifying app does not have the VIBRATE permission.
+                        long identity = Binder.clearCallingIdentity();
+                        try {
+                            mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
+                                    useDefaultVibrate ? mDefaultVibrationPattern
+                                            : mFallbackVibrationPattern,
+                                    ((notification.flags & Notification.FLAG_INSISTENT) != 0)
+                                            ? 0: -1, audioAttributesForNotification(notification));
+                            buzz = true;
+                        } finally {
+                            Binder.restoreCallingIdentity(identity);
+                        }
+                    } else if (notification.vibrate.length > 1) {
+                        // If you want your own vibration pattern, you need the VIBRATE
+                        // permission
+                        mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
+                                notification.vibrate,
+                                ((notification.flags & Notification.FLAG_INSISTENT) != 0)
+                                        ? 0: -1, audioAttributesForNotification(notification));
+                        buzz = true;
+                    }
                 }
             }
+
+        }
+        // If a notification is updated to remove the actively playing sound or vibrate,
+        // cancel that feedback now
+        if (wasBeep && !hasValidSound) {
+            clearSoundLocked();
+        }
+        if (wasBuzz && !hasValidVibrate) {
+            clearVibrateLocked();
         }
 
         // light
         // release the light
-        boolean wasShowLights = mLights.remove(record.getKey());
+        boolean wasShowLights = mLights.remove(key);
         if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThreshold
                 && ((record.getSuppressedVisualEffects()
                 & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) == 0)) {
-            mLights.add(record.getKey());
+            mLights.add(key);
             updateLightsLocked();
             if (mUseAttentionLight) {
                 mAttentionLight.pulse();
@@ -2654,7 +2699,7 @@
                     & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) != 0)) {
                 if (DBG) Slog.v(TAG, "Suppressed SystemUI from triggering screen on");
             } else {
-                EventLogTags.writeNotificationAlert(record.getKey(),
+                EventLogTags.writeNotificationAlert(key,
                         buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
                 mHandler.post(mBuzzBeepBlinked);
             }
@@ -2852,9 +2897,10 @@
     }
 
     private void scheduleSendRankingUpdate() {
-        mHandler.removeMessages(MESSAGE_SEND_RANKING_UPDATE);
-        Message m = Message.obtain(mHandler, MESSAGE_SEND_RANKING_UPDATE);
-        mHandler.sendMessage(m);
+        if (!mHandler.hasMessages(MESSAGE_SEND_RANKING_UPDATE)) {
+            Message m = Message.obtain(mHandler, MESSAGE_SEND_RANKING_UPDATE);
+            mHandler.sendMessage(m);
+        }
     }
 
     private void handleSendRankingUpdate() {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 13a96ae..098b39e 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -247,10 +247,8 @@
             }
 
             // SetupWizard
-            Intent setupIntent = new Intent(Intent.ACTION_MAIN);
-            setupIntent.addCategory(Intent.CATEGORY_SETUP_WIZARD);
-            PackageParser.Package setupPackage = getDefaultSystemHandlerActivityPackageLPr(
-                    setupIntent, userId);
+            PackageParser.Package setupPackage = getSystemPackageLPr(
+                    mService.mSetupWizardPackage);
             if (setupPackage != null
                     && doesPackageSupportRuntimePermissions(setupPackage)) {
                 grantRuntimePermissionsLPw(setupPackage, PHONE_PERMISSIONS, userId);
@@ -597,6 +595,16 @@
                 grantRuntimePermissionsLPw(emergencyInfoPckg, PHONE_PERMISSIONS, true, userId);
             }
 
+            // NFC Tag viewer
+            Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW);
+            nfcTagIntent.setType("vnd.android.cursor.item/ndef_msg");
+            PackageParser.Package nfcTagPkg = getDefaultSystemHandlerActivityPackageLPr(
+                    nfcTagIntent, userId);
+            if (nfcTagPkg != null
+                    && doesPackageSupportRuntimePermissions(nfcTagPkg)) {
+                grantRuntimePermissionsLPw(nfcTagPkg, CONTACTS_PERMISSIONS, false, userId);
+                grantRuntimePermissionsLPw(nfcTagPkg, PHONE_PERMISSIONS, false, userId);
+            }
             mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
         }
     }
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 7c71fbc..4c18e15 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -60,6 +60,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -77,7 +78,6 @@
 
     @Override
     public void onStart() {
-        Binder.LOG_RUNTIME_EXCEPTION = true;
         publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl);
     }
 
@@ -121,6 +121,21 @@
             return getCallingUid();
         }
 
+        final int injectCallingUserId() {
+            return UserHandle.getUserId(injectBinderCallingUid());
+        }
+
+        @VisibleForTesting
+        long injectClearCallingIdentity() {
+            return Binder.clearCallingIdentity();
+        }
+
+        // Injection point.
+        @VisibleForTesting
+        void injectRestoreCallingIdentity(long token) {
+            Binder.restoreCallingIdentity(token);
+        }
+
         private int getCallingUserId() {
             return UserHandle.getUserId(injectBinderCallingUid());
         }
@@ -197,14 +212,13 @@
         /**
          * Checks if the caller is in the same group as the userToCheck.
          */
-        @VisibleForTesting // We override it in unit tests
-        void ensureInUserProfiles(UserHandle userToCheck, String message) {
-            final int callingUserId = UserHandle.getCallingUserId();
+        private void ensureInUserProfiles(UserHandle userToCheck, String message) {
+            final int callingUserId = injectCallingUserId();
             final int targetUserId = userToCheck.getIdentifier();
 
             if (targetUserId == callingUserId) return;
 
-            long ident = Binder.clearCallingIdentity();
+            long ident = injectClearCallingIdentity();
             try {
                 UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
                 UserInfo targetUserInfo = mUm.getUserInfo(targetUserId);
@@ -214,7 +228,7 @@
                     throw new SecurityException(message);
                 }
             } finally {
-                Binder.restoreCallingIdentity(ident);
+                injectRestoreCallingIdentity(ident);
             }
         }
 
@@ -239,12 +253,12 @@
          * Checks if the user is enabled.
          */
         private boolean isUserEnabled(UserHandle user) {
-            long ident = Binder.clearCallingIdentity();
+            long ident = injectClearCallingIdentity();
             try {
                 UserInfo targetUserInfo = mUm.getUserInfo(user.getIdentifier());
                 return targetUserInfo != null && targetUserInfo.isEnabled();
             } finally {
-                Binder.restoreCallingIdentity(ident);
+                injectRestoreCallingIdentity(ident);
             }
         }
 
@@ -345,6 +359,9 @@
         public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
                 String packageName, ComponentName componentName, int flags, UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
+            if (!isUserEnabled(user)) {
+                return new ParceledListSlice<>(new ArrayList(0));
+            }
 
             return new ParceledListSlice<>(
                     mShortcutServiceInternal.getShortcuts(getCallingUserId(),
@@ -356,6 +373,9 @@
         public ParceledListSlice getShortcutInfo(String callingPackage, String packageName,
                 List<String> ids, UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
+            if (!isUserEnabled(user)) {
+                return new ParceledListSlice<>(new ArrayList(0));
+            }
 
             return new ParceledListSlice<>(
                     mShortcutServiceInternal.getShortcutInfo(getCallingUserId(),
@@ -366,6 +386,10 @@
         public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
                 UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
+            if (!isUserEnabled(user)) {
+                throw new IllegalStateException("Cannot pin shortcuts for disabled profile "
+                        + user);
+            }
 
             mShortcutServiceInternal.pinShortcuts(getCallingUserId(),
                     callingPackage, packageName, ids, user.getIdentifier());
@@ -375,6 +399,9 @@
         public int getShortcutIconResId(String callingPackage, ShortcutInfo shortcut,
                 UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
+            if (!isUserEnabled(user)) {
+                return 0;
+            }
 
             return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(),
                     callingPackage, shortcut, user.getIdentifier());
@@ -384,6 +411,9 @@
         public ParcelFileDescriptor getShortcutIconFd(String callingPackage, ShortcutInfo shortcut,
                 UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
+            if (!isUserEnabled(user)) {
+                return null;
+            }
 
             return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
                     callingPackage, shortcut, user.getIdentifier());
@@ -402,6 +432,11 @@
             verifyCallingPackage(callingPackage);
             ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
 
+            if (!isUserEnabled(user)) {
+                throw new IllegalStateException("Cannot start a shortcut for disabled profile "
+                        + user);
+            }
+
             // Even without the permission, pinned shortcuts are always launchable.
             if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
                     callingPackage, packageName, shortcutId, user.getIdentifier())) {
@@ -530,13 +565,13 @@
 
         /** Checks if user is a profile of or same as listeningUser.
          * and the user is enabled. */
-        boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser,
+        private boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser,
                 String debugMsg) {
             if (user.getIdentifier() == listeningUser.getIdentifier()) {
                 if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg);
                 return true;
             }
-            long ident = Binder.clearCallingIdentity();
+            long ident = injectClearCallingIdentity();
             try {
                 UserInfo userInfo = mUm.getUserInfo(user.getIdentifier());
                 UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier());
@@ -557,7 +592,7 @@
                     return true;
                 }
             } finally {
-                Binder.restoreCallingIdentity(ident);
+                injectRestoreCallingIdentity(ident);
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ef53905..6cdc40f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -81,6 +81,7 @@
 import java.io.FileDescriptor;
 import java.io.FileFilter;
 import java.io.IOException;
+import java.security.cert.Certificate;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -151,6 +152,7 @@
     private String mPackageName;
     private int mVersionCode;
     private Signature[] mSignatures;
+    private Certificate[][] mCertificates;
 
     /**
      * Path to the validated base APK for this session, which may point at an
@@ -633,7 +635,7 @@
 
         mRelinquished = true;
         mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
-                installerPackageName, installerUid, user);
+                installerPackageName, installerUid, user, mCertificates);
     }
 
     /**
@@ -695,6 +697,7 @@
             }
             if (mSignatures == null) {
                 mSignatures = apk.signatures;
+                mCertificates = apk.certificates;
             }
 
             assertApkConsistent(String.valueOf(addedFile), apk);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 58592ff..a6fce51 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -64,6 +64,7 @@
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_FACTORY_ONLY;
 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;
@@ -75,6 +76,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.pm.PackageParser.PARSE_IS_PRIVILEGED;
 import static android.content.pm.PackageParser.isApkFile;
+import static android.os.Process.FIRST_APPLICATION_UID;
 import static android.os.Process.PACKAGE_INFO_GID;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
@@ -108,12 +110,14 @@
 import android.app.admin.IDevicePolicyManager;
 import android.app.admin.SecurityLog;
 import android.app.backup.IBackupManager;
+import android.app.usage.UsageStatsManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IntentFilter.AuthorityEntry;
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
 import android.content.ServiceConnection;
@@ -146,6 +150,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.ActivityIntentInfo;
+import android.content.pm.PackageParser.IntentInfo;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.PackageStats;
@@ -273,6 +278,7 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
+import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.text.SimpleDateFormat;
@@ -319,6 +325,7 @@
     private static final boolean DEBUG_INTENT_MATCHING = false;
     private static final boolean DEBUG_PACKAGE_SCANNING = false;
     private static final boolean DEBUG_VERIFY = false;
+    private static final boolean DEBUG_FILTERS = false;
 
     // Debug output for dexopting. This is shared between PackageManagerService, OtaDexoptService
     // and PackageDexOptimizer. All these classes have their own flag to allow switching a single
@@ -444,6 +451,18 @@
         sBrowserIntent.setData(Uri.parse("http:"));
     }
 
+    /**
+     * The set of all protected actions [i.e. those actions for which a high priority
+     * intent filter is disallowed].
+     */
+    private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>();
+    static {
+        PROTECTED_ACTIONS.add(Intent.ACTION_SEND);
+        PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO);
+        PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE);
+        PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
+    }
+
     // Compilation reasons.
     public static final int REASON_FIRST_BOOT = 0;
     public static final int REASON_BOOT = 1;
@@ -530,6 +549,20 @@
      * are package location.
      */
     final private ArrayMap<String, File> mExpectingBetter = new ArrayMap<>();
+    /**
+     * Tracks high priority intent filters for protected actions. During boot, certain
+     * filter actions are protected and should never be allowed to have a high priority
+     * intent filter for them. However, there is one, and only one exception -- the
+     * setup wizard. It must be able to define a high priority intent filter for these
+     * actions to ensure there are no escapes from the wizard. We need to delay processing
+     * of these during boot as we need to look at all of the system packages in order
+     * to know which component is the setup wizard.
+     */
+    private final List<PackageParser.ActivityIntentInfo> mProtectedFilters = new ArrayList<>();
+    /**
+     * Whether or not processing protected filters should be deferred.
+     */
+    private boolean mDeferProtectedFilters = true;
 
     /**
      * Tracks existing system packages prior to receiving an OTA. Keys are package name.
@@ -1034,6 +1067,7 @@
 
     final @Nullable String mRequiredVerifierPackage;
     final @Nullable String mRequiredInstallerPackage;
+    final @Nullable String mSetupWizardPackage;
 
     private final PackageUsage mPackageUsage = new PackageUsage();
 
@@ -2427,6 +2461,36 @@
             }
             mExpectingBetter.clear();
 
+            // Resolve protected action filters. Only the setup wizard is allowed to
+            // have a high priority filter for these actions.
+            mSetupWizardPackage = getSetupWizardPackageName();
+            if (mProtectedFilters.size() > 0) {
+                if (DEBUG_FILTERS && mSetupWizardPackage == null) {
+                    Slog.i(TAG, "No setup wizard;"
+                        + " All protected intents capped to priority 0");
+                }
+                for (ActivityIntentInfo filter : mProtectedFilters) {
+                    if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
+                        if (DEBUG_FILTERS) {
+                            Slog.i(TAG, "Found setup wizard;"
+                                + " allow priority " + filter.getPriority() + ";"
+                                + " package: " + filter.activity.info.packageName
+                                + " activity: " + filter.activity.className
+                                + " priority: " + filter.getPriority());
+                        }
+                        // skip setup wizard; allow it to keep the high priority filter
+                        continue;
+                    }
+                    Slog.w(TAG, "Protected action; cap priority to 0;"
+                            + " package: " + filter.activity.info.packageName
+                            + " activity: " + filter.activity.className
+                            + " origPrio: " + filter.getPriority());
+                    filter.setPriority(0);
+                }
+            }
+            mDeferProtectedFilters = false;
+            mProtectedFilters.clear();
+
             // Now that we know all of the shared libraries, update all clients to have
             // the correct library paths.
             updateAllSharedLibrariesLPw();
@@ -2886,12 +2950,15 @@
         return cur;
     }
 
-    PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
+    private PackageInfo generatePackageInfo(PackageSetting ps, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        final PackageSetting ps = (PackageSetting) p.mExtras;
         if (ps == null) {
             return null;
         }
+        final PackageParser.Package p = ps.pkg;
+        if (p == null) {
+            return null;
+        }
 
         final PermissionsState permissionsState = ps.getPermissionsState();
 
@@ -2961,14 +3028,28 @@
                 false /* requireFullPermission */, false /* checkShell */, "get package info");
         // reader
         synchronized (mPackages) {
-            PackageParser.Package p = mPackages.get(packageName);
+            final boolean matchFactoryOnly = (flags & MATCH_FACTORY_ONLY) != 0;
+            PackageParser.Package p = null;
+            if (matchFactoryOnly) {
+                final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
+                if (ps != null) {
+                    return generatePackageInfo(ps, flags, userId);
+                }
+            }
+            if (p == null) {
+                p = mPackages.get(packageName);
+                if (matchFactoryOnly && !isSystemApp(p)) {
+                    return null;
+                }
+            }
             if (DEBUG_PACKAGE_INFO)
                 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
             if (p != null) {
-                return generatePackageInfo(p, flags, userId);
+                return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
             }
-            if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
-                return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
+            if (!matchFactoryOnly && (flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
+                final PackageSetting ps = mSettings.mPackages.get(packageName);
+                return generatePackageInfo(ps, flags, userId);
             }
         }
         return null;
@@ -3129,8 +3210,7 @@
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps != null) {
             if (ps.pkg == null) {
-                PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName,
-                        flags, userId);
+                final PackageInfo pInfo = generatePackageInfo(ps, flags, userId);
                 if (pInfo != null) {
                     return pInfo.applicationInfo;
                 }
@@ -3142,31 +3222,6 @@
         return null;
     }
 
-    private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
-            int userId) {
-        if (!sUserManager.exists(userId)) return null;
-        PackageSetting ps = mSettings.mPackages.get(packageName);
-        if (ps != null) {
-            PackageParser.Package pkg = ps.pkg;
-            if (pkg == null) {
-                if ((flags & MATCH_UNINSTALLED_PACKAGES) == 0) {
-                    return null;
-                }
-                // Only data remains, so we aren't worried about code paths
-                pkg = new PackageParser.Package(packageName);
-                pkg.applicationInfo.packageName = packageName;
-                pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
-                pkg.applicationInfo.privateFlags = ps.pkgPrivateFlags;
-                pkg.applicationInfo.uid = ps.appId;
-                pkg.applicationInfo.initForUser(userId);
-                pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString;
-                pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString;
-            }
-            return generatePackageInfo(pkg, flags, userId);
-        }
-        return null;
-    }
-
     @Override
     public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
@@ -5915,11 +5970,11 @@
             if (listUninstalled) {
                 list = new ArrayList<PackageInfo>(mSettings.mPackages.size());
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    PackageInfo pi;
+                    final PackageInfo pi;
                     if (ps.pkg != null) {
-                        pi = generatePackageInfo(ps.pkg, flags, userId);
+                        pi = generatePackageInfo(ps, flags, userId);
                     } else {
-                        pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
+                        pi = generatePackageInfo(ps, flags, userId);
                     }
                     if (pi != null) {
                         list.add(pi);
@@ -5928,7 +5983,8 @@
             } else {
                 list = new ArrayList<PackageInfo>(mPackages.size());
                 for (PackageParser.Package p : mPackages.values()) {
-                    PackageInfo pi = generatePackageInfo(p, flags, userId);
+                    final PackageInfo pi =
+                            generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
                     if (pi != null) {
                         list.add(pi);
                     }
@@ -5955,11 +6011,11 @@
         if (numMatch == 0) {
             return;
         }
-        PackageInfo pi;
+        final PackageInfo pi;
         if (ps.pkg != null) {
-            pi = generatePackageInfo(ps.pkg, flags, userId);
+            pi = generatePackageInfo(ps, flags, userId);
         } else {
-            pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
+            pi = generatePackageInfo(ps, flags, userId);
         }
         // The above might return null in cases of uninstalled apps or install-state
         // skew across users/profiles.
@@ -6951,25 +7007,46 @@
             pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
         }
 
+        UsageStatsManager usageMgr =
+                (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE);
+
         int curr = 0;
         int total = pkgs.size();
         for (PackageParser.Package pkg : pkgs) {
             curr++;
 
+            if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
+                if (DEBUG_DEXOPT) {
+                    Log.i(TAG, "Skipping update of of non-optimizable app " + pkg.packageName);
+                }
+                continue;
+            }
+
+            if (!causeFirstBoot && usageMgr.isAppInactive(pkg.packageName)) {
+                if (DEBUG_DEXOPT) {
+                    Log.i(TAG, "Skipping update of of idle app " + pkg.packageName);
+                }
+                continue;
+            }
+
             if (DEBUG_DEXOPT) {
                 Log.i(TAG, "Extracting app " + curr + " of " + total + ": " + pkg.packageName);
             }
 
-            if (PackageDexOptimizer.canOptimizePackage(pkg)) {
-                // If the cache was pruned, any compiled odex files will likely be out of date
-                // and would have to be patched (would be SELF_PATCHOAT, which is deprecated).
-                // Instead, force the extraction in this case.
-                performDexOpt(pkg.packageName,
-                        null /* instructionSet */,
-                        false /* checkProfiles */,
-                        causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
-                        false /* force */);
+            if (!isFirstBoot()) {
+                try {
+                    ActivityManagerNative.getDefault().showBootMessage(
+                            mContext.getResources().getString(R.string.android_upgrading_apk,
+                                    curr, total), true);
+                } catch (RemoteException e) {
+                }
             }
+
+            performDexOpt(pkg.packageName,
+                    null /* instructionSet */,
+                    false /* checkProfiles */,
+                    causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
+                    false /* force */);
         }
     }
 
@@ -9704,6 +9781,12 @@
                 // is granted only if it was already granted.
                 allowed = origPermissions.hasInstallPermission(perm);
             }
+            if (!allowed && (bp.protectionLevel & PermissionInfo.PROTECTION_FLAG_SETUP) != 0
+                    && pkg.packageName.equals(mSetupWizardPackage)) {
+                // If this permission is to be granted to the system setup wizard and
+                // this app is a setup wizard, then it gets the permission.
+                allowed = true;
+            }
         }
         return allowed;
     }
@@ -9761,8 +9844,314 @@
             return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
         }
 
+        /**
+         * Finds a privileged activity that matches the specified activity names.
+         */
+        private PackageParser.Activity findMatchingActivity(
+                List<PackageParser.Activity> activityList, ActivityInfo activityInfo) {
+            for (PackageParser.Activity sysActivity : activityList) {
+                if (sysActivity.info.name.equals(activityInfo.name)) {
+                    return sysActivity;
+                }
+                if (sysActivity.info.name.equals(activityInfo.targetActivity)) {
+                    return sysActivity;
+                }
+                if (sysActivity.info.targetActivity != null) {
+                    if (sysActivity.info.targetActivity.equals(activityInfo.name)) {
+                        return sysActivity;
+                    }
+                    if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) {
+                        return sysActivity;
+                    }
+                }
+            }
+            return null;
+        }
+
+        public class IterGenerator<E> {
+            public Iterator<E> generate(ActivityIntentInfo info) {
+                return null;
+            }
+        }
+
+        public class ActionIterGenerator extends IterGenerator<String> {
+            @Override
+            public Iterator<String> generate(ActivityIntentInfo info) {
+                return info.actionsIterator();
+            }
+        }
+
+        public class CategoriesIterGenerator extends IterGenerator<String> {
+            @Override
+            public Iterator<String> generate(ActivityIntentInfo info) {
+                return info.categoriesIterator();
+            }
+        }
+
+        public class SchemesIterGenerator extends IterGenerator<String> {
+            @Override
+            public Iterator<String> generate(ActivityIntentInfo info) {
+                return info.schemesIterator();
+            }
+        }
+
+        public class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
+            @Override
+            public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) {
+                return info.authoritiesIterator();
+            }
+        }
+
+        /**
+         * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
+         * MODIFIED. Do not pass in a list that should not be changed.
+         */
+        private <T> void getIntentListSubset(List<ActivityIntentInfo> intentList,
+                IterGenerator<T> generator, Iterator<T> searchIterator) {
+            // loop through the set of actions; every one must be found in the intent filter
+            while (searchIterator.hasNext()) {
+                // we must have at least one filter in the list to consider a match
+                if (intentList.size() == 0) {
+                    break;
+                }
+
+                final T searchAction = searchIterator.next();
+
+                // loop through the set of intent filters
+                final Iterator<ActivityIntentInfo> intentIter = intentList.iterator();
+                while (intentIter.hasNext()) {
+                    final ActivityIntentInfo intentInfo = intentIter.next();
+                    boolean selectionFound = false;
+
+                    // loop through the intent filter's selection criteria; at least one
+                    // of them must match the searched criteria
+                    final Iterator<T> intentSelectionIter = generator.generate(intentInfo);
+                    while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
+                        final T intentSelection = intentSelectionIter.next();
+                        if (intentSelection != null && intentSelection.equals(searchAction)) {
+                            selectionFound = true;
+                            break;
+                        }
+                    }
+
+                    // the selection criteria wasn't found in this filter's set; this filter
+                    // is not a potential match
+                    if (!selectionFound) {
+                        intentIter.remove();
+                    }
+                }
+            }
+        }
+
+        private boolean isProtectedAction(ActivityIntentInfo filter) {
+            final Iterator<String> actionsIter = filter.actionsIterator();
+            while (actionsIter != null && actionsIter.hasNext()) {
+                final String filterAction = actionsIter.next();
+                if (PROTECTED_ACTIONS.contains(filterAction)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Adjusts the priority of the given intent filter according to policy.
+         * <p>
+         * <ul>
+         * <li>The priority for non privileged applications is capped to '0'</li>
+         * <li>The priority for protected actions on privileged applications is capped to '0'</li>
+         * <li>The priority for unbundled updates to privileged applications is capped to the
+         *      priority defined on the system partition</li>
+         * </ul>
+         * <p>
+         * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
+         * allowed to obtain any priority on any action.
+         */
+        private void adjustPriority(
+                List<PackageParser.Activity> systemActivities, ActivityIntentInfo intent) {
+            // nothing to do; priority is fine as-is
+            if (intent.getPriority() <= 0) {
+                return;
+            }
+
+            final ActivityInfo activityInfo = intent.activity.info;
+            final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
+
+            final boolean privilegedApp =
+                    ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
+            if (!privilegedApp) {
+                // non-privileged applications can never define a priority >0
+                Slog.w(TAG, "Non-privileged app; cap priority to 0;"
+                        + " package: " + applicationInfo.packageName
+                        + " activity: " + intent.activity.className
+                        + " origPrio: " + intent.getPriority());
+                intent.setPriority(0);
+                return;
+            }
+
+            if (systemActivities == null) {
+                // the system package is not disabled; we're parsing the system partition
+                if (isProtectedAction(intent)) {
+                    if (mDeferProtectedFilters) {
+                        // We can't deal with these just yet. No component should ever obtain a
+                        // >0 priority for a protected actions, with ONE exception -- the setup
+                        // wizard. The setup wizard, however, cannot be known until we're able to
+                        // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
+                        // until all intent filters have been processed. Chicken, meet egg.
+                        // Let the filter temporarily have a high priority and rectify the
+                        // priorities after all system packages have been scanned.
+                        mProtectedFilters.add(intent);
+                        if (DEBUG_FILTERS) {
+                            Slog.i(TAG, "Protected action; save for later;"
+                                    + " package: " + applicationInfo.packageName
+                                    + " activity: " + intent.activity.className
+                                    + " origPrio: " + intent.getPriority());
+                        }
+                        return;
+                    } else {
+                        if (DEBUG_FILTERS && mSetupWizardPackage == null) {
+                            Slog.i(TAG, "No setup wizard;"
+                                + " All protected intents capped to priority 0");
+                        }
+                        if (intent.activity.info.packageName.equals(mSetupWizardPackage)) {
+                            if (DEBUG_FILTERS) {
+                                Slog.i(TAG, "Found setup wizard;"
+                                    + " allow priority " + intent.getPriority() + ";"
+                                    + " package: " + intent.activity.info.packageName
+                                    + " activity: " + intent.activity.className
+                                    + " priority: " + intent.getPriority());
+                            }
+                            // setup wizard gets whatever it wants
+                            return;
+                        }
+                        Slog.w(TAG, "Protected action; cap priority to 0;"
+                                + " package: " + intent.activity.info.packageName
+                                + " activity: " + intent.activity.className
+                                + " origPrio: " + intent.getPriority());
+                        intent.setPriority(0);
+                        return;
+                    }
+                }
+                // privileged apps on the system image get whatever priority they request
+                return;
+            }
+
+            // privileged app unbundled update ... try to find the same activity
+            final PackageParser.Activity foundActivity =
+                    findMatchingActivity(systemActivities, activityInfo);
+            if (foundActivity == null) {
+                // this is a new activity; it cannot obtain >0 priority
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "New activity; cap priority to 0;"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(0);
+                return;
+            }
+
+            // found activity, now check for filter equivalence
+
+            // a shallow copy is enough; we modify the list, not its contents
+            final List<ActivityIntentInfo> intentListCopy =
+                    new ArrayList<>(foundActivity.intents);
+            final List<ActivityIntentInfo> foundFilters = findFilters(intent);
+
+            // find matching action subsets
+            final Iterator<String> actionsIterator = intent.actionsIterator();
+            if (actionsIterator != null) {
+                getIntentListSubset(
+                        intentListCopy, new ActionIterGenerator(), actionsIterator);
+                if (intentListCopy.size() == 0) {
+                    // no more intents to match; we're not equivalent
+                    if (DEBUG_FILTERS) {
+                        Slog.i(TAG, "Mismatched action; cap priority to 0;"
+                                + " package: " + applicationInfo.packageName
+                                + " activity: " + intent.activity.className
+                                + " origPrio: " + intent.getPriority());
+                    }
+                    intent.setPriority(0);
+                    return;
+                }
+            }
+
+            // find matching category subsets
+            final Iterator<String> categoriesIterator = intent.categoriesIterator();
+            if (categoriesIterator != null) {
+                getIntentListSubset(intentListCopy, new CategoriesIterGenerator(),
+                        categoriesIterator);
+                if (intentListCopy.size() == 0) {
+                    // no more intents to match; we're not equivalent
+                    if (DEBUG_FILTERS) {
+                        Slog.i(TAG, "Mismatched category; cap priority to 0;"
+                                + " package: " + applicationInfo.packageName
+                                + " activity: " + intent.activity.className
+                                + " origPrio: " + intent.getPriority());
+                    }
+                    intent.setPriority(0);
+                    return;
+                }
+            }
+
+            // find matching schemes subsets
+            final Iterator<String> schemesIterator = intent.schemesIterator();
+            if (schemesIterator != null) {
+                getIntentListSubset(intentListCopy, new SchemesIterGenerator(),
+                        schemesIterator);
+                if (intentListCopy.size() == 0) {
+                    // no more intents to match; we're not equivalent
+                    if (DEBUG_FILTERS) {
+                        Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
+                                + " package: " + applicationInfo.packageName
+                                + " activity: " + intent.activity.className
+                                + " origPrio: " + intent.getPriority());
+                    }
+                    intent.setPriority(0);
+                    return;
+                }
+            }
+
+            // find matching authorities subsets
+            final Iterator<IntentFilter.AuthorityEntry>
+                    authoritiesIterator = intent.authoritiesIterator();
+            if (authoritiesIterator != null) {
+                getIntentListSubset(intentListCopy,
+                        new AuthoritiesIterGenerator(),
+                        authoritiesIterator);
+                if (intentListCopy.size() == 0) {
+                    // no more intents to match; we're not equivalent
+                    if (DEBUG_FILTERS) {
+                        Slog.i(TAG, "Mismatched authority; cap priority to 0;"
+                                + " package: " + applicationInfo.packageName
+                                + " activity: " + intent.activity.className
+                                + " origPrio: " + intent.getPriority());
+                    }
+                    intent.setPriority(0);
+                    return;
+                }
+            }
+
+            // we found matching filter(s); app gets the max priority of all intents
+            int cappedPriority = 0;
+            for (int i = intentListCopy.size() - 1; i >= 0; --i) {
+                cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority());
+            }
+            if (intent.getPriority() > cappedPriority) {
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Found matching filter(s);"
+                            + " cap priority to " + cappedPriority + ";"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(cappedPriority);
+                return;
+            }
+            // all this for nothing; the requested priority was <= what was on the system
+        }
+
         public final void addActivity(PackageParser.Activity a, String type) {
-            final boolean systemApp = a.info.applicationInfo.isSystemApp();
             mActivities.put(a.getComponentName(), a);
             if (DEBUG_SHOW_INFO)
                 Log.v(
@@ -9773,10 +10162,12 @@
             final int NI = a.intents.size();
             for (int j=0; j<NI; j++) {
                 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
-                if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
-                    intent.setPriority(0);
-                    Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
-                            + a.className + " with priority > 0, forcing to 0");
+                if ("activity".equals(type)) {
+                    final PackageSetting ps =
+                            mSettings.getDisabledSystemPkgLPr(intent.activity.info.packageName);
+                    final List<PackageParser.Activity> systemActivities =
+                            ps != null && ps.pkg != null ? ps.pkg.activities : null;
+                    adjustPriority(systemActivities, intent);
                 }
                 if (DEBUG_SHOW_INFO) {
                     Log.v(TAG, "    IntentFilter:");
@@ -9926,18 +10317,6 @@
             out.println();
         }
 
-//        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
-//            final Iterator<ResolveInfo> i = resolveInfoList.iterator();
-//            final List<ResolveInfo> retList = Lists.newArrayList();
-//            while (i.hasNext()) {
-//                final ResolveInfo resolveInfo = i.next();
-//                if (isEnabledLP(resolveInfo.activityInfo)) {
-//                    retList.add(resolveInfo);
-//                }
-//            }
-//            return retList;
-//        }
-
         // Keys are String (activity class name), values are Activity.
         private final ArrayMap<ComponentName, PackageParser.Activity> mActivities
                 = new ArrayMap<ComponentName, PackageParser.Activity>();
@@ -10599,7 +10978,8 @@
                 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*/);
+                null /*packageAbiOverride*/, null /*grantedPermissions*/,
+                null /*certificates*/);
         params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
@@ -10613,7 +10993,8 @@
 
     void installStage(String packageName, File stagedDir, String stagedCid,
             IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
-            String installerPackageName, int installerUid, UserHandle user) {
+            String installerPackageName, int installerUid, UserHandle user,
+            Certificate[][] certificates) {
         if (DEBUG_EPHEMERAL) {
             if ((sessionParams.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
                 Slog.d(TAG, "Ephemeral install of " + packageName);
@@ -10634,7 +11015,7 @@
         final InstallParams params = new InstallParams(origin, null, observer,
                 sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
                 verificationInfo, user, sessionParams.abiOverride,
-                sessionParams.grantedRuntimePermissions);
+                sessionParams.grantedRuntimePermissions, certificates);
         params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
@@ -11289,8 +11670,8 @@
      * @return the current "allow unknown sources" setting
      */
     private int getUnknownSourcesSettings() {
-        return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
-                android.provider.Settings.Global.INSTALL_NON_MARKET_APPS,
+        return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
+                android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS,
                 -1);
     }
 
@@ -11729,11 +12110,12 @@
         final String packageAbiOverride;
         final String[] grantedRuntimePermissions;
         final VerificationInfo verificationInfo;
+        final Certificate[][] certificates;
 
         InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
                 int installFlags, String installerPackageName, String volumeUuid,
                 VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
-                String[] grantedPermissions) {
+                String[] grantedPermissions, Certificate[][] certificates) {
             super(user);
             this.origin = origin;
             this.move = move;
@@ -11744,6 +12126,7 @@
             this.verificationInfo = verificationInfo;
             this.packageAbiOverride = packageAbiOverride;
             this.grantedRuntimePermissions = grantedPermissions;
+            this.certificates = certificates;
         }
 
         @Override
@@ -11778,8 +12161,23 @@
                     // predecessor. As a security measure, this is permited only if this is not a
                     // version downgrade or if the predecessor package is marked as debuggable and
                     // a downgrade is explicitly requested.
-                    if (((dataOwnerPkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0)
-                            || ((installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0)) {
+                    //
+                    // On debuggable platform builds, downgrades are permitted even for
+                    // non-debuggable packages to make testing easier. Debuggable platform builds do
+                    // not offer security guarantees and thus it's OK to disable some security
+                    // mechanisms to make debugging/testing easier on those builds. However, even on
+                    // debuggable builds downgrades of packages are permitted only if requested via
+                    // installFlags. This is because we aim to keep the behavior of debuggable
+                    // platform builds as close as possible to the behavior of non-debuggable
+                    // platform builds.
+                    final boolean downgradeRequested =
+                            (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
+                    final boolean packageDebuggable =
+                                (dataOwnerPkg.applicationInfo.flags
+                                        & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+                    final boolean downgradePermitted =
+                            (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable));
+                    if (!downgradePermitted) {
                         try {
                             checkDowngrade(dataOwnerPkg, pkgLite);
                         } catch (PackageManagerException e) {
@@ -12197,6 +12595,7 @@
         /** If non-null, drop an async trace when the install completes */
         final String traceMethod;
         final int traceCookie;
+        final Certificate[][] certificates;
 
         // The list of instruction sets supported by this app. This is currently
         // only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -12207,7 +12606,7 @@
                 int installFlags, String installerPackageName, String volumeUuid,
                 UserHandle user, String[] instructionSets,
                 String abiOverride, String[] installGrantPermissions,
-                String traceMethod, int traceCookie) {
+                String traceMethod, int traceCookie, Certificate[][] certificates) {
             this.origin = origin;
             this.move = move;
             this.installFlags = installFlags;
@@ -12220,6 +12619,7 @@
             this.installGrantPermissions = installGrantPermissions;
             this.traceMethod = traceMethod;
             this.traceCookie = traceCookie;
+            this.certificates = certificates;
         }
 
         abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
@@ -12254,8 +12654,6 @@
          * Called after the source arguments are copied. This is used mostly for
          * MoveParams when it needs to read the source file to put it in the
          * destination.
-         *
-         * @return
          */
         int doPostCopy(int uid) {
             return PackageManager.INSTALL_SUCCEEDED;
@@ -12314,9 +12712,9 @@
         FileInstallArgs(InstallParams params) {
             super(params.origin, params.move, params.observer, params.installFlags,
                     params.installerPackageName, params.volumeUuid,
-                    params.getUser(), null /* instruction sets */, params.packageAbiOverride,
+                    params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
                     params.grantedRuntimePermissions,
-                    params.traceMethod, params.traceCookie);
+                    params.traceMethod, params.traceCookie, params.certificates);
             if (isFwdLocked()) {
                 throw new IllegalArgumentException("Forward locking only supported in ASEC");
             }
@@ -12325,7 +12723,7 @@
         /** Existing install */
         FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
             super(OriginInfo.fromNothing(), null, null, 0, null, null, null, instructionSets,
-                    null, null, null, 0);
+                    null, null, null, 0, null /*certificates*/);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
         }
@@ -12550,15 +12948,15 @@
                     params.installerPackageName, params.volumeUuid,
                     params.getUser(), null /* instruction sets */, params.packageAbiOverride,
                     params.grantedRuntimePermissions,
-                    params.traceMethod, params.traceCookie);
+                    params.traceMethod, params.traceCookie, params.certificates);
         }
 
         /** Existing install */
         AsecInstallArgs(String fullCodePath, String[] instructionSets,
                         boolean isExternal, boolean isForwardLocked) {
             super(OriginInfo.fromNothing(), null, null, (isExternal ? INSTALL_EXTERNAL : 0)
-                    | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
-                    instructionSets, null, null, null, 0);
+              | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+                    instructionSets, null, null, null, 0, null /*certificates*/);
             // Hackily pretend we're still looking at a full code path
             if (!fullCodePath.endsWith(RES_FILE_NAME)) {
                 fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath();
@@ -12574,8 +12972,8 @@
 
         AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
             super(OriginInfo.fromNothing(), null, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
-                    | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
-                    instructionSets, null, null, null, 0);
+              | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+                    instructionSets, null, null, null, 0, null /*certificates*/);
             this.cid = cid;
             setMountPath(PackageHelper.getSdDir(cid));
         }
@@ -12844,7 +13242,7 @@
                     params.installerPackageName, params.volumeUuid,
                     params.getUser(), null /* instruction sets */, params.packageAbiOverride,
                     params.grantedRuntimePermissions,
-                    params.traceMethod, params.traceCookie);
+                    params.traceMethod, params.traceCookie, params.certificates);
         }
 
         int copyApk(IMediaContainerService imcs, boolean temp) {
@@ -13882,14 +14280,22 @@
             }
         }
 
-        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
         try {
-            PackageParser.collectCertificates(pkg, parseFlags);
+            // either use what we've been given or parse directly from the APK
+            if (args.certificates != null) {
+                try {
+                    PackageParser.populateCertificates(pkg, args.certificates);
+                } catch (PackageParserException e) {
+                    // there was something wrong with the certificates we were given;
+                    // try to pull them from the APK
+                    PackageParser.collectCertificates(pkg, parseFlags);
+                }
+            } else {
+                PackageParser.collectCertificates(pkg, parseFlags);
+            }
         } catch (PackageParserException e) {
             res.setError("Failed collect during installPackageLI", e);
             return;
-        } finally {
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
 
         // Get rid of all references to package scan path via parser.
@@ -15501,17 +15907,14 @@
                 // Otherwise, reset the permission.
                 final int revokeResult = permissionsState.revokeRuntimePermission(bp, userId);
                 switch (revokeResult) {
-                    case PERMISSION_OPERATION_SUCCESS: {
-                        writeRuntimePermissions = true;
-                    } break;
-
+                    case PERMISSION_OPERATION_SUCCESS:
                     case PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
                         writeRuntimePermissions = true;
                         final int appId = ps.appId;
                         mHandler.post(new Runnable() {
                             @Override
                             public void run() {
-                                killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED);
+                                killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
                             }
                         });
                     } break;
@@ -16626,6 +17029,23 @@
                 set, comp, userId);
     }
 
+    private @Nullable String getSetupWizardPackageName() {
+        final Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_SETUP_WIZARD);
+
+        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
+                        | MATCH_DISABLED_COMPONENTS,
+                UserHandle.myUserId());
+        if (matches.size() == 1) {
+            return matches.get(0).getComponentInfo().packageName;
+        } else {
+            Slog.e(TAG, "There should probably be exactly one setup wizard; found " + matches.size()
+                    + ": matches=" + matches);
+            return null;
+        }
+    }
+
     @Override
     public void setApplicationEnabledSetting(String appPackageName,
             int newState, int flags, int userId, String callingPackage) {
@@ -18757,7 +19177,7 @@
         final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
         final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
                 installerPackageName, volumeUuid, null /*verificationInfo*/, user,
-                packageAbiOverride, null);
+                packageAbiOverride, null /*grantedPermissions*/, null /*certificates*/);
         params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
diff --git a/services/core/java/com/android/server/pm/ShortcutBackupAgent.java b/services/core/java/com/android/server/pm/ShortcutBackupAgent.java
deleted file mode 100644
index a0fbc37..0000000
--- a/services/core/java/com/android/server/pm/ShortcutBackupAgent.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.pm;
-
-import android.app.backup.BlobBackupHelper;
-
-public class ShortcutBackupAgent extends BlobBackupHelper {
-    private static final String TAG = "ShortcutBackupAgent";
-    private static final int BLOB_VERSION = 1;
-
-    public ShortcutBackupAgent(int currentBlobVersion, String... keys) {
-        super(currentBlobVersion, keys);
-    }
-
-    @Override
-    protected byte[] getBackupPayload(String key) {
-        throw new RuntimeException("not implemented yet"); // todo
-    }
-
-    @Override
-    protected void applyRestoredPayload(String key, byte[] payload) {
-        throw new RuntimeException("not implemented yet"); // todo
-    }
-}
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java
index 7699f30..c6d66fe 100644
--- a/services/core/java/com/android/server/pm/ShortcutLauncher.java
+++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java
@@ -20,6 +20,10 @@
 import android.content.pm.ShortcutInfo;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.ShortcutUser.PackageWithUser;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -27,6 +31,7 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -43,15 +48,16 @@
     private static final String ATTR_LAUNCHER_USER_ID = "launcher-user";
     private static final String ATTR_VALUE = "value";
     private static final String ATTR_PACKAGE_NAME = "package-name";
+    private static final String ATTR_PACKAGE_USER_ID = "package-user";
 
     private final int mOwnerUserId;
 
     /**
      * Package name -> IDs.
      */
-    final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
+    final private ArrayMap<PackageWithUser, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
 
-    public ShortcutLauncher(@UserIdInt int ownerUserId, @NonNull String packageName,
+    private ShortcutLauncher(@UserIdInt int ownerUserId, @NonNull String packageName,
             @UserIdInt int launcherUserId, ShortcutPackageInfo spi) {
         super(launcherUserId, packageName, spi != null ? spi : ShortcutPackageInfo.newEmpty());
         mOwnerUserId = ownerUserId;
@@ -59,7 +65,7 @@
 
     public ShortcutLauncher(@UserIdInt int ownerUserId, @NonNull String packageName,
             @UserIdInt int launcherUserId) {
-        this(launcherUserId, packageName, launcherUserId, null);
+        this(ownerUserId, packageName, launcherUserId, null);
     }
 
     @Override
@@ -67,16 +73,38 @@
         return mOwnerUserId;
     }
 
+    /**
+     * Called when the new package can't receive the backup, due to signature or version mismatch.
+     */
+    @Override
+    protected void onRestoreBlocked(ShortcutService s) {
+        final ArrayList<PackageWithUser> pinnedPackages =
+                new ArrayList<>(mPinnedShortcuts.keySet());
+        mPinnedShortcuts.clear();
+        for (int i = pinnedPackages.size() - 1; i >= 0; i--) {
+            final PackageWithUser pu = pinnedPackages.get(i);
+            s.getPackageShortcutsLocked(pu.packageName, pu.userId)
+                    .refreshPinnedFlags(s);
+        }
+    }
+
+    @Override
+    protected void onRestored(ShortcutService s) {
+        // Nothing to do.
+    }
+
     public void pinShortcuts(@NonNull ShortcutService s, @UserIdInt int packageUserId,
             @NonNull String packageName, @NonNull List<String> ids) {
         final ShortcutPackage packageShortcuts =
                 s.getPackageShortcutsLocked(packageName, packageUserId);
 
+        final PackageWithUser pu = PackageWithUser.of(packageUserId, packageName);
+
         final int idSize = ids.size();
         if (idSize == 0) {
-            mPinnedShortcuts.remove(packageName);
+            mPinnedShortcuts.remove(pu);
         } else {
-            final ArraySet<String> prevSet = mPinnedShortcuts.get(packageName);
+            final ArraySet<String> prevSet = mPinnedShortcuts.get(pu);
 
             // Pin shortcuts.  Make sure only pin the ones that were visible to the caller.
             // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
@@ -93,7 +121,7 @@
                     newSet.add(id);
                 }
             }
-            mPinnedShortcuts.put(packageName, newSet);
+            mPinnedShortcuts.put(pu, newSet);
         }
         packageShortcuts.refreshPinnedFlags(s);
     }
@@ -101,12 +129,13 @@
     /**
      * Return the pinned shortcut IDs for the publisher package.
      */
-    public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName) {
-        return mPinnedShortcuts.get(packageName);
+    public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName,
+            @UserIdInt int packageUserId) {
+        return mPinnedShortcuts.get(PackageWithUser.of(packageUserId, packageName));
     }
 
-    boolean cleanUpPackage(String packageName) {
-        return mPinnedShortcuts.remove(packageName) != null;
+    boolean cleanUpPackage(String packageName, @UserIdInt int packageUserId) {
+        return mPinnedShortcuts.remove(PackageWithUser.of(packageUserId, packageName)) != null;
     }
 
     /**
@@ -126,9 +155,15 @@
         getPackageInfo().saveToXml(out);
 
         for (int i = 0; i < size; i++) {
+            final PackageWithUser pu = mPinnedShortcuts.keyAt(i);
+
+            if (forBackup && (pu.userId != getOwnerUserId())) {
+                continue; // Target package on a different user, skip. (i.e. work profile)
+            }
+
             out.startTag(null, TAG_PACKAGE);
-            ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
-                    mPinnedShortcuts.keyAt(i));
+            ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, pu.packageName);
+            ShortcutService.writeAttr(out, ATTR_PACKAGE_USER_ID, pu.userId);
 
             final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
             final int idSize = ids.size();
@@ -157,8 +192,6 @@
         final ShortcutLauncher ret = new ShortcutLauncher(launcherUserId, launcherPackageName,
                 launcherUserId);
 
-        ShortcutPackageInfo spi = null;
-
         ArraySet<String> ids = null;
         final int outerDepth = parser.getDepth();
         int type;
@@ -172,13 +205,17 @@
             if (depth == outerDepth + 1) {
                 switch (tag) {
                     case ShortcutPackageInfo.TAG_ROOT:
-                        spi = ShortcutPackageInfo.loadFromXml(parser);
+                        ret.getPackageInfo().loadFromXml(parser, fromBackup);
                         continue;
                     case TAG_PACKAGE: {
                         final String packageName = ShortcutService.parseStringAttribute(parser,
                                 ATTR_PACKAGE_NAME);
+                        final int packageUserId = fromBackup ? ownerUserId
+                                : ShortcutService.parseIntAttribute(parser,
+                                ATTR_PACKAGE_USER_ID, ownerUserId);
                         ids = new ArraySet<>();
-                        ret.mPinnedShortcuts.put(packageName, ids);
+                        ret.mPinnedShortcuts.put(
+                                PackageWithUser.of(packageUserId, packageName), ids);
                         continue;
                     }
                 }
@@ -186,17 +223,17 @@
             if (depth == outerDepth + 2) {
                 switch (tag) {
                     case TAG_PIN: {
-                        ids.add(ShortcutService.parseStringAttribute(parser,
-                                ATTR_VALUE));
+                        if (ids == null) {
+                            Slog.w(TAG, TAG_PIN + " in invalid place");
+                        } else {
+                            ids.add(ShortcutService.parseStringAttribute(parser, ATTR_VALUE));
+                        }
                         continue;
                     }
                 }
             }
             ShortcutService.warnForInvalidTag(depth, tag);
         }
-        if (spi != null) {
-            ret.replacePackageInfo(spi);
-        }
         return ret;
     }
 
@@ -208,6 +245,8 @@
         pw.print(getPackageName());
         pw.print("  Package user: ");
         pw.print(getPackageUserId());
+        pw.print("  Owner user: ");
+        pw.print(getOwnerUserId());
         pw.println();
 
         getPackageInfo().dump(s, pw, prefix + "  ");
@@ -217,10 +256,14 @@
         for (int i = 0; i < size; i++) {
             pw.println();
 
+            final PackageWithUser pu = mPinnedShortcuts.keyAt(i);
+
             pw.print(prefix);
             pw.print("  ");
             pw.print("Package: ");
-            pw.println(mPinnedShortcuts.keyAt(i));
+            pw.print(pu.packageName);
+            pw.print("  User: ");
+            pw.println(pu.userId);
 
             final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
             final int idSize = ids.size();
@@ -233,4 +276,9 @@
             }
         }
     }
+
+    @VisibleForTesting
+    ArraySet<String> getAllPinnedShortcutsForTest(String packageName, int packageUserId) {
+        return new ArraySet<>(mPinnedShortcuts.get(PackageWithUser.of(packageUserId, packageName)));
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 5916202..1076a7a 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -26,6 +26,8 @@
 import android.util.ArraySet;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -34,6 +36,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.function.Predicate;
 
@@ -83,7 +86,7 @@
      */
     private long mLastResetTime;
 
-    public ShortcutPackage(int packageUserId, String packageName, ShortcutPackageInfo spi) {
+    private ShortcutPackage(int packageUserId, String packageName, ShortcutPackageInfo spi) {
         super(packageUserId, packageName, spi != null ? spi : ShortcutPackageInfo.newEmpty());
     }
 
@@ -97,6 +100,19 @@
         return getPackageUserId();
     }
 
+    @Override
+    protected void onRestoreBlocked(ShortcutService s) {
+        // Can't restore due to version/signature mismatch.  Remove all shortcuts.
+        mShortcuts.clear();
+    }
+
+    @Override
+    protected void onRestored(ShortcutService s) {
+        // Because some launchers may not have been restored (e.g. allowBackup=false),
+        // we need to re-calculate the pinned shortcuts.
+        refreshPinnedFlags(s);
+    }
+
     /**
      * Note this does *not* provide a correct view to the calling launcher.
      */
@@ -229,20 +245,26 @@
                 s.getUserShortcutsLocked(getPackageUserId()).getAllLaunchers();
 
         for (int l = launchers.size() - 1; l >= 0; l--) {
+            // Note even if a launcher that hasn't been installed can still pin shortcuts.
+
             final ShortcutLauncher launcherShortcuts = launchers.valueAt(l);
             final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds(
-                    getPackageName());
+                    getPackageName(), getPackageUserId());
 
             if (pinned == null || pinned.size() == 0) {
                 continue;
             }
             for (int i = pinned.size() - 1; i >= 0; i--) {
-                final ShortcutInfo si = mShortcuts.get(pinned.valueAt(i));
+                final String id = pinned.valueAt(i);
+                final ShortcutInfo si = mShortcuts.get(id);
                 if (si == null) {
-                    s.wtf("Shortcut not found");
-                } else {
-                    si.addFlags(ShortcutInfo.FLAG_PINNED);
+                    // This happens if a launcher pinned shortcuts from this package, then backup&
+                    // restored, but this package doesn't allow backing up.
+                    // In that case the launcher ends up having a dangling pinned shortcuts.
+                    // That's fine, when the launcher is restored, we'll fix it.
+                    continue;
                 }
+                si.addFlags(ShortcutInfo.FLAG_PINNED);
             }
         }
 
@@ -312,11 +334,15 @@
     public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result,
             @Nullable Predicate<ShortcutInfo> query, int cloneFlag,
             @Nullable String callingLauncher, int launcherUserId) {
+        if (getPackageInfo().isShadow()) {
+            // Restored and the app not installed yet, so don't return any.
+            return;
+        }
 
         // Set of pinned shortcuts by the calling launcher.
         final ArraySet<String> pinnedByCallerSet = (callingLauncher == null) ? null
-                : s.getLauncherShortcuts(callingLauncher, getPackageUserId(), launcherUserId)
-                    .getPinnedShortcutIds(getPackageName());
+                : s.getLauncherShortcutsLocked(callingLauncher, getPackageUserId(), launcherUserId)
+                    .getPinnedShortcutIds(getPackageName(), getPackageUserId());
 
         for (int i = 0; i < mShortcuts.size(); i++) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
@@ -328,7 +354,8 @@
                     || ((pinnedByCallerSet != null) && pinnedByCallerSet.contains(si.getId()));
             if (!si.isDynamic()) {
                 if (!si.isPinned()) {
-                    s.wtf("Shortcut not pinned here");
+                    s.wtf("Shortcut not pinned: package " + getPackageName()
+                            + ", user=" + getPackageUserId() + ", id=" + si.getId());
                     continue;
                 }
                 if (!isPinnedByCaller) {
@@ -479,7 +506,6 @@
                 ShortcutService.parseIntAttribute(parser, ATTR_CALL_COUNT);
         ret.mLastResetTime =
                 ShortcutService.parseLongAttribute(parser, ATTR_LAST_RESET);
-        ShortcutPackageInfo spi = null;
 
         final int outerDepth = parser.getDepth();
         int type;
@@ -493,7 +519,7 @@
             if (depth == outerDepth + 1) {
                 switch (tag) {
                     case ShortcutPackageInfo.TAG_ROOT:
-                        spi = ShortcutPackageInfo.loadFromXml(parser);
+                        ret.getPackageInfo().loadFromXml(parser, fromBackup);
                         continue;
                     case TAG_SHORTCUT:
                         final ShortcutInfo si = parseShortcut(parser, packageName);
@@ -505,9 +531,6 @@
             }
             ShortcutService.warnForInvalidTag(depth, tag);
         }
-        if (spi != null) {
-            ret.replacePackageInfo(spi);
-        }
         return ret;
     }
 
@@ -567,4 +590,9 @@
                 intentPersistableExtras, weight, extras, lastChangedTimestamp, flags,
                 iconRes, bitmapPath);
     }
+
+    @VisibleForTesting
+    List<ShortcutInfo> getAllShortcutsForTest() {
+        return new ArrayList<>(mShortcuts.values());
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
index 5f706b8..2c45890 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
@@ -67,10 +67,6 @@
         return mIsShadow;
     }
 
-    public boolean isInstalled() {
-        return !mIsShadow;
-    }
-
     public void setShadow(boolean shadow) {
         mIsShadow = shadow;
     }
@@ -79,14 +75,24 @@
         return mVersionCode;
     }
 
-    public boolean canRestoreTo(PackageInfo target) {
+    public boolean hasSignatures() {
+        return mSigHashes.size() > 0;
+    }
+
+    public boolean canRestoreTo(ShortcutService s, PackageInfo target) {
+        if (!s.shouldBackupApp(target)) {
+            // "allowBackup" was true when backed up, but now false.
+            Slog.w(TAG, "Can't restore: package no longer allows backup");
+            return false;
+        }
         if (target.versionCode < mVersionCode) {
-            Slog.w(TAG, String.format("Package current version %d < backed up version %d",
+            Slog.w(TAG, String.format(
+                    "Can't restore: package current version %d < backed up version %d",
                     target.versionCode, mVersionCode));
             return false;
         }
         if (!BackupUtils.signaturesMatch(mSigHashes, target)) {
-            Slog.w(TAG, "Package signature mismtach");
+            Slog.w(TAG, "Can't restore: Package signature mismatch");
             return false;
         }
         return true;
@@ -106,6 +112,11 @@
     }
 
     public void refresh(ShortcutService s, ShortcutPackageItem pkg) {
+        if (mIsShadow) {
+            s.wtf("Attempted to refresh package info for shadow package " + pkg.getPackageName()
+                    + ", user=" + pkg.getOwnerUserId());
+            return;
+        }
         // Note use mUserId here, rather than userId.
         final PackageInfo pi = s.getPackageInfoWithSignatures(
                 pkg.getPackageName(), pkg.getPackageUserId());
@@ -132,15 +143,17 @@
         out.endTag(null, TAG_ROOT);
     }
 
-    public static ShortcutPackageInfo loadFromXml(XmlPullParser parser)
+    public void loadFromXml(XmlPullParser parser, boolean fromBackup)
             throws IOException, XmlPullParserException {
 
         final int versionCode = ShortcutService.parseIntAttribute(parser, ATTR_VERSION);
-        final boolean shadow = ShortcutService.parseBooleanAttribute(parser, ATTR_SHADOW);
+
+        // When restoring from backup, it's always shadow.
+        final boolean shadow =
+                fromBackup || ShortcutService.parseBooleanAttribute(parser, ATTR_SHADOW);
 
         final ArrayList<byte[]> hashes = new ArrayList<>();
 
-
         final int outerDepth = parser.getDepth();
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -163,7 +176,11 @@
             }
             ShortcutService.warnForInvalidTag(depth, tag);
         }
-        return new ShortcutPackageInfo(versionCode, hashes, shadow);
+
+        // Successfully loaded; replace the feilds.
+        mVersionCode = versionCode;
+        mIsShadow = shadow;
+        mSigHashes = hashes;
     }
 
     public void dump(ShortcutService s, PrintWriter pw, String prefix) {
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index de2709d..f31dd17 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -16,6 +16,8 @@
 package com.android.server.pm;
 
 import android.annotation.NonNull;
+import android.content.pm.PackageInfo;
+import android.util.Slog;
 
 import com.android.internal.util.Preconditions;
 
@@ -25,10 +27,12 @@
 import java.io.IOException;
 
 abstract class ShortcutPackageItem {
+    private static final String TAG = ShortcutService.TAG;
+
     private final int mPackageUserId;
     private final String mPackageName;
 
-    private ShortcutPackageInfo mPackageInfo;
+    private final ShortcutPackageInfo mPackageInfo;
 
     protected ShortcutPackageItem(int packageUserId, @NonNull String packageName,
             @NonNull ShortcutPackageInfo packageInfo) {
@@ -61,25 +65,62 @@
         return mPackageInfo;
     }
 
-    /**
-     * Should be only used when loading from a file.o
-     */
-    protected void replacePackageInfo(@NonNull ShortcutPackageInfo packageInfo) {
-        mPackageInfo = Preconditions.checkNotNull(packageInfo);
-    }
-
     public void refreshPackageInfoAndSave(ShortcutService s) {
+        if (mPackageInfo.isShadow()) {
+            return; // Don't refresh for shadow user.
+        }
         mPackageInfo.refresh(s, this);
         s.scheduleSaveUser(getOwnerUserId());
     }
 
-    public void ensureNotShadowAndSave(ShortcutService s) {
-        if (mPackageInfo.isShadow()) {
-            mPackageInfo.setShadow(false);
-            s.scheduleSaveUser(getOwnerUserId());
+    public void attemptToRestoreIfNeededAndSave(ShortcutService s) {
+        if (!mPackageInfo.isShadow()) {
+            return; // Already installed, nothing to do.
         }
+        if (!s.isPackageInstalled(mPackageName, mPackageUserId)) {
+            if (ShortcutService.DEBUG) {
+                Slog.d(TAG, String.format("Package still not installed: %s user=%d",
+                        mPackageName, mPackageUserId));
+            }
+            return; // Not installed, no need to restore yet.
+        }
+        if (!mPackageInfo.hasSignatures()) {
+            s.wtf("Attempted to restore package " + mPackageName + ", user=" + mPackageUserId
+                    + " but signatures not found in the restore data.");
+            onRestoreBlocked(s);
+            return;
+        }
+
+        final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
+        if (!mPackageInfo.canRestoreTo(s, pi)) {
+            // Package is now installed, but can't restore.  Let the subclass do the cleanup.
+            onRestoreBlocked(s);
+            return;
+        }
+        if (ShortcutService.DEBUG) {
+            Slog.d(TAG, String.format("Restored package: %s/%d on user %d", mPackageName,
+                    mPackageUserId, getOwnerUserId()));
+        }
+
+        onRestored(s);
+
+        // Now the package is not shadow.
+        mPackageInfo.setShadow(false);
+
+        s.scheduleSaveUser(mPackageUserId);
     }
 
+    /**
+     * Called when the new package can't be restored because it has a lower version number
+     * or different signatures.
+     */
+    protected abstract void onRestoreBlocked(ShortcutService s);
+
+    /**
+     * Called when the new package is successfully restored.
+     */
+    protected abstract void onRestored(ShortcutService s);
+
     public abstract void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
             throws IOException, XmlPullParserException;
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 76a2dfa..5c1e7a8 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -46,6 +46,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
+import android.os.FileUtils;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
@@ -101,6 +102,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 /**
@@ -112,17 +114,16 @@
  *
  * - Scan and remove orphan bitmaps (just in case).
  *
- * - Backup & restore
- *
  * - Detect when already registered instances are passed to APIs again, which might break
  *   internal bitmap handling.
+ *
+ * - Add more call stats.
  */
 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
-    static final boolean ENABLE_DEBUG_COMMAND = true; // STOPSHIP if true
 
     @VisibleForTesting
     static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day
@@ -262,6 +263,26 @@
             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
             | PackageManager.MATCH_UNINSTALLED_PACKAGES;
 
+    // Stats
+    @VisibleForTesting
+    interface Stats {
+        int GET_DEFAULT_HOME = 0;
+        int GET_PACKAGE_INFO = 1;
+        int GET_PACKAGE_INFO_WITH_SIG = 2;
+        int GET_APPLICATION_INFO = 3;
+        int LAUNCHER_PERMISSION_CHECK = 4;
+
+        int COUNT = LAUNCHER_PERMISSION_CHECK + 1;
+    }
+
+    final Object mStatLock = new Object();
+
+    @GuardedBy("mStatLock")
+    private final int[] mCountStats = new int[Stats.COUNT];
+
+    @GuardedBy("mStatLock")
+    private final long[] mDurationStats = new long[Stats.COUNT];
+
     public ShortcutService(Context context) {
         this(context, BackgroundThread.get().getLooper());
     }
@@ -278,6 +299,13 @@
         mPackageMonitor.register(context, looper, UserHandle.ALL, /* externalStorage= */ false);
     }
 
+    void logDurationStat(int statId, long start) {
+        synchronized (mStatLock) {
+            mCountStats[statId]++;
+            mDurationStats[statId] += (System.currentTimeMillis() - start);
+        }
+    }
+
     /**
      * System service lifecycle.
      */
@@ -822,7 +850,7 @@
 
     @GuardedBy("mLock")
     @NonNull
-    boolean isUserLoadedLocked(@UserIdInt int userId) {
+    private boolean isUserLoadedLocked(@UserIdInt int userId) {
         return mUsers.get(userId) != null;
     }
 
@@ -841,19 +869,27 @@
         return userPackages;
     }
 
+    void forEachLoadedUserLocked(@NonNull Consumer<ShortcutUser> c) {
+        for (int i = mUsers.size() - 1; i >= 0; i--) {
+            c.accept(mUsers.valueAt(i));
+        }
+    }
+
     /** Return the per-user per-package state. */
     @GuardedBy("mLock")
     @NonNull
     ShortcutPackage getPackageShortcutsLocked(
             @NonNull String packageName, @UserIdInt int userId) {
-        return getUserShortcutsLocked(userId).getPackageShortcuts(packageName);
+        return getUserShortcutsLocked(userId).getPackageShortcuts(this, packageName);
     }
 
     @GuardedBy("mLock")
     @NonNull
-    ShortcutLauncher getLauncherShortcuts(
-            @NonNull String packageName, @UserIdInt int userId, @UserIdInt int launcherUserId) {
-        return getUserShortcutsLocked(userId).getLauncherShortcuts(packageName, launcherUserId);
+    ShortcutLauncher getLauncherShortcutsLocked(
+            @NonNull String packageName, @UserIdInt int ownerUserId,
+            @UserIdInt int launcherUserId) {
+        return getUserShortcutsLocked(ownerUserId)
+                .getLauncherShortcuts(this, packageName, launcherUserId);
     }
 
     // === Caller validation ===
@@ -1212,8 +1248,6 @@
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
 
-            ps.ensureNotShadowAndSave(this);
-
             // Throttling.
             if (!ps.tryApiCall(this)) {
                 return false;
@@ -1249,8 +1283,6 @@
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
 
-            ps.ensureNotShadowAndSave(this);
-
             // Throttling.
             if (!ps.tryApiCall(this)) {
                 return false;
@@ -1288,8 +1320,6 @@
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
 
-            ps.ensureNotShadowAndSave(this);
-
             // Throttling.
             if (!ps.tryApiCall(this)) {
                 return false;
@@ -1422,15 +1452,17 @@
     @VisibleForTesting
     boolean hasShortcutHostPermissionInner(@NonNull String callingPackage, int userId) {
         synchronized (mLock) {
-            long start = System.currentTimeMillis();
+            final long start = System.currentTimeMillis();
 
             final ShortcutUser user = getUserShortcutsLocked(userId);
 
             final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
 
             // Default launcher from package manager.
+            final long startGetHomeActivitiesAsUser = System.currentTimeMillis();
             final ComponentName defaultLauncher = injectPackageManagerInternal()
                     .getHomeActivitiesAsUser(allHomeCandidates, userId);
+            logDurationStat(Stats.GET_DEFAULT_HOME, startGetHomeActivitiesAsUser);
 
             ComponentName detected;
             if (defaultLauncher != null) {
@@ -1473,10 +1505,8 @@
                     lastPriority = ri.priority;
                 }
             }
-            final long end = System.currentTimeMillis();
-            if (DEBUG) {
-                Slog.v(TAG, String.format("hasShortcutPermission took %d ms", end - start));
-            }
+            logDurationStat(Stats.LAUNCHER_PERMISSION_CHECK, start);
+
             if (detected != null) {
                 if (DEBUG) {
                     Slog.v(TAG, "Detected launcher: " + detected);
@@ -1492,10 +1522,17 @@
 
     // === House keeping ===
 
+    /**
+     * Remove all the information associated with a package.  This will really remove all the
+     * information, including the restore information (i.e. it'll remove packages even if they're
+     * shadow).
+     */
     @VisibleForTesting
     void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) {
-
-        // TODO Don't remove shadow packages' information.
+        if (isPackageInstalled(packageName, packageUserId)) {
+            wtf("Package " + packageName + " is still installed for user " + packageUserId);
+            return;
+        }
 
         final boolean wasUserLoaded = isUserLoadedLocked(owningUserId);
 
@@ -1504,7 +1541,7 @@
 
         // First, remove the package from the package list (if the package is a publisher).
         if (packageUserId == owningUserId) {
-            if (mUser.getPackages().remove(packageName) != null) {
+            if (mUser.removePackage(packageName) != null) {
                 doNotify = true;
             }
         }
@@ -1515,12 +1552,12 @@
         // Then remove pinned shortcuts from all launchers.
         final ArrayMap<PackageWithUser, ShortcutLauncher> launchers = mUser.getAllLaunchers();
         for (int i = launchers.size() - 1; i >= 0; i--) {
-            launchers.valueAt(i).cleanUpPackage(packageName);
+            launchers.valueAt(i).cleanUpPackage(packageName, packageUserId);
         }
         // Now there may be orphan shortcuts because we removed pinned shortucts at the previous
         // step.  Remove them too.
-        for (int i = mUser.getPackages().size() - 1; i >= 0; i--) {
-            mUser.getPackages().valueAt(i).refreshPinnedFlags(this);
+        for (int i = mUser.getAllPackages().size() - 1; i >= 0; i--) {
+            mUser.getAllPackages().valueAt(i).refreshPinnedFlags(this);
         }
 
         scheduleSaveUser(owningUserId);
@@ -1539,6 +1576,7 @@
      * Entry point from {@link LauncherApps}.
      */
     private class LocalService extends ShortcutServiceInternal {
+
         @Override
         public List<ShortcutInfo> getShortcuts(int launcherUserId,
                 @NonNull String callingPackage, long changedSince,
@@ -1551,13 +1589,16 @@
                             : ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO;
 
             synchronized (mLock) {
+                getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
+                        .attemptToRestoreIfNeededAndSave(ShortcutService.this);
+
                 if (packageName != null) {
                     getShortcutsInnerLocked(launcherUserId,
                             callingPackage, packageName, changedSince,
                             componentName, queryFlags, userId, ret, cloneFlag);
                 } else {
                     final ArrayMap<String, ShortcutPackage> packages =
-                            getUserShortcutsLocked(userId).getPackages();
+                            getUserShortcutsLocked(userId).getAllPackages();
                     for (int i = packages.size() - 1; i >= 0; i--) {
                         getShortcutsInnerLocked(launcherUserId,
                                 callingPackage, packages.keyAt(i), changedSince,
@@ -1601,6 +1642,9 @@
             final ArrayList<ShortcutInfo> ret = new ArrayList<>(ids.size());
             final ArraySet<String> idSet = new ArraySet<>(ids);
             synchronized (mLock) {
+                getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
+                        .attemptToRestoreIfNeededAndSave(ShortcutService.this);
+
                 getPackageShortcutsLocked(packageName, userId).findAll(
                         ShortcutService.this, ret,
                         (ShortcutInfo si) -> idSet.contains(si.getId()),
@@ -1616,13 +1660,16 @@
             Preconditions.checkStringNotEmpty(shortcutId, "shortcutId");
 
             synchronized (mLock) {
+                getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
+                        .attemptToRestoreIfNeededAndSave(ShortcutService.this);
+
                 final ShortcutInfo si = getShortcutInfoLocked(
                         launcherUserId, callingPackage, packageName, shortcutId, userId);
                 return si != null && si.isPinned();
             }
         }
 
-        public ShortcutInfo getShortcutInfoLocked(
+        private ShortcutInfo getShortcutInfoLocked(
                 int launcherUserId, @NonNull String callingPackage,
                 @NonNull String packageName, @NonNull String shortcutId, int userId) {
             Preconditions.checkStringNotEmpty(packageName, "packageName");
@@ -1646,9 +1693,8 @@
 
             synchronized (mLock) {
                 final ShortcutLauncher launcher =
-                        getLauncherShortcuts(callingPackage, userId, launcherUserId);
-
-                launcher.ensureNotShadowAndSave(ShortcutService.this);
+                        getLauncherShortcutsLocked(callingPackage, userId, launcherUserId);
+                launcher.attemptToRestoreIfNeededAndSave(ShortcutService.this);
 
                 launcher.pinShortcuts(
                         ShortcutService.this, userId, packageName, shortcutIds);
@@ -1665,6 +1711,9 @@
             Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty");
 
             synchronized (mLock) {
+                getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
+                        .attemptToRestoreIfNeededAndSave(ShortcutService.this);
+
                 // Make sure the shortcut is actually visible to the launcher.
                 final ShortcutInfo si = getShortcutInfoLocked(
                         launcherUserId, callingPackage, packageName, shortcutId, userId);
@@ -1690,6 +1739,9 @@
             Preconditions.checkNotNull(shortcut, "shortcut");
 
             synchronized (mLock) {
+                getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
+                        .attemptToRestoreIfNeededAndSave(ShortcutService.this);
+
                 final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
                         shortcut.getPackageName(), userId).findShortcutById(shortcut.getId());
                 return (shortcutInfo != null && shortcutInfo.hasIconResource())
@@ -1704,6 +1756,9 @@
             Preconditions.checkNotNull(shortcutIn, "shortcut");
 
             synchronized (mLock) {
+                getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
+                        .attemptToRestoreIfNeededAndSave(ShortcutService.this);
+
                 final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
                         shortcutIn.getPackageName(), userId).findShortcutById(shortcutIn.getId());
                 if (shortcutInfo == null || !shortcutInfo.hasIconFile()) {
@@ -1757,28 +1812,28 @@
      * perform cleanup.
      */
     @VisibleForTesting
-    void cleanupGonePackages(@UserIdInt int userId) {
+    void cleanupGonePackages(@UserIdInt int ownerUserId) {
         if (DEBUG) {
-            Slog.d(TAG, "cleanupGonePackages() userId=" + userId);
+            Slog.d(TAG, "cleanupGonePackages() ownerUserId=" + ownerUserId);
         }
         final ArrayList<PackageWithUser> gonePackages = new ArrayList<>();
 
         synchronized (mLock) {
-            final ShortcutUser user = getUserShortcutsLocked(userId);
+            final ShortcutUser user = getUserShortcutsLocked(ownerUserId);
 
             user.forAllPackageItems(spi -> {
                 if (spi.getPackageInfo().isShadow()) {
                     return; // Don't delete shadow information.
                 }
                 if (isPackageInstalled(spi.getPackageName(), spi.getPackageUserId())) {
-                    return;
+                    return; // Package not gone.
                 }
                 gonePackages.add(PackageWithUser.of(spi));
             });
             if (gonePackages.size() > 0) {
                 for (int i = gonePackages.size() - 1; i >= 0; i--) {
                     final PackageWithUser pu = gonePackages.get(i);
-                    cleanUpPackageLocked(pu.packageName, userId, pu.userId);
+                    cleanUpPackageLocked(pu.packageName, ownerUserId, pu.userId);
                 }
             }
         }
@@ -1789,7 +1844,8 @@
             Slog.d(TAG, String.format("handlePackageAdded: %s user=%d", packageName, userId));
         }
         synchronized (mLock) {
-            getUserShortcutsLocked(userId).unshadowPackage(this, packageName, userId);
+            forEachLoadedUserLocked(user ->
+                    user.attemptToRestoreIfNeededAndSave(this, packageName, userId));
         }
     }
 
@@ -1798,18 +1854,20 @@
             Slog.d(TAG, String.format("handlePackageUpdateFinished: %s user=%d",
                     packageName, userId));
         }
-
         synchronized (mLock) {
-            getUserShortcutsLocked(userId).unshadowPackage(this, packageName, userId);
+            forEachLoadedUserLocked(user ->
+                    user.attemptToRestoreIfNeededAndSave(this, packageName, userId));
         }
     }
 
-    private void handlePackageRemoved(String packageName, @UserIdInt int userId) {
+    private void handlePackageRemoved(String packageName, @UserIdInt int packageUserId) {
         if (DEBUG) {
-            Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName, userId));
+            Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName,
+                    packageUserId));
         }
         synchronized (mLock) {
-            cleanUpPackageLocked(packageName, userId, userId);
+            forEachLoadedUserLocked(user ->
+                cleanUpPackageLocked(packageName, user.getUserId(), packageUserId));
         }
     }
 
@@ -1836,6 +1894,7 @@
     @VisibleForTesting
     PackageInfo injectPackageInfo(String packageName, @UserIdInt int userId,
             boolean getSignatures) {
+        final long start = System.currentTimeMillis();
         final long token = injectClearCallingIdentity();
         try {
             return mIPackageManager.getPackageInfo(packageName, PACKAGE_MATCH_FLAGS
@@ -1847,11 +1906,16 @@
             return null;
         } finally {
             injectRestoreCallingIdentity(token);
+
+            logDurationStat(
+                    (getSignatures ? Stats.GET_PACKAGE_INFO_WITH_SIG : Stats.GET_PACKAGE_INFO),
+                    start);
         }
     }
 
     @VisibleForTesting
     ApplicationInfo injectApplicationInfo(String packageName, @UserIdInt int userId) {
+        final long start = System.currentTimeMillis();
         final long token = injectClearCallingIdentity();
         try {
             return mIPackageManager.getApplicationInfo(packageName, PACKAGE_MATCH_FLAGS, userId);
@@ -1861,6 +1925,8 @@
             return null;
         } finally {
             injectRestoreCallingIdentity(token);
+
+            logDurationStat(Stats.GET_APPLICATION_INFO, start);
         }
     }
 
@@ -1869,7 +1935,7 @@
         return (ai != null) && ((ai.flags & flags) == flags);
     }
 
-    private boolean isPackageInstalled(String packageName, int userId) {
+    boolean isPackageInstalled(String packageName, int userId) {
         return isApplicationFlagSet(packageName, userId, ApplicationInfo.FLAG_INSTALLED);
     }
 
@@ -1879,8 +1945,12 @@
         return isApplicationFlagSet(packageName, userId, ApplicationInfo.FLAG_ALLOW_BACKUP);
     }
 
+    boolean shouldBackupApp(PackageInfo pi) {
+        return (pi.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0;
+    }
+
     @Override
-    public byte[] getBackupPayload(@UserIdInt int userId) throws RemoteException {
+    public byte[] getBackupPayload(@UserIdInt int userId) {
         enforceSystem();
         if (DEBUG) {
             Slog.d(TAG, "Backing up user " + userId);
@@ -1908,7 +1978,7 @@
     }
 
     @Override
-    public void applyRestore(byte[] payload, @UserIdInt int userId) throws RemoteException {
+    public void applyRestore(byte[] payload, @UserIdInt int userId) {
         enforceSystem();
         if (DEBUG) {
             Slog.d(TAG, "Restoring user " + userId);
@@ -1923,6 +1993,15 @@
         }
         synchronized (mLock) {
             mUsers.put(userId, user);
+
+            // Then purge all the save images.
+            final File bitmapPath = getUserBitmapFilePath(userId);
+            final boolean success = FileUtils.deleteContents(bitmapPath);
+            if (!success) {
+                Slog.w(TAG, "Failed to delete " + bitmapPath);
+            }
+
+            saveUserLocked(userId);
         }
     }
 
@@ -1974,9 +2053,19 @@
             pw.print("  Icon format: ");
             pw.print(mIconPersistFormat);
             pw.print("  Icon quality: ");
-            pw.print(mIconPersistQuality);
+            pw.println(mIconPersistQuality);
             pw.println();
 
+            pw.println("  Stats:");
+            synchronized (mStatLock) {
+                final String p = "     ";
+                dumpStatLS(pw, p, Stats.GET_DEFAULT_HOME, "getHomeActivities()");
+                dumpStatLS(pw, p, Stats.LAUNCHER_PERMISSION_CHECK, "Launcher permission check");
+
+                dumpStatLS(pw, p, Stats.GET_PACKAGE_INFO, "getPackageInfo()");
+                dumpStatLS(pw, p, Stats.GET_PACKAGE_INFO_WITH_SIG, "getPackageInfo(SIG)");
+                dumpStatLS(pw, p, Stats.GET_APPLICATION_INFO, "getApplicationInfo");
+            }
 
             for (int i = 0; i < mUsers.size(); i++) {
                 pw.println();
@@ -1991,6 +2080,15 @@
         return tobj.format("%Y-%m-%d %H:%M:%S");
     }
 
+    private void dumpStatLS(PrintWriter pw, String prefix, int statId, String label) {
+        pw.print(prefix);
+        final int count = mCountStats[statId];
+        final long dur = mDurationStats[statId];
+        pw.println(String.format("%s: count=%d, total=%dms, avg=%.1fms",
+                label, count, dur,
+                (count == 0 ? 0 : ((double) dur) / count)));
+    }
+
     // === Shell support ===
 
     @Override
@@ -2061,6 +2159,9 @@
                     case "refresh-default-launcher":
                         handleRefreshDefaultLauncher();
                         break;
+                    case "unload-user":
+                        handleUnloadUser();
+                        break;
                     default:
                         return handleDefaultCommands(cmd);
                 }
@@ -2098,6 +2199,10 @@
             pw.println("cmd shortcut refresh-default-launcher [--user USER_ID]");
             pw.println("    Refresh the cached default launcher");
             pw.println();
+            pw.println("cmd shortcut unload-user [--user USER_ID]");
+            pw.println("    Unload a user from the memory");
+            pw.println("    (This should not affect any observable behavior)");
+            pw.println();
         }
 
         private int handleResetThrottling() throws CommandException {
@@ -2169,6 +2274,12 @@
             clearLauncher();
             showLauncher();
         }
+
+        private void handleUnloadUser() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
+
+            ShortcutService.this.handleCleanupUser(mUserId);
+        }
     }
 
     // === Unit test support ===
@@ -2202,9 +2313,10 @@
     }
 
     final void wtf(String message) {
-        Slog.wtf(TAG, message, /* exception= */ null);
+        wtf( message, /* exception= */ null);
     }
 
+    // Injection point.
     void wtf(String message, Exception e) {
         Slog.wtf(TAG, message, e);
     }
@@ -2275,7 +2387,7 @@
             final ShortcutUser user = mUsers.get(userId);
             if (user == null) return null;
 
-            final ShortcutPackage pkg = user.getPackages().get(packageName);
+            final ShortcutPackage pkg = user.getAllPackages().get(packageName);
             if (pkg == null) return null;
 
             return pkg.findShortcutById(shortcutId);
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 487558f..593f607 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -53,8 +53,8 @@
             this.packageName = Preconditions.checkNotNull(packageName);
         }
 
-        public static PackageWithUser of(int launcherUserId, String packageName) {
-            return new PackageWithUser(launcherUserId, packageName);
+        public static PackageWithUser of(int userId, String packageName) {
+            return new PackageWithUser(userId, packageName);
         }
 
         public static PackageWithUser of(ShortcutPackageItem spi) {
@@ -78,12 +78,12 @@
 
         @Override
         public String toString() {
-            return String.format("{Launcher: %d, %s}", userId, packageName);
+            return String.format("{Package: %d, %s}", userId, packageName);
         }
     }
 
     @UserIdInt
-    final int mUserId;
+    private final int mUserId;
 
     private final ArrayMap<String, ShortcutPackage> mPackages = new ArrayMap<>();
 
@@ -95,10 +95,18 @@
         mUserId = userId;
     }
 
-    public ArrayMap<String, ShortcutPackage> getPackages() {
+    public int getUserId() {
+        return mUserId;
+    }
+
+    public ArrayMap<String, ShortcutPackage> getAllPackages() {
         return mPackages;
     }
 
+    public ShortcutPackage removePackage(@NonNull String packageName) {
+        return mPackages.remove(packageName);
+    }
+
     public ArrayMap<PackageWithUser, ShortcutLauncher> getAllLaunchers() {
         return mLaunchers;
     }
@@ -113,22 +121,26 @@
         return mLaunchers.remove(PackageWithUser.of(packageUserId, packageName));
     }
 
-    public ShortcutPackage getPackageShortcuts(@NonNull String packageName) {
+    public ShortcutPackage getPackageShortcuts(ShortcutService s, @NonNull String packageName) {
         ShortcutPackage ret = mPackages.get(packageName);
         if (ret == null) {
             ret = new ShortcutPackage(mUserId, packageName);
             mPackages.put(packageName, ret);
+        } else {
+            ret.attemptToRestoreIfNeededAndSave(s);
         }
         return ret;
     }
 
-    public ShortcutLauncher getLauncherShortcuts(@NonNull String packageName,
+    public ShortcutLauncher getLauncherShortcuts(ShortcutService s, @NonNull String packageName,
             @UserIdInt int launcherUserId) {
         final PackageWithUser key = PackageWithUser.of(launcherUserId, packageName);
         ShortcutLauncher ret = mLaunchers.get(key);
         if (ret == null) {
             ret = new ShortcutLauncher(mUserId, packageName, launcherUserId);
             mLaunchers.put(key, ret);
+        } else {
+            ret.attemptToRestoreIfNeededAndSave(s);
         }
         return ret;
     }
@@ -148,14 +160,6 @@
         }
     }
 
-    public void unshadowPackage(ShortcutService s, @NonNull String packageName,
-            @UserIdInt int packageUserId) {
-        forPackageItem(packageName, packageUserId, spi -> {
-            Slog.i(TAG, String.format("Restoring for %s, user=%d", packageName, packageUserId));
-            spi.ensureNotShadowAndSave(s);
-        });
-    }
-
     public void forPackageItem(@NonNull String packageName, @UserIdInt int packageUserId,
             Consumer<ShortcutPackageItem> callback) {
         forAllPackageItems(spi -> {
@@ -166,6 +170,13 @@
         });
     }
 
+    public void attemptToRestoreIfNeededAndSave(ShortcutService s, @NonNull String packageName,
+            @UserIdInt int packageUserId) {
+        forPackageItem(packageName, packageUserId, spi -> {
+            spi.attemptToRestoreIfNeededAndSave(s);
+        });
+    }
+
     public void saveToXml(ShortcutService s, XmlSerializer out, boolean forBackup)
             throws IOException, XmlPullParserException {
         out.startTag(null, TAG_ROOT);
@@ -229,7 +240,7 @@
                                 s, parser, userId, fromBackup);
 
                         // Don't use addShortcut(), we don't need to save the icon.
-                        ret.getPackages().put(shortcuts.getPackageName(), shortcuts);
+                        ret.mPackages.put(shortcuts.getPackageName(), shortcuts);
                         continue;
                     }
 
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 3ff46ac..60a0d62 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -467,13 +467,16 @@
 
     @Override
     public List<UserInfo> getProfiles(int userId, boolean enabledOnly) {
+        boolean returnFullInfo = true;
         if (userId != UserHandle.getCallingUserId()) {
             checkManageUsersPermission("getting profiles related to user " + userId);
+        } else {
+            returnFullInfo = hasManageUsersPermission();
         }
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mUsersLock) {
-                return getProfilesLU(userId, enabledOnly);
+                return getProfilesLU(userId, enabledOnly, returnFullInfo);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -481,7 +484,7 @@
     }
 
     /** Assume permissions already checked and caller's identity cleared */
-    private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly) {
+    private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly, boolean fullInfo) {
         UserInfo user = getUserInfoLU(userId);
         ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
         if (user == null) {
@@ -500,7 +503,17 @@
             if (mRemovingUserIds.get(profile.id)) {
                 continue;
             }
-            users.add(userWithName(profile));
+            if (profile.partial) {
+                continue;
+            }
+            UserInfo userInfo = userWithName(profile);
+            // If full info is not required - clear PII data to prevent 3P apps from reading it
+            if (!fullInfo) {
+                userInfo = new UserInfo(userInfo);
+                userInfo.name = null;
+                userInfo.iconPath = null;
+            }
+            users.add(userInfo);
         }
         return users;
     }
@@ -573,12 +586,26 @@
 
     private void broadcastProfileAvailabilityChanges(UserHandle profileHandle,
             UserHandle parentHandle, boolean inQuietMode) {
-        Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+        Intent intent = new Intent();
+        if (inQuietMode) {
+            intent.setAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
+        } else {
+            intent.setAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+        }
         intent.putExtra(Intent.EXTRA_QUIET_MODE, inQuietMode);
         intent.putExtra(Intent.EXTRA_USER, profileHandle);
         intent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier());
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
         mContext.sendBroadcastAsUser(intent, parentHandle);
+
+        //TODO: remove once Launcher3 is updated.
+        Intent oldIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
+        oldIntent.putExtra(Intent.EXTRA_QUIET_MODE, inQuietMode);
+        oldIntent.putExtra(Intent.EXTRA_USER, profileHandle);
+        oldIntent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier());
+        oldIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mContext.sendBroadcastAsUser(oldIntent, parentHandle);
+
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 4b355de62..364e9fa6 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -425,6 +425,18 @@
                             }
                         }
                     }
+                    break;
+                case UserManager.DISALLOW_SAFE_BOOT:
+                    // Unlike with the other restrictions, we want to propagate the new value to
+                    // the system settings even if it is false. The other restrictions modify
+                    // settings which could be manually changed by the user from the Settings app
+                    // after the policies enforcing these restrictions have been revoked, so we
+                    // leave re-setting of those settings to the user.
+                    android.provider.Settings.Global.putInt(
+                            context.getContentResolver(),
+                            android.provider.Settings.Global.SAFE_BOOT_DISALLOWED,
+                            newValue ? 1 : 0);
+                    break;
             }
         } finally {
             Binder.restoreCallingIdentity(id);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 747e31e..fb56a0c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -69,6 +69,7 @@
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiPlaybackClient;
 import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
+import android.hardware.input.InputManagerInternal;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
@@ -107,6 +108,7 @@
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.MutableBoolean;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.LongSparseArray;
@@ -304,6 +306,7 @@
     WindowManagerInternal mWindowManagerInternal;
     PowerManager mPowerManager;
     ActivityManagerInternal mActivityManagerInternal;
+    InputManagerInternal mInputManagerInternal;
     DreamManagerInternal mDreamManagerInternal;
     PowerManagerInternal mPowerManagerInternal;
     IStatusBarService mStatusBarService;
@@ -396,6 +399,8 @@
     volatile boolean mBeganFromNonInteractive;
     volatile int mPowerKeyPressCounter;
     volatile boolean mEndCallKeyHandled;
+    volatile boolean mCameraGestureTriggeredDuringGoingToSleep;
+    volatile boolean mGoingToSleep;
 
     boolean mRecentsVisible;
     int mRecentAppsHeldModifiers;
@@ -601,6 +606,9 @@
     boolean mConsumeSearchKeyUp;
     boolean mAssistKeyLongPressed;
     boolean mPendingMetaAction;
+    boolean mPendingCapsLockToggle;
+    int mMetaState;
+    int mInitialMetaState;
     boolean mForceShowSystemBars;
 
     // support for activating the lock screen while the screen is on
@@ -685,6 +693,7 @@
             = new LogDecelerateInterpolator(100, 0);
 
     private boolean mForceWindowDrawsStatusBarBackground;
+    private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
 
     private static final int MSG_ENABLE_POINTER_LOCATION = 1;
     private static final int MSG_DISABLE_POINTER_LOCATION = 2;
@@ -1032,7 +1041,11 @@
                 GestureLauncherService.class);
         boolean gesturedServiceIntercepted = false;
         if (gestureService != null) {
-            gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive);
+            gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
+                    mTmpBoolean);
+            if (mTmpBoolean.value && mGoingToSleep) {
+                mCameraGestureTriggeredDuringGoingToSleep = true;
+            }
         }
 
         // If the power key has still not yet been handled, then detect short
@@ -1486,6 +1499,7 @@
         mWindowManagerFuncs = windowManagerFuncs;
         mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
         mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -1817,41 +1831,6 @@
             }
         }
 
-        mStatusBarHeight =
-                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
-
-        // Height of the navigation bar when presented horizontally at bottom
-        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
-        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
-                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
-        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
-        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.navigation_bar_height_landscape);
-
-        // Width of the navigation bar when presented vertically along one side
-        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
-        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
-        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
-        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
-                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
-
-        // Height of the navigation bar when presented horizontally at bottom
-        mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
-        mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
-                res.getDimensionPixelSize(
-                        com.android.internal.R.dimen.navigation_bar_height_car_mode);
-        mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
-        mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
-
-        // Width of the navigation bar when presented vertically along one side
-        mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
-        mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
-        mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
-        mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
-                res.getDimensionPixelSize(
-                        com.android.internal.R.dimen.navigation_bar_width_car_mode);
-
         // SystemUI (status bar) layout policy
         int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
         int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
@@ -1860,6 +1839,7 @@
         mNavigationBarCanMove = width != height && shortSizeDp < 600;
 
         mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
+
         // Allow a system property to override this. Used by the emulator.
         // See also hasNavigationBar().
         String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
@@ -2290,6 +2270,46 @@
         }
     }
 
+    @Override
+    public void onConfigurationChanged() {
+        final Resources res = mContext.getResources();
+
+        mStatusBarHeight =
+                res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+
+        // Height of the navigation bar when presented horizontally at bottom
+        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
+        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
+                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
+        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
+        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_height_landscape);
+
+        // Width of the navigation bar when presented vertically along one side
+        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
+        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
+        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
+        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
+                res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
+
+        // Height of the navigation bar when presented horizontally at bottom
+        mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
+        mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
+                res.getDimensionPixelSize(
+                        com.android.internal.R.dimen.navigation_bar_height_car_mode);
+        mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
+        mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
+
+        // Width of the navigation bar when presented vertically along one side
+        mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
+        mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
+        mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
+        mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
+                res.getDimensionPixelSize(
+                        com.android.internal.R.dimen.navigation_bar_width_car_mode);
+    }
+
     /** {@inheritDoc} */
     @Override
     public int windowTypeToLayerLw(int type) {
@@ -2954,6 +2974,10 @@
         if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
             mPendingMetaAction = false;
         }
+        // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
+        if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
+            mPendingCapsLockToggle = false;
+        }
 
         // First we always handle the home key here, so applications
         // can never break it, although if keyguard is on, we do let
@@ -3107,10 +3131,8 @@
                 return -1;
             }
         } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) {
-            if (down) {
-                if (repeatCount == 0) {
-                    toggleKeyboardShortcutsMenu(event.getDeviceId());
-                }
+            if (down && repeatCount == 0 && !isKeyguardLocked()) {
+                toggleKeyboardShortcutsMenu(event.getDeviceId());
             }
         } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
             if (down) {
@@ -3204,6 +3226,38 @@
             }
         }
 
+        // Toggle Caps Lock on META-ALT.
+        boolean actionTriggered = false;
+        if (KeyEvent.isModifierKey(keyCode)) {
+            if (!mPendingCapsLockToggle) {
+                // Start tracking meta state for combo.
+                mInitialMetaState = mMetaState;
+                mPendingCapsLockToggle = true;
+            } else if (event.getAction() == KeyEvent.ACTION_UP) {
+                int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
+                int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
+
+                // Check for Caps Lock toggle
+                if ((metaOnMask != 0) && (altOnMask != 0)) {
+                    // Check if nothing else is pressed
+                    if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
+                        // Handle Caps Lock Toggle
+                        mInputManagerInternal.toggleCapsLock(event.getDeviceId());
+                        actionTriggered = true;
+                    }
+                }
+
+                // Always stop tracking when key goes up.
+                mPendingCapsLockToggle = false;
+            }
+        }
+        // Store current meta state to be able to evaluate it later.
+        mMetaState = metaState;
+
+        if (actionTriggered) {
+            return -1;
+        }
+
         if (KeyEvent.isMetaKey(keyCode)) {
             if (down) {
                 mPendingMetaAction = true;
@@ -5950,6 +6004,8 @@
     @Override
     public void startedGoingToSleep(int why) {
         if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
+        mCameraGestureTriggeredDuringGoingToSleep = false;
+        mGoingToSleep = true;
         if (mKeyguardDelegate != null) {
             mKeyguardDelegate.onStartedGoingToSleep(why);
         }
@@ -5962,6 +6018,8 @@
         if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
         MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
 
+        mGoingToSleep = false;
+
         // We must get this work done here because the power manager will drop
         // the wake lock and let the system suspend once this function returns.
         synchronized (mLock) {
@@ -5971,8 +6029,10 @@
             updateLockScreenTimeout();
         }
         if (mKeyguardDelegate != null) {
-            mKeyguardDelegate.onFinishedGoingToSleep(why);
+            mKeyguardDelegate.onFinishedGoingToSleep(why,
+                    mCameraGestureTriggeredDuringGoingToSleep);
         }
+        mCameraGestureTriggeredDuringGoingToSleep = false;
     }
 
     // Called on the PowerManager's Notifier thread.
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 8d296d5..52e5880 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -294,9 +294,9 @@
         mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP;
     }
 
-    public void onFinishedGoingToSleep(int why) {
+    public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) {
         if (mKeyguardService != null) {
-            mKeyguardService.onFinishedGoingToSleep(why);
+            mKeyguardService.onFinishedGoingToSleep(why, cameraGestureTriggered);
         }
         mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP;
     }
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index 429b188..dacdec0 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -117,9 +117,9 @@
     }
 
     @Override
-    public void onFinishedGoingToSleep(int reason) {
+    public void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) {
         try {
-            mService.onFinishedGoingToSleep(reason);
+            mService.onFinishedGoingToSleep(reason, cameraGestureTriggered);
         } catch (RemoteException e) {
             Slog.w(TAG , "Remote Exception", e);
         }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index ff5a0f9..8cd536d 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -53,6 +53,8 @@
 import android.provider.Settings.Secure;
 import android.provider.Settings.SettingNotFoundException;
 import android.service.dreams.DreamManagerInternal;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseIntArray;
@@ -72,6 +74,7 @@
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
 import com.android.server.vr.VrManagerInternal;
+import com.android.server.vr.VrManagerService;
 import com.android.server.vr.VrStateListener;
 import libcore.util.Objects;
 
@@ -538,7 +541,10 @@
     @Override
     public void onBootPhase(int phase) {
         synchronized (mLock) {
-            if (phase == PHASE_BOOT_COMPLETED) {
+            if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+                incrementBootCount();
+
+            } else if (phase == PHASE_BOOT_COMPLETED) {
                 final long now = SystemClock.uptimeMillis();
                 mBootCompleted = true;
                 mDirty |= DIRTY_BOOT_COMPLETED;
@@ -553,8 +559,6 @@
                     }
                 }
                 mBootCompletedRunnables = null;
-
-                incrementBootCount();
             }
         }
     }
@@ -657,7 +661,13 @@
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Secure.BRIGHTNESS_USE_TWILIGHT),
                     false, mSettingsObserver, UserHandle.USER_ALL);
-            getLocalService(VrManagerInternal.class).registerListener(mVrStateListener);
+            IVrManager vrManager =
+                    (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
+            try {
+                vrManager.registerListener(mVrStateCallbacks);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+            }
             // Go.
             readConfigurationLocked();
             updateSettingsLocked();
@@ -3006,7 +3016,7 @@
         }
     }
 
-    private final VrStateListener mVrStateListener = new VrStateListener() {
+    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
         @Override
         public void onVrStateChanged(boolean enabled) {
             powerHintInternal(POWER_HINT_VR_MODE, enabled ? 1 : 0);
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 858f7c7..9c2c6bf 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -375,7 +375,7 @@
                 } else {
                     mTrustAgentService.onConfigure(Collections.EMPTY_LIST, null);
                 }
-                final long maxTimeToLock = dpm.getMaximumTimeToLock(null);
+                final long maxTimeToLock = dpm.getMaximumTimeToLockForUserAndProfiles(mUserId);
                 if (maxTimeToLock != mMaximumTimeToLock) {
                     // If the timeout changes, cancel the alarm and send a timeout event to have
                     // the agent re-evaluate trust.
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 93bb9d7..1bbb9f5 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -31,13 +31,6 @@
     public static final int NO_ERROR = 0;
 
     /**
-     * Return current VR mode state.
-     *
-     * @return {@code true} if VR mode is enabled.
-     */
-    public abstract boolean isInVrMode();
-
-    /**
      * Return {@code true} if the given package is the currently bound VrListenerService for the
      * given user.
      *
@@ -59,22 +52,6 @@
     public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName,
             int userId, @NonNull ComponentName calling);
 
-    /**
-     * Add a listener for VR mode state changes.
-     * <p>
-     * This listener will immediately be called with the current VR mode state.
-     * </p>
-     * @param listener the listener instance to add.
-     */
-    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(@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.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index c572e76..e6e5a2d 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.vr;
 
+import android.Manifest;
 import android.app.AppOpsManager;
 import android.app.NotificationManager;
 import android.annotation.NonNull;
@@ -29,11 +30,15 @@
 import android.os.IBinder;
 import android.os.IInterface;
 import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.NotificationListenerService;
 import android.service.vr.IVrListener;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
 import android.service.vr.VrListenerService;
 import android.util.ArraySet;
 import android.util.Slog;
@@ -46,6 +51,7 @@
 import com.android.server.utils.ManagedApplicationService.BinderChecker;
 
 import java.lang.StringBuilder;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Objects;
@@ -75,6 +81,8 @@
 
     public static final String TAG = "VrManagerService";
 
+    public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager";
+
     private static native void initializeNative();
     private static native void setVrModeNative(boolean enabled);
 
@@ -84,7 +92,6 @@
 
     // State protected by mLock
     private boolean mVrModeEnabled;
-    private final Set<VrStateListener> mListeners = new ArraySet<>();
     private EnabledComponentsObserver mComponentObserver;
     private ManagedApplicationService mCurrentVrService;
     private Context mContext;
@@ -92,10 +99,37 @@
     private int mCurrentVrModeUser;
     private boolean mWasDefaultGranted;
     private boolean mGuard;
+    private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
+            new RemoteCallbackList<>();
     private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>();
     private String mPreviousNotificationPolicyAccessPackage;
     private String mPreviousManageOverlayPackage;
 
+    private static final int MSG_VR_STATE_CHANGE = 0;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case MSG_VR_STATE_CHANGE : {
+                    boolean state = (msg.arg1 == 1);
+                    int i = mRemoteCallbacks.beginBroadcast();
+                    while (i > 0) {
+                        i--;
+                        try {
+                            mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
+                        } catch (RemoteException e) {
+                            // Noop
+                        }
+                    }
+                    mRemoteCallbacks.finishBroadcast();
+                } break;
+                default :
+                    throw new IllegalStateException("Unknown message type: " + msg.what);
+            }
+        }
+    };
+
     private static final BinderChecker sBinderChecker = new BinderChecker() {
         @Override
         public IInterface asInterface(IBinder binder) {
@@ -125,16 +159,47 @@
         }
     }
 
+    private final IVrManager mVrManager = new IVrManager.Stub() {
+
+        @Override
+        public void registerListener(IVrStateCallbacks cb) {
+            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
+            if (cb == null) {
+                throw new IllegalArgumentException("Callback binder object is null.");
+            }
+
+            VrManagerService.this.addStateCallback(cb);
+        }
+
+        @Override
+        public void unregisterListener(IVrStateCallbacks cb) {
+            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
+            if (cb == null) {
+                throw new IllegalArgumentException("Callback binder object is null.");
+            }
+
+            VrManagerService.this.removeStateCallback(cb);
+        }
+
+        @Override
+        public boolean getVrModeState() {
+            return VrManagerService.this.getVrMode();
+        }
+
+    };
+
+    private void enforceCallerPermission(String permission) {
+        if (mContext.checkCallingOrSelfPermission(permission)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Caller does not hold the permission " + permission);
+        }
+    }
+
     /**
      * Implementation of VrManagerInternal.  Callable only from system services.
      */
     private final class LocalService extends VrManagerInternal {
         @Override
-        public boolean isInVrMode() {
-            return VrManagerService.this.getVrMode();
-        }
-
-        @Override
         public void setVrMode(boolean enabled, ComponentName packageName, int userId,
                 ComponentName callingPackage) {
             VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
@@ -146,16 +211,6 @@
         }
 
         @Override
-        public void registerListener(VrStateListener listener) {
-            VrManagerService.this.addListener(listener);
-        }
-
-        @Override
-        public void unregisterListener(VrStateListener listener) {
-            VrManagerService.this.removeListener(listener);
-        }
-
-        @Override
         public int hasVrPackage(ComponentName packageName, int userId) {
             return VrManagerService.this.hasVrPackage(packageName, userId);
         }
@@ -173,6 +228,7 @@
         }
 
         publishLocalService(VrManagerInternal.class, new LocalService());
+        publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
     }
 
     @Override
@@ -551,9 +607,8 @@
      * Note: Must be called while holding {@code mLock}.
      */
     private void onVrModeChangedLocked() {
-        for (VrStateListener l : mListeners) {
-            l.onVrStateChanged(mVrModeEnabled);
-        }
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
+                (mVrModeEnabled) ? 1 : 0, 0));
     }
 
     /**
@@ -577,9 +632,9 @@
         }
     }
 
-    private boolean getVrMode() {
+    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
         synchronized (mLock) {
-            return mVrModeEnabled;
+            return mComponentObserver.isValid(targetPackageName, userId);
         }
     }
 
@@ -593,21 +648,21 @@
         }
     }
 
-    private void addListener(VrStateListener listener) {
-        synchronized (mLock) {
-            mListeners.add(listener);
-        }
+    /*
+     * Implementation of IVrManager calls.
+     */
+
+    private void addStateCallback(IVrStateCallbacks cb) {
+        mRemoteCallbacks.register(cb);
     }
 
-    private void removeListener(VrStateListener listener) {
-        synchronized (mLock) {
-            mListeners.remove(listener);
-        }
+    private void removeStateCallback(IVrStateCallbacks cb) {
+        mRemoteCallbacks.unregister(cb);
     }
 
-    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
+    private boolean getVrMode() {
         synchronized (mLock) {
-            return mComponentObserver.isValid(targetPackageName, userId);
+            return mVrModeEnabled;
         }
     }
 }
diff --git a/services/core/java/com/android/server/webkit/WebViewUtilityImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
similarity index 64%
rename from services/core/java/com/android/server/webkit/WebViewUtilityImpl.java
rename to services/core/java/com/android/server/webkit/SystemImpl.java
index aaa7977..9486cfd 100644
--- a/services/core/java/com/android/server/webkit/WebViewUtilityImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -19,15 +19,22 @@
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
 import android.content.Context;
+import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
 import android.content.res.XmlResourceParser;
+import android.os.Build;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings.Global;
 import android.provider.Settings;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
-import android.webkit.WebViewFactory;
 import android.webkit.WebViewFactory.MissingWebViewPackageException;
+import android.webkit.WebViewFactory;
 import android.webkit.WebViewProviderInfo;
 
 import com.android.internal.util.XmlUtils;
@@ -42,8 +49,8 @@
  * Default implementation for the WebView preparation Utility interface.
  * @hide
  */
-public class WebViewUtilityImpl implements WebViewUtilityInterface {
-    private static final String TAG = WebViewUtilityImpl.class.getSimpleName();
+public class SystemImpl implements SystemInterface {
+    private static final String TAG = SystemImpl.class.getSimpleName();
     private static final String TAG_START = "webviewproviders";
     private static final String TAG_WEBVIEW_PROVIDER = "webviewprovider";
     private static final String TAG_PACKAGE_NAME = "packageName";
@@ -103,9 +110,7 @@
                     Log.e(TAG, "Found an element that is not a webview provider");
                 }
             }
-        } catch(XmlPullParserException e) {
-            throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
-        } catch(IOException e) {
+        } catch (XmlPullParserException | IOException e) {
             throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
         } finally {
             if (parser != null) parser.close();
@@ -113,6 +118,11 @@
         return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
     }
 
+    public int getFactoryPackageVersion(String packageName) throws NameNotFoundException {
+        PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+        return pm.getPackageInfo(packageName, PackageManager.MATCH_FACTORY_ONLY).versionCode;
+    }
+
     /**
      * Reads all signatures at the current depth (within the current provider) from the XML parser.
      */
@@ -158,4 +168,70 @@
         } catch (RemoteException e) {
         }
     }
+
+    @Override
+    public boolean isFallbackLogicEnabled() {
+        // Note that this is enabled by default (i.e. if the setting hasn't been set).
+        return Settings.Global.getInt(AppGlobals.getInitialApplication().getContentResolver(),
+                Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, 1) == 1;
+    }
+
+    @Override
+    public void enableFallbackLogic(boolean enable) {
+        Settings.Global.putInt(AppGlobals.getInitialApplication().getContentResolver(),
+                Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, enable ? 1 : 0);
+    }
+
+    @Override
+    public void uninstallAndDisablePackageForAllUsers(Context context, String packageName) {
+        enablePackageForAllUsers(context, packageName, false);
+        try {
+            PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+            if (pm.getApplicationInfo(packageName, 0).isUpdatedSystemApp()) {
+                pm.deletePackage(packageName, new IPackageDeleteObserver.Stub() {
+                        public void packageDeleted(String packageName, int returnCode) {
+                            enablePackageForAllUsers(context, packageName, false);
+                        }
+                    }, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS);
+            }
+        } catch (NameNotFoundException e) {
+        }
+    }
+
+    @Override
+    public void enablePackageForAllUsers(Context context, String packageName, boolean enable) {
+        UserManager userManager = (UserManager)context.getSystemService(Context.USER_SERVICE);
+        for(UserInfo userInfo : userManager.getUsers()) {
+            enablePackageForUser(packageName, enable, userInfo.id);
+        }
+    }
+
+    @Override
+    public void enablePackageForUser(String packageName, boolean enable, int userId) {
+        try {
+            AppGlobals.getPackageManager().setApplicationEnabledSetting(
+                    packageName,
+                    enable ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT :
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0,
+                    userId, null);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Tried to disable " + packageName + " for user " + userId + ": " + e);
+        }
+    }
+
+    @Override
+    public boolean systemIsDebuggable() {
+        return Build.IS_DEBUGGABLE;
+    }
+
+    @Override
+    public PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
+            throws NameNotFoundException {
+        PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+        return pm.getPackageInfo(configInfo.packageName, PACKAGE_FLAGS);
+    }
+
+    // flags declaring we want extra info from the package manager for webview providers
+    private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
+            | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
 }
diff --git a/services/core/java/com/android/server/webkit/WebViewUtilityInterface.java b/services/core/java/com/android/server/webkit/SystemInterface.java
similarity index 64%
rename from services/core/java/com/android/server/webkit/WebViewUtilityInterface.java
rename to services/core/java/com/android/server/webkit/SystemInterface.java
index 1919f40..7bde37a 100644
--- a/services/core/java/com/android/server/webkit/WebViewUtilityInterface.java
+++ b/services/core/java/com/android/server/webkit/SystemInterface.java
@@ -16,22 +16,36 @@
 
 package com.android.server.webkit;
 
-import android.webkit.WebViewProviderInfo;
 import android.content.Context;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.webkit.WebViewProviderInfo;
 
 /**
- * Utility interface for the WebViewUpdateService.
+ * System interface for the WebViewUpdateService.
  * This interface provides a way to test the WebView preparation mechanism - during normal use this
  * interface is implemented using calls to the Android framework, but by providing an alternative
  * implementation we can test the WebView preparation logic without reaching other framework code.
+ *
  * @hide
  */
-public interface WebViewUtilityInterface {
+public interface SystemInterface {
     public WebViewProviderInfo[] getWebViewPackages();
     public int onWebViewProviderChanged(PackageInfo packageInfo);
+    public int getFactoryPackageVersion(String packageName) throws NameNotFoundException;
 
     public String getUserChosenWebViewProvider(Context context);
     public void updateUserSetting(Context context, String newProviderName);
     public void killPackageDependents(String packageName);
+
+    public boolean isFallbackLogicEnabled();
+    public void enableFallbackLogic(boolean enable);
+
+    public void uninstallAndDisablePackageForAllUsers(Context context, String packageName);
+    public void enablePackageForAllUsers(Context context, String packageName, boolean enable);
+    public void enablePackageForUser(String packageName, boolean enable, int userId);
+
+    public boolean systemIsDebuggable();
+    public PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
+            throws NameNotFoundException;
 }
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index c4f9cc1..ebec445 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -16,30 +16,20 @@
 
 package com.android.server.webkit;
 
-import android.app.ActivityManagerNative;
-import android.app.AppGlobals;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
-import android.content.pm.UserInfo;
 import android.os.Binder;
-import android.os.Build;
 import android.os.PatternMatcher;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings.Global;
-import android.provider.Settings;
-import android.util.AndroidRuntimeException;
 import android.util.Base64;
 import android.util.Slog;
 import android.webkit.IWebViewUpdateService;
@@ -52,7 +42,6 @@
 import java.io.FileDescriptor;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -62,26 +51,21 @@
 public class WebViewUpdateService extends SystemService {
 
     private static final String TAG = "WebViewUpdateService";
-    private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000.
-
-    // Keeps track of the number of running relro creations
-    private int mNumRelroCreationsStarted = 0;
-    private int mNumRelroCreationsFinished = 0;
-    // Implies that we need to rerun relro creation because we are using an out-of-date package
-    private boolean mWebViewPackageDirty = false;
-    private boolean mAnyWebViewInstalled = false;
-
-    private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
-
-    // The WebView package currently in use (or the one we are preparing).
-    private PackageInfo mCurrentWebViewPackage = null;
 
     private BroadcastReceiver mWebViewUpdatedReceiver;
-    private WebViewUtilityInterface mWebViewUtility;
+    private SystemInterface mSystemInterface;
+
+    static final int PACKAGE_CHANGED = 0;
+    static final int PACKAGE_ADDED = 1;
+    static final int PACKAGE_ADDED_REPLACED = 2;
+    static final int PACKAGE_REMOVED = 3;
+
+    private WebViewUpdater mWebViewUpdater;
 
     public WebViewUpdateService(Context context) {
         super(context);
-        mWebViewUtility = new WebViewUtilityImpl();
+        mSystemInterface = new SystemImpl();
+        mWebViewUpdater = new WebViewUpdater(getContext(), mSystemInterface);
     }
 
     @Override
@@ -89,76 +73,34 @@
         mWebViewUpdatedReceiver = new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
-                    // When a package is replaced we will receive two intents, one representing
-                    // the removal of the old package and one representing the addition of the
-                    // new package.
-                    // In the case where we receive an intent to remove the old version of the
-                    // package that is being replaced we early-out here so that we don't run the
-                    // update-logic twice.
-                    if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)
-                        && intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
-                        return;
-                    }
-
-                    // Ensure that we only heed PACKAGE_CHANGED intents if they change an entire
-                    // package, not just a component
-                    if (intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED)) {
-                        if (!WebViewFactory.entirePackageChanged(intent)) {
-                            return;
-                        }
-                    }
-
-                    if (intent.getAction().equals(Intent.ACTION_USER_ADDED)) {
-                        int userId =
-                            intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
-                        handleNewUser(userId);
-                        return;
-                    }
-
-                    updateFallbackState(context, intent);
-
-                    for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) {
-                        String webviewPackage = "package:" + provider.packageName;
-
-                        if (webviewPackage.equals(intent.getDataString())) {
-                            boolean updateWebView = false;
-                            boolean removedOrChangedOldPackage = false;
-                            String oldProviderName = null;
-                            PackageInfo newPackage = null;
-                            synchronized(WebViewUpdateService.this) {
-                                try {
-                                    newPackage = findPreferredWebViewPackage();
-                                    if (mCurrentWebViewPackage != null)
-                                        oldProviderName = mCurrentWebViewPackage.packageName;
-                                    // Only trigger update actions if the updated package is the one
-                                    // that will be used, or the one that was in use before the
-                                    // update, or if we haven't seen a valid WebView package before.
-                                    updateWebView =
-                                        provider.packageName.equals(newPackage.packageName)
-                                        || provider.packageName.equals(oldProviderName)
-                                        || mCurrentWebViewPackage == null;
-                                    // We removed the old package if we received an intent to remove
-                                    // or replace the old package.
-                                    removedOrChangedOldPackage =
-                                        provider.packageName.equals(oldProviderName);
-                                    if (updateWebView) {
-                                        onWebViewProviderChanged(newPackage);
-                                    }
-                                } catch (WebViewFactory.MissingWebViewPackageException e) {
-                                    Slog.e(TAG, "Could not find valid WebView package to create " +
-                                            "relro with " + e);
-                                }
+                    switch (intent.getAction()) {
+                        case Intent.ACTION_PACKAGE_REMOVED:
+                            // When a package is replaced we will receive two intents, one
+                            // representing the removal of the old package and one representing the
+                            // addition of the new package.
+                            // In the case where we receive an intent to remove the old version of
+                            // the package that is being replaced we early-out here so that we don't
+                            // run the update-logic twice.
+                            if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) return;
+                            packageStateChanged(packageNameFromIntent(intent), PACKAGE_REMOVED);
+                            break;
+                        case Intent.ACTION_PACKAGE_CHANGED:
+                            // Ensure that we only heed PACKAGE_CHANGED intents if they change an
+                            // entire package, not just a component
+                            if (entirePackageChanged(intent)) {
+                                packageStateChanged(packageNameFromIntent(intent), PACKAGE_CHANGED);
                             }
-                            if(updateWebView && !removedOrChangedOldPackage
-                                    && oldProviderName != null) {
-                                // If the provider change is the result of adding or replacing a
-                                // package that was not the previous provider then we must kill
-                                // packages dependent on the old package ourselves. The framework
-                                // only kills dependents of packages that are being removed.
-                                mWebViewUtility.killPackageDependents(oldProviderName);
-                            }
-                            return;
-                        }
+                            break;
+                        case Intent.ACTION_PACKAGE_ADDED:
+                            packageStateChanged(packageNameFromIntent(intent),
+                                    (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)
+                                     ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED));
+                            break;
+                        case Intent.ACTION_USER_ADDED:
+                            int userId =
+                                intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+                            handleNewUser(userId);
+                            break;
                     }
                 }
         };
@@ -168,7 +110,7 @@
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addDataScheme("package");
         // Make sure we only receive intents for WebView packages from our config file.
-        for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) {
+        for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
             filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL);
         }
         getContext().registerReceiver(mWebViewUpdatedReceiver, filter);
@@ -180,12 +122,27 @@
         publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/);
     }
 
+    private void packageStateChanged(String packageName, int changedState) {
+        updateFallbackState(packageName, changedState);
+        mWebViewUpdater.packageStateChanged(packageName, changedState);
+    }
+
+    public void prepareWebViewInSystemServer() {
+        updateFallbackStateOnBoot();
+        mWebViewUpdater.prepareWebViewInSystemServer();
+    }
+
+    private static String packageNameFromIntent(Intent intent) {
+        return intent.getDataString().substring("package:".length());
+    }
+
     private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) {
         for (WebViewProviderInfo provider : providers) {
             if (provider.availableByDefault && !provider.isFallback) {
                 try {
-                    PackageInfo packageInfo = getPackageInfoForProvider(provider);
-                    if (isEnabledPackage(packageInfo) && isValidProvider(provider, packageInfo)) {
+                    PackageInfo packageInfo = mSystemInterface.getPackageInfoForProvider(provider);
+                    if (isEnabledPackage(packageInfo)
+                            && mWebViewUpdater.isValidProvider(provider, packageInfo)) {
                         return true;
                     }
                 } catch (NameNotFoundException e) {
@@ -196,59 +153,51 @@
         return false;
     }
 
-    private static void enablePackageForUser(String packageName, boolean enable, int userId) {
-        try {
-            AppGlobals.getPackageManager().setApplicationEnabledSetting(
-                    packageName,
-                    enable ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT :
-                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0,
-                    userId, null);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Tried to disable " + packageName + " for user " + userId + ": " + e);
-        }
-    }
-
     /**
      * Called when a new user has been added to update the state of its fallback package.
      */
     void handleNewUser(int userId) {
-        if (!isFallbackLogicEnabled()) return;
+        if (!mSystemInterface.isFallbackLogicEnabled()) return;
 
-        WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages();
+        WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
         WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
         if (fallbackProvider == null) return;
 
-        enablePackageForUser(fallbackProvider.packageName,
+        mSystemInterface.enablePackageForUser(fallbackProvider.packageName,
                 !existsValidNonFallbackProvider(webviewProviders), userId);
     }
 
+    public void updateFallbackStateOnBoot() {
+        WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
+        updateFallbackState(webviewProviders, true);
+    }
+
     /**
      * Handle the enabled-state of our fallback package, i.e. if there exists some non-fallback
      * package that is valid (and available by default) then disable the fallback package,
      * otherwise, enable the fallback package.
      */
-    void updateFallbackState(final Context context, final Intent intent) {
-        if (!isFallbackLogicEnabled()) return;
+    public void updateFallbackState(String changedPackage, int changedState) {
+        if (!mSystemInterface.isFallbackLogicEnabled()) return;
 
-        WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages();
+        WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
 
-        if (intent != null && (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)
-                    || intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED))) {
-            // A package was changed / updated / downgraded, early out if it is not one of the
-            // webview packages that are available by default.
-            String changedPackage = null;
-            for (WebViewProviderInfo provider : webviewProviders) {
-                String webviewPackage = "package:" + provider.packageName;
-                if (webviewPackage.equals(intent.getDataString())) {
-                    if (provider.availableByDefault) {
-                        changedPackage = provider.packageName;
-                    }
-                    break;
+        // A package was changed / updated / downgraded, early out if it is not one of the
+        // webview packages that are available by default.
+        boolean changedPackageAvailableByDefault = false;
+        for (WebViewProviderInfo provider : webviewProviders) {
+            if (provider.packageName.equals(changedPackage)) {
+                if (provider.availableByDefault) {
+                    changedPackageAvailableByDefault = true;
                 }
+                break;
             }
-            if (changedPackage == null) return;
         }
+        if (!changedPackageAvailableByDefault) return;
+        updateFallbackState(webviewProviders, false);
+    }
 
+    private void updateFallbackState(WebViewProviderInfo[] webviewProviders, boolean isBoot) {
         // If there exists a valid and enabled non-fallback package - disable the fallback
         // package, otherwise, enable it.
         WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
@@ -257,55 +206,29 @@
 
         boolean isFallbackEnabled = false;
         try {
-            isFallbackEnabled = isEnabledPackage(getPackageInfoForProvider(fallbackProvider));
+            isFallbackEnabled = isEnabledPackage(
+                    mSystemInterface.getPackageInfoForProvider(fallbackProvider));
         } catch (NameNotFoundException e) {
         }
 
         if (existsValidNonFallbackProvider
                 // During an OTA the primary user's WebView state might differ from other users', so
                 // ignore the state of that user during boot.
-                && (isFallbackEnabled || intent == null)) {
-            // Uninstall and disable fallback package for all users.
-            context.getPackageManager().deletePackage(fallbackProvider.packageName,
-                    new IPackageDeleteObserver.Stub() {
-                public void packageDeleted(String packageName, int returnCode) {
-                    // Ignore returnCode since the deletion could fail, e.g. we might be trying
-                    // to delete a non-updated system-package (and we should still disable the
-                    // package)
-                    UserManager userManager =
-                        (UserManager)context.getSystemService(Context.USER_SERVICE);
-                    // Disable the fallback package for all users.
-                    for(UserInfo userInfo : userManager.getUsers()) {
-                        enablePackageForUser(packageName, false, userInfo.id);
-                    }
-                }
-            }, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS);
+                && (isFallbackEnabled || isBoot)) {
+            mSystemInterface.uninstallAndDisablePackageForAllUsers(getContext(),
+                    fallbackProvider.packageName);
         } else if (!existsValidNonFallbackProvider
                 // During an OTA the primary user's WebView state might differ from other users', so
                 // ignore the state of that user during boot.
-                && (!isFallbackEnabled || intent==null)) {
+                && (!isFallbackEnabled || isBoot)) {
             // Enable the fallback package for all users.
-            UserManager userManager =
-                (UserManager)context.getSystemService(Context.USER_SERVICE);
-            for(UserInfo userInfo : userManager.getUsers()) {
-                enablePackageForUser(fallbackProvider.packageName, true, userInfo.id);
-            }
+            mSystemInterface.enablePackageForAllUsers(getContext(),
+                    fallbackProvider.packageName, true);
         }
     }
 
-    private static boolean isFallbackLogicEnabled() {
-        // Note that this is enabled by default (i.e. if the setting hasn't been set).
-        return Settings.Global.getInt(AppGlobals.getInitialApplication().getContentResolver(),
-                Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, 1) == 1;
-    }
-
-    private static void enableFallbackLogic(boolean enable) {
-        Settings.Global.putInt(AppGlobals.getInitialApplication().getContentResolver(),
-                Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, enable ? 1 : 0);
-    }
-
     /**
-     * Returns the only fallback provider, or null if there is none.
+     * Returns the only fallback provider in the set of given packages, or null if there is none.
      */
     private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) {
         for (WebViewProviderInfo provider : webviewPackages) {
@@ -317,188 +240,372 @@
     }
 
     private boolean isFallbackPackage(String packageName) {
-        if (packageName == null || !isFallbackLogicEnabled()) return false;
+        if (packageName == null || !mSystemInterface.isFallbackLogicEnabled()) return false;
 
-        WebViewProviderInfo[] webviewPackages = mWebViewUtility.getWebViewPackages();
+        WebViewProviderInfo[] webviewPackages = mSystemInterface.getWebViewPackages();
         WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewPackages);
         return (fallbackProvider != null
                 && packageName.equals(fallbackProvider.packageName));
     }
 
     /**
-     * Perform any WebView loading preparations that must happen at boot from the system server,
-     * after the package manager has started or after an update to the webview is installed.
-     * This must be called in the system server.
-     * Currently, this means spawning the child processes which will create the relro files.
+     * Class that decides what WebView implementation to use and prepares that implementation for
+     * use.
      */
-    public void prepareWebViewInSystemServer() {
-        updateFallbackState(getContext(), null);
-        try {
-            synchronized(this) {
-                mCurrentWebViewPackage = findPreferredWebViewPackage();
-                onWebViewProviderChanged(mCurrentWebViewPackage);
-            }
-        } catch (Throwable t) {
-            // Log and discard errors at this stage as we must not crash the system server.
-            Slog.e(TAG, "error preparing webview provider from system server", t);
+    private static class WebViewUpdater {
+        private Context mContext;
+        private SystemInterface mSystemInterface;
+        private int mMinimumVersionCode = -1;
+
+        public WebViewUpdater(Context context, SystemInterface systemInterface) {
+            mContext = context;
+            mSystemInterface = systemInterface;
         }
-    }
 
+        private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000.
 
-    /**
-     * Change WebView provider and provider setting and kill packages using the old provider.
-     * Return the new provider (in case we are in the middle of creating relro files this new
-     * provider will not be in use directly, but will when the relros are done).
-     */
-    private String changeProviderAndSetting(String newProviderName) {
-        PackageInfo oldPackage = null;
-        PackageInfo newPackage = null;
-        synchronized(this) {
-            oldPackage = mCurrentWebViewPackage;
-            mWebViewUtility.updateUserSetting(getContext(), newProviderName);
+        // Keeps track of the number of running relro creations
+        private int mNumRelroCreationsStarted = 0;
+        private int mNumRelroCreationsFinished = 0;
+        // Implies that we need to rerun relro creation because we are using an out-of-date package
+        private boolean mWebViewPackageDirty = false;
+        private boolean mAnyWebViewInstalled = false;
 
-            try {
-                newPackage = findPreferredWebViewPackage();
-                if (oldPackage != null && newPackage.packageName.equals(oldPackage.packageName)) {
-                    // If we don't perform the user change, revert the settings change.
-                    mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName);
-                    return newPackage.packageName;
+        private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
+
+        // The WebView package currently in use (or the one we are preparing).
+        private PackageInfo mCurrentWebViewPackage = null;
+
+        private Object mLock = new Object();
+
+        public void packageStateChanged(String packageName, int changedState) {
+            for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
+                String webviewPackage = provider.packageName;
+
+                if (webviewPackage.equals(packageName)) {
+                    boolean updateWebView = false;
+                    boolean removedOrChangedOldPackage = false;
+                    String oldProviderName = null;
+                    PackageInfo newPackage = null;
+                    synchronized(mLock) {
+                        try {
+                            newPackage = findPreferredWebViewPackage();
+                            if (mCurrentWebViewPackage != null)
+                                oldProviderName = mCurrentWebViewPackage.packageName;
+                            // Only trigger update actions if the updated package is the one
+                            // that will be used, or the one that was in use before the
+                            // update, or if we haven't seen a valid WebView package before.
+                            updateWebView =
+                                provider.packageName.equals(newPackage.packageName)
+                                || provider.packageName.equals(oldProviderName)
+                                || mCurrentWebViewPackage == null;
+                            // We removed the old package if we received an intent to remove
+                            // or replace the old package.
+                            removedOrChangedOldPackage =
+                                provider.packageName.equals(oldProviderName);
+                            if (updateWebView) {
+                                onWebViewProviderChanged(newPackage);
+                            }
+                        } catch (WebViewFactory.MissingWebViewPackageException e) {
+                            Slog.e(TAG, "Could not find valid WebView package to create " +
+                                    "relro with " + e);
+                        }
+                    }
+                    if(updateWebView && !removedOrChangedOldPackage
+                            && oldProviderName != null) {
+                        // If the provider change is the result of adding or replacing a
+                        // package that was not the previous provider then we must kill
+                        // packages dependent on the old package ourselves. The framework
+                        // only kills dependents of packages that are being removed.
+                        mSystemInterface.killPackageDependents(oldProviderName);
+                    }
+                    return;
                 }
-            } catch (WebViewFactory.MissingWebViewPackageException e) {
-                Slog.e(TAG, "Tried to change WebView provider but failed to fetch WebView package "
-                        + e);
-                // If we don't perform the user change but don't have an installed WebView package,
-                // we will have changed the setting and it will be used when a package is available.
-                return newProviderName;
             }
-            onWebViewProviderChanged(newPackage);
         }
-        // Kill apps using the old provider
-        if (oldPackage != null) {
-            mWebViewUtility.killPackageDependents(oldPackage.packageName);
+
+        public void prepareWebViewInSystemServer() {
+            try {
+                synchronized(mLock) {
+                    mCurrentWebViewPackage = findPreferredWebViewPackage();
+                    onWebViewProviderChanged(mCurrentWebViewPackage);
+                }
+            } catch (Throwable t) {
+                // Log and discard errors at this stage as we must not crash the system server.
+                Slog.e(TAG, "error preparing webview provider from system server", t);
+            }
         }
-        return newPackage.packageName;
-    }
 
-    /**
-     * This is called when we change WebView provider, either when the current provider is updated
-     * or a new provider is chosen / takes precedence.
-     */
-    private void onWebViewProviderChanged(PackageInfo newPackage) {
-        synchronized(this) {
-            mAnyWebViewInstalled = true;
-            if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
-                mCurrentWebViewPackage = newPackage;
-                mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName);
+        /**
+         * Change WebView provider and provider setting and kill packages using the old provider.
+         * Return the new provider (in case we are in the middle of creating relro files this new
+         * provider will not be in use directly, but will when the relros are done).
+         */
+        public String changeProviderAndSetting(String newProviderName) {
+            PackageInfo oldPackage = null;
+            PackageInfo newPackage = null;
+            synchronized(mLock) {
+                oldPackage = mCurrentWebViewPackage;
+                mSystemInterface.updateUserSetting(mContext, newProviderName);
 
-                // The relro creations might 'finish' (not start at all) before
-                // WebViewFactory.onWebViewProviderChanged which means we might not know the number
-                // of started creations before they finish.
-                mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
-                mNumRelroCreationsFinished = 0;
-                mNumRelroCreationsStarted = mWebViewUtility.onWebViewProviderChanged(newPackage);
-                // If the relro creations finish before we know the number of started creations we
-                // will have to do any cleanup/notifying here.
+                try {
+                    newPackage = findPreferredWebViewPackage();
+                    if (oldPackage != null
+                            && newPackage.packageName.equals(oldPackage.packageName)) {
+                        // If we don't perform the user change, revert the settings change.
+                        mSystemInterface.updateUserSetting(mContext, newPackage.packageName);
+                        return newPackage.packageName;
+                    }
+                } catch (WebViewFactory.MissingWebViewPackageException e) {
+                    Slog.e(TAG, "Tried to change WebView provider but failed to fetch WebView " +
+                            "package " + e);
+                    // If we don't perform the user change but don't have an installed WebView
+                    // package, we will have changed the setting and it will be used when a package
+                    // is available.
+                    return newProviderName;
+                }
+                onWebViewProviderChanged(newPackage);
+            }
+            // Kill apps using the old provider
+            if (oldPackage != null) {
+                mSystemInterface.killPackageDependents(oldPackage.packageName);
+            }
+            return newPackage.packageName;
+        }
+
+        /**
+         * This is called when we change WebView provider, either when the current provider is
+         * updated or a new provider is chosen / takes precedence.
+         */
+        private void onWebViewProviderChanged(PackageInfo newPackage) {
+            synchronized(mLock) {
+                mAnyWebViewInstalled = true;
+                if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+                    mCurrentWebViewPackage = newPackage;
+                    mSystemInterface.updateUserSetting(mContext, newPackage.packageName);
+
+                    // The relro creations might 'finish' (not start at all) before
+                    // WebViewFactory.onWebViewProviderChanged which means we might not know the
+                    // number of started creations before they finish.
+                    mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
+                    mNumRelroCreationsFinished = 0;
+                    mNumRelroCreationsStarted =
+                        mSystemInterface.onWebViewProviderChanged(newPackage);
+                    // If the relro creations finish before we know the number of started creations
+                    // we will have to do any cleanup/notifying here.
+                    checkIfRelrosDoneLocked();
+                } else {
+                    mWebViewPackageDirty = true;
+                }
+            }
+        }
+
+        private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
+            WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
+            List<ProviderAndPackageInfo> providers = new ArrayList<>();
+            for(int n = 0; n < allProviders.length; n++) {
+                try {
+                    PackageInfo packageInfo =
+                        mSystemInterface.getPackageInfoForProvider(allProviders[n]);
+                    if (isValidProvider(allProviders[n], packageInfo)) {
+                        providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
+                    }
+                } catch (NameNotFoundException e) {
+                    // Don't add non-existent packages
+                }
+            }
+            return providers.toArray(new ProviderAndPackageInfo[providers.size()]);
+        }
+
+        /**
+         * Fetch only the currently valid WebView packages.
+         **/
+        public WebViewProviderInfo[] getValidWebViewPackages() {
+            ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
+            WebViewProviderInfo[] providers =
+                new WebViewProviderInfo[providersAndPackageInfos.length];
+            for(int n = 0; n < providersAndPackageInfos.length; n++) {
+                providers[n] = providersAndPackageInfos[n].provider;
+            }
+            return providers;
+        }
+
+
+        private class ProviderAndPackageInfo {
+            public final WebViewProviderInfo provider;
+            public final PackageInfo packageInfo;
+
+            public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) {
+                this.provider = provider;
+                this.packageInfo = packageInfo;
+            }
+        }
+
+        /**
+         * Returns either the package info of the WebView provider determined in the following way:
+         * If the user has chosen a provider then use that if it is valid,
+         * otherwise use the first package in the webview priority list that is valid.
+         *
+         */
+        private PackageInfo findPreferredWebViewPackage() {
+            ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
+
+            String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(mContext);
+
+            // If the user has chosen provider, use that
+            for (ProviderAndPackageInfo providerAndPackage : providers) {
+                if (providerAndPackage.provider.packageName.equals(userChosenProvider)
+                        && isEnabledPackage(providerAndPackage.packageInfo)) {
+                    return providerAndPackage.packageInfo;
+                }
+            }
+
+            // User did not choose, or the choice failed; use the most stable provider that is
+            // enabled and available by default (not through user choice).
+            for (ProviderAndPackageInfo providerAndPackage : providers) {
+                if (providerAndPackage.provider.availableByDefault
+                        && isEnabledPackage(providerAndPackage.packageInfo)) {
+                    return providerAndPackage.packageInfo;
+                }
+            }
+
+            // Could not find any enabled package either, use the most stable provider.
+            for (ProviderAndPackageInfo providerAndPackage : providers) {
+                return providerAndPackage.packageInfo;
+            }
+
+            mAnyWebViewInstalled = false;
+            throw new WebViewFactory.MissingWebViewPackageException(
+                    "Could not find a loadable WebView package");
+        }
+
+        public void notifyRelroCreationCompleted() {
+            synchronized (mLock) {
+                mNumRelroCreationsFinished++;
                 checkIfRelrosDoneLocked();
-            } else {
-                mWebViewPackageDirty = true;
             }
         }
-    }
 
-    private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
-        WebViewProviderInfo[] allProviders = mWebViewUtility.getWebViewPackages();
-        List<ProviderAndPackageInfo> providers = new ArrayList<>();
-        for(int n = 0; n < allProviders.length; n++) {
-            try {
-                PackageInfo packageInfo = getPackageInfoForProvider(allProviders[n]);
-                if (isValidProvider(allProviders[n], packageInfo)) {
-                    providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
+        public WebViewProviderResponse waitForAndGetProvider() {
+            PackageInfo webViewPackage = null;
+            final long NS_PER_MS = 1000000;
+            final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
+            boolean webViewReady = false;
+            int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS;
+            synchronized (mLock) {
+                webViewReady = webViewIsReadyLocked();
+                while (!webViewReady) {
+                    final long timeNowMs = System.nanoTime() / NS_PER_MS;
+                    if (timeNowMs >= timeoutTimeMs) break;
+                    try {
+                        mLock.wait(timeoutTimeMs - timeNowMs);
+                    } catch (InterruptedException e) {}
+                    webViewReady = webViewIsReadyLocked();
                 }
-            } catch (NameNotFoundException e) {
-                // Don't add non-existent packages
+                // Make sure we return the provider that was used to create the relro file
+                webViewPackage = mCurrentWebViewPackage;
+                if (webViewReady) {
+                } else if (!mAnyWebViewInstalled) {
+                    webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
+                } else {
+                    // Either the current relro creation  isn't done yet, or the new relro creatioin
+                    // hasn't kicked off yet (the last relro creation used an out-of-date WebView).
+                    webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
+                }
             }
+            if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
+            return new WebViewProviderResponse(webViewPackage, webViewStatus);
         }
-        return providers.toArray(new ProviderAndPackageInfo[providers.size()]);
-    }
 
-    /**
-     * Fetch only the currently valid WebView packages.
-     **/
-    private WebViewProviderInfo[] getValidWebViewPackages() {
-        ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
-        WebViewProviderInfo[] providers = new WebViewProviderInfo[providersAndPackageInfos.length];
-        for(int n = 0; n < providersAndPackageInfos.length; n++) {
-            providers[n] = providersAndPackageInfos[n].provider;
-        }
-        return providers;
-    }
-
-    private class ProviderAndPackageInfo {
-        public final WebViewProviderInfo provider;
-        public final PackageInfo packageInfo;
-
-        public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) {
-            this.provider = provider;
-            this.packageInfo = packageInfo;
-        }
-    }
-
-    /**
-     * Returns either the package info of the WebView provider determined in the following way:
-     * If the user has chosen a provider then use that if it is valid,
-     * otherwise use the first package in the webview priority list that is valid.
-     *
-     * @hide
-     */
-    private PackageInfo findPreferredWebViewPackage() {
-        ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
-
-        String userChosenProvider = mWebViewUtility.getUserChosenWebViewProvider(getContext());
-
-        // If the user has chosen provider, use that
-        for (ProviderAndPackageInfo providerAndPackage : providers) {
-            if (providerAndPackage.provider.packageName.equals(userChosenProvider)
-                    && isEnabledPackage(providerAndPackage.packageInfo)) {
-                return providerAndPackage.packageInfo;
+        public String getCurrentWebViewPackageName() {
+            synchronized(mLock) {
+                if (mCurrentWebViewPackage == null)
+                    return null;
+                return mCurrentWebViewPackage.packageName;
             }
         }
 
-        // User did not choose, or the choice failed; use the most stable provider that is
-        // enabled and available by default (not through user choice).
-        for (ProviderAndPackageInfo providerAndPackage : providers) {
-            if (providerAndPackage.provider.availableByDefault
-                    && isEnabledPackage(providerAndPackage.packageInfo)) {
-                return providerAndPackage.packageInfo;
+        /**
+         * Returns whether WebView is ready and is not going to go through its preparation phase
+         * again directly.
+         */
+        private boolean webViewIsReadyLocked() {
+            return !mWebViewPackageDirty
+                && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
+                // The current package might be replaced though we haven't received an intent
+                // declaring this yet, the following flag makes anyone loading WebView to wait in
+                // this case.
+                && mAnyWebViewInstalled;
+        }
+
+        private void checkIfRelrosDoneLocked() {
+            if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+                if (mWebViewPackageDirty) {
+                    mWebViewPackageDirty = false;
+                    // If we have changed provider since we started the relro creation we need to
+                    // redo the whole process using the new package instead.
+                    PackageInfo newPackage = findPreferredWebViewPackage();
+                    onWebViewProviderChanged(newPackage);
+                } else {
+                    mLock.notifyAll();
+                }
             }
         }
 
-        // Could not find any enabled package either, use the most stable provider.
-        for (ProviderAndPackageInfo providerAndPackage : providers) {
-            return providerAndPackage.packageInfo;
+        /**
+         * Returns whether this provider is valid for use as a WebView provider.
+         */
+        public boolean isValidProvider(WebViewProviderInfo configInfo,
+                PackageInfo packageInfo) {
+            if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
+                    && packageInfo.versionCode < getMinimumVersionCode()
+                    && !mSystemInterface.systemIsDebuggable()) {
+                // Non-system package webview providers may be downgraded arbitrarily low, prevent
+                // that by enforcing minimum version code. This check is only enforced for user
+                // builds.
+                return false;
+            }
+            if (providerHasValidSignature(configInfo, packageInfo, mSystemInterface) &&
+                    WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) {
+                return true;
+            }
+            return false;
         }
 
-        mAnyWebViewInstalled = false;
-        throw new WebViewFactory.MissingWebViewPackageException(
-                "Could not find a loadable WebView package");
-    }
+        /**
+         * Gets the minimum version code allowed for a valid provider. It is the minimum versionCode
+         * of all available-by-default and non-fallback WebView provider packages. If there is no
+         * such WebView provider package on the system, then return -1, which means all positive
+         * versionCode WebView packages are accepted.
+         */
+        private int getMinimumVersionCode() {
+            if (mMinimumVersionCode > 0) {
+                return mMinimumVersionCode;
+            }
 
-    /**
-     * Returns whether this provider is valid for use as a WebView provider.
-     */
-    private static boolean isValidProvider(WebViewProviderInfo configInfo,
-            PackageInfo packageInfo) {
-        if (providerHasValidSignature(configInfo, packageInfo) &&
-                WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) {
-            return true;
+            for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
+                if (provider.availableByDefault && !provider.isFallback) {
+                    try {
+                        int versionCode =
+                            mSystemInterface.getFactoryPackageVersion(provider.packageName);
+                        if (mMinimumVersionCode < 0 || versionCode < mMinimumVersionCode) {
+                            mMinimumVersionCode = versionCode;
+                        }
+                    } catch (PackageManager.NameNotFoundException e) {
+                        // Safe to ignore.
+                    }
+                }
+            }
+
+            return mMinimumVersionCode;
         }
-        return false;
     }
 
     private static boolean providerHasValidSignature(WebViewProviderInfo provider,
-            PackageInfo packageInfo) {
-        if (Build.IS_DEBUGGABLE)
+            PackageInfo packageInfo, SystemInterface systemInterface) {
+        if (systemInterface.systemIsDebuggable()) {
             return true;
+        }
         Signature[] packageSignatures;
         // If no signature is declared, instead check whether the package is included in the
         // system.
@@ -527,40 +634,16 @@
         return packageInfo.applicationInfo.enabled;
     }
 
-    private static PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
-            throws NameNotFoundException {
-        PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
-        return pm.getPackageInfo(configInfo.packageName, PACKAGE_FLAGS);
-    }
-
-    // flags declaring we want extra info from the package manager for webview providers
-    private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
-            | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
-
     /**
-     * Returns whether WebView is ready and is not going to go through its preparation phase again
-     * directly.
+     * Returns whether the entire package from an ACTION_PACKAGE_CHANGED intent was changed (rather
+     * than just one of its components).
+     * @hide
      */
-    private boolean webViewIsReadyLocked() {
-        return !mWebViewPackageDirty
-            && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
-            // The current package might be replaced though we haven't received an intent declaring
-            // this yet, the following flag makes anyone loading WebView to wait in this case.
-            && mAnyWebViewInstalled;
-    }
-
-    private void checkIfRelrosDoneLocked() {
-        if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
-            if (mWebViewPackageDirty) {
-                mWebViewPackageDirty = false;
-                // If we have changed provider since we started the relro creation we need to
-                // redo the whole process using the new package instead.
-                PackageInfo newPackage = findPreferredWebViewPackage();
-                onWebViewProviderChanged(newPackage);
-            } else {
-                this.notifyAll();
-            }
-        }
+    public static boolean entirePackageChanged(Intent intent) {
+        String[] componentList =
+            intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+        return Arrays.asList(componentList).contains(
+                intent.getDataString().substring("package:".length()));
     }
 
     private class BinderService extends IWebViewUpdateService.Stub {
@@ -590,10 +673,7 @@
 
             long callingId = Binder.clearCallingIdentity();
             try {
-                synchronized (WebViewUpdateService.this) {
-                    mNumRelroCreationsFinished++;
-                    checkIfRelrosDoneLocked();
-                }
+                WebViewUpdateService.this.mWebViewUpdater.notifyRelroCreationCompleted();
             } finally {
                 Binder.restoreCallingIdentity(callingId);
             }
@@ -613,34 +693,7 @@
                 throw new IllegalStateException("Cannot create a WebView from the SystemServer");
             }
 
-            PackageInfo webViewPackage = null;
-            final long NS_PER_MS = 1000000;
-            final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
-            boolean webViewReady = false;
-            int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS;
-            synchronized (WebViewUpdateService.this) {
-                webViewReady = WebViewUpdateService.this.webViewIsReadyLocked();
-                while (!webViewReady) {
-                    final long timeNowMs = System.nanoTime() / NS_PER_MS;
-                    if (timeNowMs >= timeoutTimeMs) break;
-                    try {
-                        WebViewUpdateService.this.wait(timeoutTimeMs - timeNowMs);
-                    } catch (InterruptedException e) {}
-                    webViewReady = WebViewUpdateService.this.webViewIsReadyLocked();
-                }
-                // Make sure we return the provider that was used to create the relro file
-                webViewPackage = WebViewUpdateService.this.mCurrentWebViewPackage;
-                if (webViewReady) {
-                } else if (!mAnyWebViewInstalled) {
-                    webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
-                } else {
-                    // Either the current relro creation  isn't done yet, or the new relro creatioin
-                    // hasn't kicked off yet (the last relro creation used an out-of-date WebView).
-                    webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
-                }
-            }
-            if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
-            return new WebViewProviderResponse(webViewPackage, webViewStatus);
+            return WebViewUpdateService.this.mWebViewUpdater.waitForAndGetProvider();
         }
 
         /**
@@ -659,26 +712,28 @@
                 throw new SecurityException(msg);
             }
 
-            return WebViewUpdateService.this.changeProviderAndSetting(newProvider);
+            long callingId = Binder.clearCallingIdentity();
+            try {
+                return WebViewUpdateService.this.mWebViewUpdater.changeProviderAndSetting(
+                        newProvider);
+            } finally {
+                Binder.restoreCallingIdentity(callingId);
+            }
         }
 
         @Override // Binder call
         public WebViewProviderInfo[] getValidWebViewPackages() {
-            return WebViewUpdateService.this.getValidWebViewPackages();
+            return WebViewUpdateService.this.mWebViewUpdater.getValidWebViewPackages();
         }
 
         @Override // Binder call
         public WebViewProviderInfo[] getAllWebViewPackages() {
-            return WebViewUpdateService.this.mWebViewUtility.getWebViewPackages();
+            return WebViewUpdateService.this.mSystemInterface.getWebViewPackages();
         }
 
         @Override // Binder call
         public String getCurrentWebViewPackageName() {
-            synchronized(WebViewUpdateService.this) {
-                if (WebViewUpdateService.this.mCurrentWebViewPackage == null)
-                    return null;
-                return WebViewUpdateService.this.mCurrentWebViewPackage.packageName;
-            }
+            return WebViewUpdateService.this.mWebViewUpdater.getCurrentWebViewPackageName();
         }
 
         @Override // Binder call
@@ -699,7 +754,7 @@
                 throw new SecurityException(msg);
             }
 
-            WebViewUpdateService.enableFallbackLogic(enable);
+            WebViewUpdateService.this.mSystemInterface.enableFallbackLogic(enable);
         }
     }
 }
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
index a9461e8..68448f3 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
@@ -36,12 +36,13 @@
 
         final PrintWriter pw = getOutPrintWriter();
         try {
-            // TODO(gsennton) add command for changing WebView provider
             switch(cmd) {
                 case "enable-redundant-packages":
                     return enableFallbackLogic(false);
                 case "disable-redundant-packages":
                     return enableFallbackLogic(true);
+                case "set-webview-implementation":
+                    return setWebViewImplementation();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -58,6 +59,21 @@
         return 0;
     }
 
+    private int setWebViewImplementation() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        String shellChosenPackage = getNextArg();
+        String newPackage = mInterface.changeProviderAndSetting(shellChosenPackage);
+        if (shellChosenPackage.equals(newPackage)) {
+            pw.println("Success");
+            return 0;
+        } else {
+            pw.println(String.format(
+                        "Failed to switch to %s, the WebView implementation is now provided by %s.",
+                        shellChosenPackage, newPackage));
+            return 1;
+        }
+    }
+
     @Override
     public void onHelp() {
         PrintWriter pw = getOutPrintWriter();
@@ -72,6 +88,8 @@
         pw.println("  disable-redundant-packages");
         pw.println("    Disallow installing and enabling fallback packages when a more-preferred");
         pw.println("    package is available.");
+        pw.println("  set-webview-implementation PACKAGE");
+        pw.println("    Set the WebView implementation to the specified package.");
         pw.println();
     }
 }
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index b501398..bae628a 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -39,6 +39,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
@@ -1213,6 +1214,8 @@
             window.type = windowState.mAttrs.type;
             window.layer = windowState.mLayer;
             window.token = windowState.mClient.asBinder();
+            window.title = windowState.mAttrs.getTitle();
+            window.accessibilityIdOfAnchor = windowState.mAttrs.accessibilityIdOfAnchor;
 
             WindowState attachedWindow = windowState.mAttachedWindow;
             if (attachedWindow != null) {
@@ -1285,6 +1288,12 @@
                     && !oldWindow.childTokens.equals(newWindow.childTokens)) {
                 return true;
             }
+            if (!TextUtils.equals(oldWindow.title, newWindow.title)) {
+                return true;
+            }
+            if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) {
+                return true;
+            }
             return false;
         }
 
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index d684278..11b01cc 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -881,7 +881,7 @@
      * when a thumbnail is specified with the pending animation override.
      */
     Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, @Nullable Rect contentInsets,
-            Bitmap thumbnailHeader, final int taskId, int orientation) {
+            Bitmap thumbnailHeader, final int taskId, int uiMode, int orientation) {
         Animation a;
         final int thumbWidthI = thumbnailHeader.getWidth();
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -896,7 +896,7 @@
         final float toY;
         final float pivotX;
         final float pivotY;
-        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+        if (isTvUiMode(uiMode) || orientation == Configuration.ORIENTATION_PORTRAIT) {
             fromX = mTmpRect.left;
             fromY = mTmpRect.top;
 
@@ -1028,7 +1028,7 @@
      * activity that is leaving, and the activity that is entering.
      */
     Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
-            int orientation, int transit, Rect containingFrame, Rect contentInsets,
+            int uiMode, int orientation, int transit, Rect containingFrame, Rect contentInsets,
             @Nullable Rect surfaceInsets, boolean freeform, int taskId) {
         Animation a;
         final int appWidth = containingFrame.width();
@@ -1067,8 +1067,7 @@
                     mTmpFromClipRect.inset(contentInsets);
                     mNextAppTransitionInsets.set(contentInsets);
 
-                    if (orientation == Configuration.ORIENTATION_PORTRAIT) {
-                        // We scale the width and clip to the top/left square
+                    if (isTvUiMode(uiMode) || orientation == Configuration.ORIENTATION_PORTRAIT) {
                         // We scale the width and clip to the top/left square
                         float scale = thumbWidth /
                                 (appWidth - contentInsets.left - contentInsets.right);
@@ -1401,7 +1400,7 @@
      *                      to the recents thumbnail and hence need to account for the surface being
      *                      bigger.
      */
-    Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
+    Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, int uiMode,
             int orientation, Rect frame, Rect displayFrame, Rect insets,
             @Nullable Rect surfaceInsets, boolean isVoiceInteraction, boolean freeform,
             int taskId) {
@@ -1481,7 +1480,7 @@
             mNextAppTransitionScaleUp =
                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
             a = createAspectScaledThumbnailEnterExitAnimationLocked(
-                    getThumbnailTransitionState(enter), orientation, transit, frame,
+                    getThumbnailTransitionState(enter), uiMode, orientation, transit, frame,
                     insets, surfaceInsets, freeform, taskId);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
                 String animName = mNextAppTransitionScaleUp ?
@@ -1922,4 +1921,11 @@
         }
         return prepared;
     }
+
+    /**
+     * @return whether the specified {@param uiMode} is the TV mode.
+     */
+    private boolean isTvUiMode(int uiMode) {
+        return (uiMode & Configuration.UI_MODE_TYPE_TELEVISION) > 0;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 97d0ae0..3ec02b9 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -183,7 +183,12 @@
 
         for (int i = mState.size() - 1; i >= 0; i--) {
             DimLayer.DimLayerUser user = mState.keyAt(i);
-            if (user.isFullscreen()) {
+            DimLayerState state = mState.valueAt(i);
+            // We have to check that we are acutally the shared fullscreen layer
+            // for this path. If we began as non fullscreen and became fullscreen
+            // (e.g. Docked stack closing), then we may not be the shared layer
+            // and we have to make sure we always animate the layer.
+            if (user.isFullscreen() && state.dimLayer == mSharedFullScreenDimLayer) {
                 fullScreen = i;
                 if (mState.valueAt(i).continueDimming) {
                     fullScreenAndDimming = i;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 68ea4df..6ac71c7 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -76,8 +76,8 @@
 
     private final WindowManagerService mService;
     private final DisplayContent mDisplayContent;
-    private final int mDividerWindowWidth;
-    private final int mDividerInsets;
+    private int mDividerWindowWidth;
+    private int mDividerInsets;
     private boolean mResizing;
     private WindowState mWindow;
     private final Rect mTmpRect = new Rect();
@@ -105,14 +105,23 @@
         mService = service;
         mDisplayContent = displayContent;
         final Context context = service.mContext;
-        mDividerWindowWidth = context.getResources().getDimensionPixelSize(
-                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(),
                 "DockedStackDim");
         mMinimizedDockInterpolator = AnimationUtils.loadInterpolator(
                 context, android.R.interpolator.fast_out_slow_in);
+        loadDimens();
+    }
+
+    private void loadDimens() {
+        final Context context = mService.mContext;
+        mDividerWindowWidth = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_thickness);
+        mDividerInsets = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_insets);
+    }
+
+    void onConfigurationChanged() {
+        loadDimens();
     }
 
     boolean isResizing() {
@@ -243,6 +252,9 @@
             }
         }
         mDockedStackListeners.finishBroadcast();
+        if (!exists) {
+            setMinimizedDockedStack(false);
+        }
     }
 
     void notifyDockedStackMinimizedChanged(boolean minimizedDock, long animDuration) {
@@ -263,6 +275,7 @@
         notifyDockedDividerVisibilityChanged(wasVisible());
         notifyDockedStackExistsChanged(
                 mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID) != null);
+        notifyDockedStackMinimizedChanged(mMinimizedDock, 0 /* animDuration */);
     }
 
     void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
@@ -338,12 +351,13 @@
      * @param animate Whether to animate the change.
      */
     private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
-        if (minimizedDock == mMinimizedDock
+        final boolean wasMinimized = mMinimizedDock;
+        mMinimizedDock = minimizedDock;
+        if (minimizedDock == wasMinimized
                 || mDisplayContent.getDockedStackVisibleForUserLocked() == null) {
             return;
         }
 
-        mMinimizedDock = minimizedDock;
         mAnimatingForIme = false;
         if (minimizedDock) {
             if (animate) {
@@ -369,13 +383,13 @@
 
     private void setMinimizedDockedStack(boolean minimized) {
         final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
+        notifyDockedStackMinimizedChanged(minimized, 0);
         if (stack == null) {
             return;
         }
         if (stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f)) {
             mService.mWindowPlacerLocked.performSurfacePlacement();
         }
-        notifyDockedStackMinimizedChanged(minimized, 0);
     }
 
     private boolean isAnimationMaximizing() {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1f03c04..8a9ace7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -425,7 +425,7 @@
         if (mFullscreen
                 || !StackId.isTaskResizeableByDockedStack(mStack.mStackId)
                 || displayContent == null
-                || displayContent.getDockedStackLocked() != null) {
+                || displayContent.getDockedStackVisibleForUserLocked() != null) {
             return true;
         }
         return false;
@@ -595,6 +595,12 @@
                 if (win.mHasSurface && !resizingWindows.contains(win)) {
                     if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + win);
                     resizingWindows.add(win);
+
+                    // If we are not drag resizing, force recreating of a new surface so updating
+                    // the content and positioning that surface will be in sync.
+                    if (!win.computeDragResizing()) {
+                        win.mResizedWhileNotDragResizing = true;
+                    }
                 }
                 if (win.isGoneForLayoutLw()) {
                     win.mResizedWhileGone = true;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 0bf7102..3430ac9 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -37,8 +37,8 @@
 
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
@@ -89,6 +89,9 @@
     // Device rotation as of the last time {@link #mBounds} was set.
     int mRotation;
 
+    /** Density as of last time {@link #mBounds} was set. */
+    int mDensity;
+
     /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
     DimLayer mAnimationBackgroundSurface;
 
@@ -128,6 +131,10 @@
     // in which case a second window animation would cause jitter.
     private boolean mFreezeMovementAnimations = false;
 
+    // Temporary storage for the new bounds that should be used after the configuration change.
+    // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
+    private final Rect mBoundsAfterRotation = new Rect();
+
     TaskStack(WindowManagerService service, int stackId) {
         mService = service;
         mStackId = stackId;
@@ -246,9 +253,11 @@
     private boolean setBounds(Rect bounds) {
         boolean oldFullscreen = mFullscreen;
         int rotation = Surface.ROTATION_0;
+        int density = DENSITY_DPI_UNDEFINED;
         if (mDisplayContent != null) {
             mDisplayContent.getLogicalDisplayRect(mTmpRect);
             rotation = mDisplayContent.getDisplayInfo().rotation;
+            density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
             mFullscreen = bounds == null;
             if (mFullscreen) {
                 bounds = mTmpRect;
@@ -270,6 +279,7 @@
 
         mBounds.set(bounds);
         mRotation = rotation;
+        mDensity = density;
 
         updateAdjustedBounds();
 
@@ -339,32 +349,34 @@
 
         mTmpRect2.set(mBounds);
         final int newRotation = mDisplayContent.getDisplayInfo().rotation;
-        if (mRotation == newRotation) {
+        final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
+        if (mRotation == newRotation && mDensity == newDensity) {
             setBounds(mTmpRect2);
         } else {
             mLastUpdateDisplayInfoRotation = newRotation;
-            updateBoundsAfterRotation();
+            updateBoundsAfterConfigChange(true);
         }
     }
 
-    void onConfigurationChanged() {
+    boolean onConfigurationChanged() {
         mLastConfigChangedRotation = getDisplayInfo().rotation;
-        updateBoundsAfterRotation();
+        return updateBoundsAfterConfigChange(false);
     }
 
-    void updateBoundsAfterRotation() {
+    boolean updateBoundsAfterConfigChange(boolean scheduleResize) {
         if (mLastConfigChangedRotation != mLastUpdateDisplayInfoRotation) {
             // We wait for the rotation values after configuration change and display info. update
             // to be equal before updating the bounds due to rotation change otherwise things might
             // get out of alignment...
-            return;
+            return false;
         }
 
         final int newRotation = getDisplayInfo().rotation;
+        final int newDensity = getDisplayInfo().logicalDensityDpi;
 
-        if (mRotation == newRotation) {
+        if (mRotation == newRotation && mDensity == newDensity) {
             // Nothing to do here if the rotation didn't change
-            return;
+            return false;
         }
 
         mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
@@ -373,11 +385,22 @@
             snapDockedStackAfterRotation(mTmpRect2);
         }
 
-        // Post message to inform activity manager of the bounds change simulating
-        // a one-way call. We do this to prevent a deadlock between window manager
-        // lock and activity manager lock been held.
-        mService.mH.obtainMessage(
-                RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget();
+        if (scheduleResize) {
+            // Post message to inform activity manager of the bounds change simulating
+            // a one-way call. We do this to prevent a deadlock between window manager
+            // lock and activity manager lock been held.
+            mService.mH.obtainMessage(RESIZE_STACK, mStackId,
+                    0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget();
+        } else {
+            mBoundsAfterRotation.set(mTmpRect2);
+        }
+
+        return true;
+    }
+
+    void getBoundsForNewConfiguration(Rect outBounds) {
+        outBounds.set(mBoundsAfterRotation);
+        mBoundsAfterRotation.setEmpty();
     }
 
     /**
@@ -869,6 +892,10 @@
         }
     }
 
+    boolean isAdjustedForMinimizedDock() {
+        return mMinimizeAmount != 0f;
+    }
+
     private boolean adjustForIME(final WindowState imeWin) {
         final int dockedSide = getDockSide();
         final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
@@ -938,9 +965,11 @@
                     (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom);
         } else if (dockSide == DOCKED_LEFT) {
             mTmpAdjustedBounds.set(mBounds);
+            final int width = mBounds.width();
             mTmpAdjustedBounds.right =
                     (int) (minimizeAmount * mDockedStackMinimizeThickness
                             + (1 - minimizeAmount) * mBounds.right);
+            mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
         } else if (dockSide == DOCKED_RIGHT) {
             mTmpAdjustedBounds.set(mBounds);
             mTmpAdjustedBounds.left =
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index f76f03f..6bdcd42 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -191,18 +191,20 @@
     }
 
     private void adjustSpecialWindows() {
-        int layer = mHighestApplicationLayer + 1;
+        int layer = mHighestApplicationLayer + WINDOW_LAYER_MULTIPLIER;
         // For pinned and docked stack window, we want to make them above other windows also when
         // these windows are animating.
         while (!mDockedWindows.isEmpty()) {
             layer = assignAndIncreaseLayerIfNeeded(mDockedWindows.remove(), layer);
         }
 
-        // Leave some space here so the dim layer while dismissing docked/fullscreen stack has space
-        // below the divider but above the app windows. It needs to be below the divider in because
-        // the divider sometimes overlaps the app windows.
-        layer++;
         layer = assignAndIncreaseLayerIfNeeded(mDockDivider, layer);
+
+        if (mDockDivider != null && mDockDivider.isVisibleLw()
+                && mService.mInputMethodWindow != null) {
+            layer = assignAndIncreaseLayerIfNeeded(mService.mInputMethodWindow, layer);
+        }
+
         // We know that we will be animating a relaunching window in the near future, which will
         // receive a z-order increase. We want the replaced window to immediately receive the same
         // treatment, e.g. to be above the dock divider.
@@ -216,13 +218,14 @@
     }
 
     private int assignAndIncreaseLayerIfNeeded(WindowState win, int layer) {
-        if (win != null) {
+        if (win != null && layer > win.mLayer) {
             assignAnimLayer(win, layer);
-            layer++;
+            // Make sure we leave space inbetween normal windows for dims and such.
+            layer += WINDOW_LAYER_MULTIPLIER;
         }
         return layer;
     }
-    
+
     private void assignAnimLayer(WindowState w, int layer) {
         w.mLayer = layer;
         w.mWinAnimator.mAnimLayer = w.mLayer + w.getAnimLayerAdjustment() +
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index dcb4a63..2af324d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -125,6 +125,7 @@
 import com.android.internal.app.IAssistScreenshotReceiver;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IShortcutService;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
@@ -515,6 +516,8 @@
 
     private final SparseIntArray mTmpTaskIds = new SparseIntArray();
 
+    private final ArrayList<Integer> mChangedStackList = new ArrayList();
+
     boolean mForceResizableTasks = false;
 
     int getDragLayerLocked() {
@@ -1366,11 +1369,8 @@
         final int fl = w.mAttrs.flags
                 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
         final int type = w.mAttrs.type;
-        // The dock divider has to sit above the application windows and so does the IME. IME also
-        // needs to sit above the dock divider, so it doesn't get cut in half. We make the dock
-        // divider be a target for IME, so this relationship can occur naturally.
         if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
-                || type == TYPE_APPLICATION_STARTING || type == TYPE_DOCK_DIVIDER) {
+                || type == TYPE_APPLICATION_STARTING) {
             if (DEBUG_INPUT_METHOD) {
                 Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
                 if (!w.isVisibleOrAdding()) {
@@ -2017,7 +2017,13 @@
             final WindowStateAnimator winAnimator = win.mWinAnimator;
             winAnimator.mEnterAnimationPending = true;
             winAnimator.mEnteringAnimation = true;
-            prepareWindowReplacementTransition(atoken);
+            // Check if we need to prepare a transition for replacing window first.
+            if (atoken != null && !prepareWindowReplacementTransition(atoken)) {
+                // If not, check if need to set up a dummy transition during display freeze
+                // so that the unfreeze wait for the apps to draw. This might be needed if
+                // the app is relaunching.
+                prepareNoneTransitionForRelaunching(atoken);
+            }
 
             if (displayContent.isDefaultDisplay) {
                 if (mPolicy.getInsetHintLw(win.mAttrs, mRotation, outContentInsets, outStableInsets,
@@ -2077,10 +2083,10 @@
         return res;
     }
 
-    private void prepareWindowReplacementTransition(AppWindowToken atoken) {
-        if (atoken == null) {
-            return;
-        }
+    /**
+     * Returns true if we're done setting up any transitions.
+     */
+    private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
         atoken.allDrawn = false;
         WindowState replacedWindow = null;
         for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) {
@@ -2093,7 +2099,7 @@
         if (replacedWindow == null) {
             // We expect to already receive a request to remove the old window. If it did not
             // happen, let's just simply add a window.
-            return;
+            return false;
         }
         // We use the visible frame, because we want the animation to morph the window from what
         // was visible to the user to the final destination of the new window.
@@ -2105,6 +2111,19 @@
         mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
                 frame.width(), frame.height());
         executeAppTransition();
+        return true;
+    }
+
+    private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
+        // Set up a none-transition and add the app to opening apps, so that the display
+        // unfreeze wait for the apps to be drawn.
+        // Note that if the display unfroze already because app unfreeze timed out,
+        // we don't set up the transition anymore and just let it go.
+        if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
+            mOpeningApps.add(atoken);
+            prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT);
+            executeAppTransition();
+        }
     }
 
     /**
@@ -2567,7 +2586,7 @@
 
                     try {
 
-                        win.applyGravityAndUpdateFrame();
+                        win.applyGravityAndUpdateFrame(win.mContainingFrame, win.mDisplayFrame);
                         win.mWinAnimator.computeShownFrameLocked();
 
                         win.mWinAnimator.setSurfaceBoundariesLocked(false);
@@ -2916,8 +2935,9 @@
 
         // If we're starting a drag-resize, we'll be changing the surface size as well as
         // notifying the client to render to with an offset from the surface's top-left.
-        if (win.isDragResizeChanged()) {
+        if (win.isDragResizeChanged() || win.mResizedWhileNotDragResizing) {
             win.setDragResizing();
+            win.mResizedWhileNotDragResizing = false;
             // We can only change top level windows to the full-screen surface when
             // resizing (as we only have one full-screen surface). So there is no need
             // to preserve and destroy windows which are attached to another, they
@@ -3039,7 +3059,7 @@
             if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
                     + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
                     + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
-            Animation a = mAppTransition.loadAnimation(lp, transit, enter,
+            Animation a = mAppTransition.loadAnimation(lp, transit, enter, mCurConfiguration.uiMode,
                     mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets,
                     isVoiceInteraction, freeform, atoken.mTask.mTaskId);
             if (a != null) {
@@ -3398,7 +3418,8 @@
             }
         }
 
-        if (isStackVisibleLocked(DOCKED_STACK_ID)
+        if ((isStackVisibleLocked(DOCKED_STACK_ID)
+                && !mStackIdToStack.get(DOCKED_STACK_ID).isAdjustedForMinimizedDock())
                 || isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
             // We don't let app affect the system orientation when in freeform or docked mode since
             // they don't occupy the entire display and their request can conflict with other apps.
@@ -3580,7 +3601,7 @@
     }
 
     @Override
-    public void setNewConfiguration(Configuration config) {
+    public int[] setNewConfiguration(Configuration config) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setNewConfiguration()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -3592,16 +3613,32 @@
                 mWaitingForConfig = false;
                 mLastFinishedFreezeSource = "new-config";
             }
-            onConfigurationChanged();
-            mWindowPlacerLocked.performSurfacePlacement();
+            return onConfigurationChanged();
         }
     }
 
-    private void onConfigurationChanged() {
+    @Override
+    public Rect getBoundsForNewConfiguration(int stackId) {
+        synchronized(mWindowMap) {
+            final TaskStack stack = mStackIdToStack.get(stackId);
+            final Rect outBounds = new Rect();
+            stack.getBoundsForNewConfiguration(outBounds);
+            return outBounds;
+        }
+    }
+
+    private int[] onConfigurationChanged() {
+        mPolicy.onConfigurationChanged();
+        getDefaultDisplayContentLocked().getDockedDividerController().onConfigurationChanged();
+        mChangedStackList.clear();
         for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) {
             final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
-            stack.onConfigurationChanged();
+            if (stack.onConfigurationChanged()) {
+                mChangedStackList.add(stack.mStackId);
+            }
         }
+        return mChangedStackList.isEmpty() ?
+                null : ArrayUtils.convertToIntArray(mChangedStackList);
     }
 
     @Override
@@ -4117,6 +4154,14 @@
             for (int i = 0; i < windowsCount; i++) {
                 WindowState win = wtoken.allAppWindows.get(i);
                 if (win == wtoken.startingWindow) {
+                    // Starting window that's exiting will be removed when the animation
+                    // finishes. Mark all relevant flags for that finishExit will proceed
+                    // all the way to actually remove it.
+                    if (!visible && win.isVisibleNow() && wtoken.mAppAnimator.isAnimating()) {
+                        win.mAnimatingExit = true;
+                        win.mRemoveOnExit = true;
+                        win.mWindowRemovalAllowed = true;
+                    }
                     continue;
                 }
 
@@ -4266,9 +4311,13 @@
                 wtoken.appDied = false;
                 wtoken.removeAllWindows();
             } else if (visible) {
-                mOpeningApps.add(wtoken);
+                if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) {
+                    // Add the app mOpeningApps if transition is unset but ready. This means
+                    // we're doing a screen freeze, and the unfreeze will wait for all opening
+                    // apps to be ready.
+                    mOpeningApps.add(wtoken);
+                }
                 wtoken.startingMoved = false;
-
                 // If the token is currently hidden (should be the common case), or has been
                 // stopped, then we need to set up to wait for its windows to be ready.
                 if (wtoken.hidden || wtoken.mAppStopped) {
@@ -4312,6 +4361,7 @@
                 }
                 wtoken.inPendingTransaction = true;
                 if (visible) {
+                    mOpeningApps.add(wtoken);
                     wtoken.mEnteringAnimation = true;
                 } else {
                     mClosingApps.add(wtoken);
@@ -6068,7 +6118,7 @@
                         int bottom = wf.bottom - cr.bottom;
                         frame.union(left, top, right, bottom);
                         ws.getVisibleBounds(stackBounds);
-                        if (!frame.intersect(stackBounds)) {
+                        if (!Rect.intersects(frame, stackBounds)) {
                             // Set frame empty if there's no intersection.
                             frame.setEmpty();
                         }
@@ -7568,6 +7618,11 @@
                    + " milliseconds before attempting to detect safe mode.");
         }
 
+        if (Settings.Global.getInt(
+                mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) {
+            return false;
+        }
+
         int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
                 KeyEvent.KEYCODE_MENU);
         int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
@@ -8969,7 +9024,8 @@
                     || winAnimator.mSurfaceResized
                     || w.mOutsetsChanged
                     || configChanged
-                    || dragResizingChanged) {
+                    || dragResizingChanged
+                    || w.mResizedWhileNotDragResizing) {
                 if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
                     Slog.v(TAG_WM, "Resize reasons for w=" + w + ": "
                             + " contentInsetsChanged=" + w.mContentInsetsChanged
@@ -9003,7 +9059,8 @@
                 // the display until this window has been redrawn; to do that,
                 // we need to go through the process of getting informed by the
                 // application when it has finished drawing.
-                if (w.mOrientationChanging || dragResizingChanged) {
+                if (w.mOrientationChanging || dragResizingChanged
+                        || w.mResizedWhileNotDragResizing) {
                     if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
                         Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
                                 + ", mDrawState=DRAW_PENDING in " + w
@@ -9363,6 +9420,10 @@
             return;
         }
 
+        if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
+                "startFreezingDisplayLocked: inTransaction=" + inTransaction
+                + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
+                + " called by " + Debug.getCallers(8));
         mScreenFrozenLock.acquire();
 
         mDisplayFrozen = true;
@@ -9433,6 +9494,9 @@
             return;
         }
 
+        if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
+                "stopFreezingDisplayLocked: Unfreezing now");
+
         mDisplayFrozen = false;
         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
         StringBuilder sb = new StringBuilder(128);
@@ -10597,7 +10661,10 @@
     @Override
     public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
         try {
-            getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
+            WindowState focusedWindow = getFocusedWindow();
+            if (focusedWindow != null && focusedWindow.mClient != null) {
+                getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver, deviceId);
+            }
         } catch (RemoteException e) {
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 57ead8b..ddfc022 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -328,6 +328,8 @@
      */
     final Rect mInsetFrame = new Rect();
 
+    private static final Rect sTmpRect = new Rect();
+
     boolean mContentChanged;
 
     // If a window showing a wallpaper: the requested offset for the
@@ -466,6 +468,13 @@
      */
     boolean mResizedWhileGone = false;
 
+    /**
+     * Indicates whether we got resized but drag resizing flag was false. In this case, we also
+     * need to recreate the surface and defer surface bound updates in order to make sure the
+     * buffer contents and the positioning/size stay in sync.
+     */
+    boolean mResizedWhileNotDragResizing;
+
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, final DisplayContent displayContent) {
@@ -629,6 +638,20 @@
         return mAttrs.packageName;
     }
 
+    /**
+     * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame}
+     * from {@param frame}. In other words, it applies the insets that would result if
+     * {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from
+     * {@param insetFrame}.
+     */
+    private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame) {
+        final int left = Math.max(0, insetFrame.left - layoutFrame.left);
+        final int top = Math.max(0, insetFrame.top - layoutFrame.top);
+        final int right = Math.max(0, layoutFrame.right - insetFrame.right);
+        final int bottom = Math.max(0, layoutFrame.bottom - insetFrame.bottom);
+        frame.inset(left, top, right, bottom);
+    }
+
     @Override
     public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf,
             Rect osf) {
@@ -654,11 +677,25 @@
             task.getTempInsetBounds(mInsetFrame);
         }
 
+        // Denotes the actual frame used to calculate the insets and to perform the layout. When
+        // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the
+        // insets temporarily. By the notion of a task having a different layout frame, we can
+        // achieve that while still moving the task around.
+        final Rect layoutContainingFrame;
+        final Rect layoutDisplayFrame;
+
+        // The offset from the layout containing frame to the actual containing frame.
+        final int layoutXDiff;
+        final int layoutYDiff;
         if (mInsetFrame.isEmpty()  && (fullscreenTask
                 || layoutInParentFrame())) {
             // We use the parent frame as the containing frame for fullscreen and child windows
             mContainingFrame.set(pf);
             mDisplayFrame.set(df);
+            layoutDisplayFrame = df;
+            layoutContainingFrame = pf;
+            layoutXDiff = 0;
+            layoutYDiff = 0;
         } else {
             task.getBounds(mContainingFrame);
             if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
@@ -670,10 +707,18 @@
                 mContainingFrame.bottom = mContainingFrame.top + frozen.height();
             }
             final WindowState imeWin = mService.mInputMethodWindow;
-            if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this
-                    && mContainingFrame.bottom > cf.bottom) {
-                // IME is up and obscuring this window. Adjust the window position so it is visible.
-                mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
+            // IME is up and obscuring this window. Adjust the window position so it is visible.
+            if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) {
+                    if (windowsAreFloating && mContainingFrame.bottom > cf.bottom) {
+                        // In freeform we want to move the top up directly.
+                        // TODO: Investigate why this is cf not pf.
+                        mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
+                    } else if (mContainingFrame.bottom > pf.bottom) {
+                        // But in docked we want to behave like fullscreen
+                        // and behave as if the task were given smaller bounds
+                        // for the purposes of layout.
+                        mContainingFrame.bottom = pf.bottom;
+                    }
             }
 
             if (windowsAreFloating) {
@@ -685,6 +730,14 @@
                 }
             }
             mDisplayFrame.set(mContainingFrame);
+            layoutXDiff = !mInsetFrame.isEmpty() ? mInsetFrame.left - mContainingFrame.left : 0;
+            layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0;
+            layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame;
+            subtractInsets(mDisplayFrame, layoutContainingFrame, df);
+            subtractInsets(mContainingFrame, layoutContainingFrame, pf);
+            subtractInsets(mInsetFrame, layoutContainingFrame, pf);
+            layoutDisplayFrame = df;
+            layoutDisplayFrame.intersect(layoutContainingFrame);
         }
 
         final int pw = mContainingFrame.width();
@@ -715,7 +768,11 @@
         final int fw = mFrame.width();
         final int fh = mFrame.height();
 
-        applyGravityAndUpdateFrame();
+        applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
+
+        // Offset the actual frame by the amount layout frame is off.
+        mFrame.offset(-layoutXDiff, -layoutYDiff);
+        mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
 
         // Calculate the outsets before the content frame gets shrinked to the window frame.
         if (hasOutsets) {
@@ -727,12 +784,6 @@
             mOutsets.set(0, 0, 0, 0);
         }
 
-        // Denotes the actual frame used to calculate the insets. When resizing in docked mode,
-        // we'd like to freeze the layout, so we also need to freeze the insets temporarily. By the
-        // notion of a task having a different inset frame, we can achieve that while still moving
-        // the task around.
-        final Rect frame = !mInsetFrame.isEmpty() ? mInsetFrame : mFrame;
-
         // Make sure the content and visible frames are inside of the
         // final window frame.
         if (windowsAreFloating && !mFrame.isEmpty()) {
@@ -761,29 +812,29 @@
                 mMovedByResize = true;
             }
         } else {
-            mContentFrame.set(Math.max(mContentFrame.left, frame.left),
-                    Math.max(mContentFrame.top, frame.top),
-                    Math.min(mContentFrame.right, frame.right),
-                    Math.min(mContentFrame.bottom, frame.bottom));
+            mContentFrame.set(Math.max(mContentFrame.left, layoutContainingFrame.left),
+                    Math.max(mContentFrame.top, layoutContainingFrame.top),
+                    Math.min(mContentFrame.right, layoutContainingFrame.right),
+                    Math.min(mContentFrame.bottom, layoutContainingFrame.bottom));
 
-            mVisibleFrame.set(Math.max(mVisibleFrame.left, frame.left),
-                    Math.max(mVisibleFrame.top, frame.top),
-                    Math.min(mVisibleFrame.right, frame.right),
-                    Math.min(mVisibleFrame.bottom, frame.bottom));
+            mVisibleFrame.set(Math.max(mVisibleFrame.left, layoutContainingFrame.left),
+                    Math.max(mVisibleFrame.top, layoutContainingFrame.top),
+                    Math.min(mVisibleFrame.right, layoutContainingFrame.right),
+                    Math.min(mVisibleFrame.bottom, layoutContainingFrame.bottom));
 
-            mStableFrame.set(Math.max(mStableFrame.left, frame.left),
-                    Math.max(mStableFrame.top, frame.top),
-                    Math.min(mStableFrame.right, frame.right),
-                    Math.min(mStableFrame.bottom, frame.bottom));
+            mStableFrame.set(Math.max(mStableFrame.left, layoutContainingFrame.left),
+                    Math.max(mStableFrame.top, layoutContainingFrame.top),
+                    Math.min(mStableFrame.right, layoutContainingFrame.right),
+                    Math.min(mStableFrame.bottom, layoutContainingFrame.bottom));
         }
 
         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),
-                    Math.max(frame.bottom - mOverscanFrame.bottom, 0));
+            mOverscanInsets.set(Math.max(mOverscanFrame.left - layoutContainingFrame.left, 0),
+                    Math.max(mOverscanFrame.top - layoutContainingFrame.top, 0),
+                    Math.max(layoutContainingFrame.right - mOverscanFrame.right, 0),
+                    Math.max(layoutContainingFrame.bottom - mOverscanFrame.bottom, 0));
         }
 
         if (mAttrs.type == TYPE_DOCK_DIVIDER) {
@@ -799,45 +850,37 @@
             mContentInsets.setEmpty();
             mVisibleInsets.setEmpty();
         } else {
-            // Using mContentInsets as a temp rect. It is safe because we're setting it below.
-            getDisplayContent().getLogicalDisplayRect(mContentInsets);
+            getDisplayContent().getLogicalDisplayRect(mTmpRect);
             // Override right and/or bottom insets in case if the frame doesn't fit the screen in
             // non-fullscreen mode.
-            boolean overrideRightInset = !fullscreenTask && mFrame.right > mContentInsets.right;
-            boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mContentInsets.bottom;
-            mContentInsets.set(mContentFrame.left - frame.left,
-                    mContentFrame.top - frame.top,
-                    overrideRightInset ? 0 : frame.right - mContentFrame.right,
-                    overrideBottomInset ? 0 : frame.bottom - mContentFrame.bottom);
+            boolean overrideRightInset = !fullscreenTask && mFrame.right > mTmpRect.right;
+            boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mTmpRect.bottom;
+            mContentInsets.set(mContentFrame.left - layoutContainingFrame.left,
+                    mContentFrame.top - layoutContainingFrame.top,
+                    overrideRightInset ? mTmpRect.right - mContentFrame.right
+                            : layoutContainingFrame.right - mContentFrame.right,
+                    overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom
+                            : layoutContainingFrame.bottom - mContentFrame.bottom);
 
-            mVisibleInsets.set(mVisibleFrame.left - frame.left,
-                    mVisibleFrame.top - frame.top,
-                    overrideRightInset ? 0 : frame.right - mVisibleFrame.right,
-                    overrideBottomInset ? 0 : frame.bottom - mVisibleFrame.bottom);
+            mVisibleInsets.set(mVisibleFrame.left - layoutContainingFrame.left,
+                    mVisibleFrame.top - layoutContainingFrame.top,
+                    overrideRightInset ? mTmpRect.right - mVisibleFrame.right
+                            : layoutContainingFrame.right - mVisibleFrame.right,
+                    overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom
+                            : layoutContainingFrame.bottom - mVisibleFrame.bottom);
 
-            mStableInsets.set(Math.max(mStableFrame.left - frame.left, 0),
-                    Math.max(mStableFrame.top - frame.top, 0),
-                    overrideRightInset ? 0 : Math.max(frame.right - mStableFrame.right, 0),
-                    overrideBottomInset ? 0 :  Math.max(frame.bottom - mStableFrame.bottom, 0));
+            mStableInsets.set(Math.max(mStableFrame.left - layoutContainingFrame.left, 0),
+                    Math.max(mStableFrame.top - layoutContainingFrame.top, 0),
+                    overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0)
+                            : Math.max(layoutContainingFrame.right - mStableFrame.right, 0),
+                    overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0)
+                            :  Math.max(layoutContainingFrame.bottom - mStableFrame.bottom, 0));
         }
 
-        if (!mInsetFrame.isEmpty()) {
-            mContentFrame.set(mFrame);
-            mContentFrame.top += mContentInsets.top;
-            mContentFrame.bottom -= mContentInsets.bottom;
-            mContentFrame.left += mContentInsets.left;
-            mContentFrame.right -= mContentInsets.right;
-            mVisibleFrame.set(mFrame);
-            mVisibleFrame.top += mVisibleInsets.top;
-            mVisibleFrame.bottom -= mVisibleInsets.bottom;
-            mVisibleFrame.left += mVisibleInsets.left;
-            mVisibleFrame.right -= mVisibleInsets.right;
-            mStableFrame.set(mFrame);
-            mStableFrame.top += mStableInsets.top;
-            mStableFrame.bottom -= mStableInsets.bottom;
-            mStableFrame.left += mStableInsets.left;
-            mStableFrame.right -= mStableInsets.right;
-        }
+        mContentFrame.offset(-layoutXDiff, -layoutYDiff);
+        mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
+        mStableFrame.offset(-layoutXDiff, -layoutYDiff);
+
         mCompatFrame.set(mFrame);
         if (mEnforceSizeCompat) {
             // If there is a size compatibility scale being applied to the
@@ -1878,6 +1921,11 @@
     }
 
     private boolean shouldSaveSurface() {
+        if (mWinAnimator.mSurfaceController == null) {
+            // Don't bother if the surface controller is gone for any reason.
+            return false;
+        }
+
         if ((mAttrs.flags & FLAG_SECURE) != 0) {
             // We don't save secure surfaces since their content shouldn't be shown while the app
             // isn't on screen and content might leak through during the transition animation with
@@ -1951,10 +1999,18 @@
             return;
         }
         mSurfaceSaved = false;
-        setHasSurface(true);
-        mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
-        if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
-            Slog.v(TAG, "Restoring saved surface: " + this);
+        if (mWinAnimator.mSurfaceController != null) {
+            setHasSurface(true);
+            mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
+
+            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
+                Slog.v(TAG, "Restoring saved surface: " + this);
+            }
+        } else {
+            // mSurfaceController shouldn't be null if mSurfaceSaved was still true at
+            // this point. Even if we destroyed the saved surface because of rotation
+            // or resize, mSurfaceSaved flag should have been cleared. So this is a wtf.
+            Slog.wtf(TAG, "Failed to restore saved surface: surface gone! " + this);
         }
     }
 
@@ -2523,9 +2579,9 @@
         }
     }
 
-    void applyGravityAndUpdateFrame() {
-        final int pw = mContainingFrame.width();
-        final int ph = mContainingFrame.height();
+    void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
+        final int pw = containingFrame.width();
+        final int ph = containingFrame.height();
         final Task task = getTask();
         final boolean nonFullscreenTask = isInMultiWindowMode();
         final boolean fitToDisplay = task != null && !task.isFloating() && !layoutInParentFrame();
@@ -2572,7 +2628,7 @@
             y = mAttrs.y;
         }
 
-        if (nonFullscreenTask) {
+        if (nonFullscreenTask && !layoutInParentFrame()) {
             // Make sure window fits in containing frame since it is in a non-fullscreen task as
             // required by {@link Gravity#apply} call.
             w = Math.min(w, pw);
@@ -2580,13 +2636,13 @@
         }
 
         // Set mFrame
-        Gravity.apply(mAttrs.gravity, w, h, mContainingFrame,
+        Gravity.apply(mAttrs.gravity, w, h, containingFrame,
                 (int) (x + mAttrs.horizontalMargin * pw),
                 (int) (y + mAttrs.verticalMargin * ph), mFrame);
 
         // Now make sure the window fits in the overall display frame.
         if (fitToDisplay) {
-            Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+            Gravity.applyDisplay(mAttrs.gravity, displayFrame, mFrame);
         }
 
         // We need to make sure we update the CompatFrame as it is used for
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 1e103f0..34452ee 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -967,13 +967,15 @@
             if (appTransformation != null) {
                 tmpMatrix.postConcat(appTransformation.getMatrix());
             }
+
+            // The translation that applies the position of the window needs to be applied at the
+            // end in case that other translations include scaling. Otherwise the scaling will
+            // affect this translation. But it needs to be set before the screen rotation animation
+            // so the pivot point is at the center of the screen for all windows.
+            tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
             if (screenAnimation) {
                 tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
             }
-            // The translation that applies the position of the window needs to be applied at the
-            // end in case that other translations include scaling. Otherwise the scaling will
-            // affect this translation.
-            tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
 
             //TODO (multidisplay): Magnification is supported only for the default display.
             if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
@@ -1316,6 +1318,11 @@
         final WindowState w = mWin;
         final Task task = w.getTask();
 
+        // We got resized, so block all updates until we got the new surface.
+        if (w.mResizedWhileNotDragResizing) {
+            return;
+        }
+
         mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0);
         calculateSurfaceBounds(w, w.getAttrs());
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index eda2f39..04aa735 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1582,7 +1582,8 @@
                 // synchronize its thumbnail surface with the surface for the
                 // open/close animation (only on the way down)
                 anim = mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect,
-                        insets, thumbnailHeader, taskId, mService.mCurConfiguration.orientation);
+                        insets, thumbnailHeader, taskId, mService.mCurConfiguration.uiMode,
+                        mService.mCurConfiguration.orientation);
                 openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer);
                 openingAppAnimator.deferThumbnailDestruction =
                         !mService.mAppTransition.isNextThumbnailTransitionScaleUp();
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index a5237ca..cd485c5 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1312,6 +1312,12 @@
     }
 }
 
+static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */,
+         jlong ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    im->getInputManager()->getReader()->toggleCapsLockState(deviceId);
+}
+
 static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */,
         jlong ptr, jobjectArray windowHandleObjArray) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1508,6 +1514,8 @@
             (void*) nativeSetInputFilterEnabled },
     { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I",
             (void*) nativeInjectInputEvent },
+    { "nativeToggleCapsLock", "(JI)V",
+            (void*) nativeToggleCapsLock },
     { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
             (void*) nativeSetInputWindows },
     { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6fe5c16..fdea84b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1131,9 +1131,7 @@
                 }
                 String tagDAM = parser.getName();
                 if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
-                    PersistableBundle bundle = new PersistableBundle();
-                    bundle.restoreFromXml(parser);
-                    result.options = bundle;
+                    result.options = PersistableBundle.restoreFromXml(parser);
                 } else {
                     Slog.w(LOG_TAG, "Unknown tag under " + tag +  ": " + tagDAM);
                 }
@@ -2805,6 +2803,10 @@
                         && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
                     throw new IllegalArgumentException("Admin is already added");
                 }
+                if (policy.mRemovingAdmins.contains(adminReceiver)) {
+                    throw new IllegalArgumentException(
+                            "Trying to set an admin which is being removed");
+                }
                 ActiveAdmin newAdmin = new ActiveAdmin(info, /* parent */ false);
                 policy.mAdminMap.put(adminReceiver, newAdmin);
                 int replaceIndex = -1;
@@ -3006,7 +3008,7 @@
             ArrayList<ActiveAdmin> admins = new ArrayList<ActiveAdmin>();
             for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
                 DevicePolicyData policy = getUserData(userInfo.id);
-                if (!isManagedProfile(userInfo.id)) {
+                if (!userInfo.isManagedProfile()) {
                     admins.addAll(policy.mAdminList);
                 } else {
                     // For managed profiles, we always include the policies set on the parent
@@ -3740,32 +3742,26 @@
         final int callingUid = mInjector.binderGetCallingUid();
         final int userHandle = mInjector.userHandleGetCallingUserId();
 
-        if (getCredentialOwner(userHandle, /* parent */ false) != userHandle) {
-            throw new SecurityException("You can not change password for this profile because"
-                    + " it shares the password with the owner profile");
-        }
-
         String password = passwordOrNull != null ? passwordOrNull : "";
 
+        // Password resetting to empty/null is not allowed for managed profiles.
+        if (TextUtils.isEmpty(password)) {
+            enforceNotManagedProfile(userHandle, "clear the active password");
+        }
+
         int quality;
         synchronized (this) {
-            // If caller has PO (or DO), it can clear the password, so see if that's the case
-            // first.
+            // If caller has PO (or DO) it can change the password, so see if that's the case first.
             ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
                     null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
             if (admin == null) {
                 // Otherwise, make sure the caller has any active admin with the right policy.
                 admin = getActiveAdminForCallerLocked(null,
                         DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
-            }
 
-            final ComponentName adminComponent = admin.info.getComponent();
-
-            // As of N, only profile owners and device owners can reset the password.
-            if (!(isProfileOwner(adminComponent, userHandle)
-                    || isDeviceOwner(adminComponent, userHandle))) {
                 final boolean preN = getTargetSdk(admin.info.getPackageName(), userHandle)
                         <= android.os.Build.VERSION_CODES.M;
+
                 // As of N, password resetting to empty/null is not allowed anymore.
                 // TODO Should we allow DO/PO to set an empty password?
                 if (TextUtils.isEmpty(password)) {
@@ -3982,6 +3978,15 @@
                         && timeMs > admin.maximumTimeToUnlock) {
                     timeMs = admin.maximumTimeToUnlock;
                 }
+                // If userInfo.id is a managed profile, we also need to look at
+                // the policies set on the parent.
+                if (admin.hasParentActiveAdmin()) {
+                    final ActiveAdmin parentAdmin = admin.getParentActiveAdmin();
+                    if (parentAdmin.maximumTimeToUnlock > 0
+                            && timeMs > parentAdmin.maximumTimeToUnlock) {
+                        timeMs = parentAdmin.maximumTimeToUnlock;
+                    }
+                }
             }
         }
 
@@ -4015,30 +4020,57 @@
         }
         enforceFullCrossUsersPermission(userHandle);
         synchronized (this) {
-            long time = 0;
-
             if (who != null) {
                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
-                return admin != null ? admin.maximumTimeToUnlock : time;
+                return admin != null ? admin.maximumTimeToUnlock : 0;
             }
-
             // Return the strictest policy across all participating admins.
             List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(
                     userHandle, parent);
-            final int N = admins.size();
-            for (int i = 0; i < N; i++) {
-                ActiveAdmin admin = admins.get(i);
-                if (time == 0) {
-                    time = admin.maximumTimeToUnlock;
-                } else if (admin.maximumTimeToUnlock != 0
-                        && time > admin.maximumTimeToUnlock) {
-                    time = admin.maximumTimeToUnlock;
+            return getMaximumTimeToLockPolicyFromAdmins(admins);
+        }
+    }
+
+    @Override
+    public long getMaximumTimeToLockForUserAndProfiles(int userHandle) {
+        if (!mHasFeature) {
+            return 0;
+        }
+        enforceFullCrossUsersPermission(userHandle);
+        synchronized (this) {
+            // All admins for this user.
+            ArrayList<ActiveAdmin> admins = new ArrayList<ActiveAdmin>();
+            for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+                DevicePolicyData policy = getUserData(userInfo.id);
+                admins.addAll(policy.mAdminList);
+                // If it is a managed profile, it may have parent active admins
+                if (userInfo.isManagedProfile()) {
+                    for (ActiveAdmin admin : policy.mAdminList) {
+                        if (admin.hasParentActiveAdmin()) {
+                            admins.add(admin.getParentActiveAdmin());
+                        }
+                    }
                 }
             }
-            return time;
+            return getMaximumTimeToLockPolicyFromAdmins(admins);
         }
     }
 
+    private long getMaximumTimeToLockPolicyFromAdmins(List<ActiveAdmin> admins) {
+        long time = 0;
+        final int N = admins.size();
+        for (int i = 0; i < N; i++) {
+            ActiveAdmin admin = admins.get(i);
+            if (time == 0) {
+                time = admin.maximumTimeToUnlock;
+            } else if (admin.maximumTimeToUnlock != 0
+                    && time > admin.maximumTimeToUnlock) {
+                time = admin.maximumTimeToUnlock;
+            }
+        }
+        return time;
+    }
+
     @Override
     public void lockNow(boolean parent) {
         if (!mHasFeature) {
@@ -4356,6 +4388,13 @@
         }
     }
 
+    /**
+     * @return {@code true} if the package is installed and set as always-on, {@code false} if it is
+     * not installed and therefore not available.
+     *
+     * @throws SecurityException if the caller is not a profile or device owner.
+     * @throws UnsupportedException if the package does not support being set as always-on.
+     */
     @Override
     public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage)
             throws SecurityException {
@@ -4365,13 +4404,19 @@
 
         final int userId = mInjector.userHandleGetCallingUserId();
         final long token = mInjector.binderClearCallingIdentity();
-        try{
+        try {
+            if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) {
+                return false;
+            }
             ConnectivityManager connectivityManager = (ConnectivityManager)
                     mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-            return connectivityManager.setAlwaysOnVpnPackageForUser(userId, vpnPackage);
+            if (!connectivityManager.setAlwaysOnVpnPackageForUser(userId, vpnPackage)) {
+                throw new UnsupportedOperationException();
+            }
         } finally {
             mInjector.binderRestoreCallingIdentity(token);
         }
+        return true;
     }
 
     @Override
@@ -6394,17 +6439,16 @@
 
     @Override
     public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent,
-            PersistableBundle args) {
+            PersistableBundle args, boolean parent) {
         if (!mHasFeature) {
             return;
         }
         Preconditions.checkNotNull(admin, "admin is null");
         Preconditions.checkNotNull(agent, "agent is null");
         final int userHandle = UserHandle.getCallingUserId();
-        enforceNotManagedProfile(userHandle, "set trust agent configuration");
         synchronized (this) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
-                    DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
+                    DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES, parent);
             ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
             saveSettingsLocked(userHandle);
         }
@@ -6412,7 +6456,7 @@
 
     @Override
     public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
-            ComponentName agent, int userHandle) {
+            ComponentName agent, int userHandle, boolean parent) {
         if (!mHasFeature) {
             return null;
         }
@@ -6422,46 +6466,44 @@
         synchronized (this) {
             final String componentName = agent.flattenToString();
             if (admin != null) {
-                final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle);
+                final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle, parent);
                 if (ap == null) return null;
                 TrustAgentInfo trustAgentInfo = ap.trustAgentInfos.get(componentName);
                 if (trustAgentInfo == null || trustAgentInfo.options == null) return null;
-                List<PersistableBundle> result = new ArrayList<PersistableBundle>();
+                List<PersistableBundle> result = new ArrayList<>();
                 result.add(trustAgentInfo.options);
                 return result;
             }
 
             // Return strictest policy for this user and profiles that are visible from this user.
-            final List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
             List<PersistableBundle> result = null;
-
             // Search through all admins that use KEYGUARD_DISABLE_TRUST_AGENTS and keep track
             // of the options. If any admin doesn't have options, discard options for the rest
             // and return null.
+            List<ActiveAdmin> admins =
+                    getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent);
             boolean allAdminsHaveOptions = true;
-            for (UserInfo userInfo : profiles) {
-                DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
-                final int N = policy.mAdminList.size();
-                for (int i=0; i < N; i++) {
-                    final ActiveAdmin active = policy.mAdminList.get(i);
-                    final boolean disablesTrust = (active.disabledKeyguardFeatures
-                            & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
-                    final TrustAgentInfo info = active.trustAgentInfos.get(componentName);
-                    if (info != null && info.options != null && !info.options.isEmpty()) {
-                        if (disablesTrust) {
-                            if (result == null) {
-                                result = new ArrayList<PersistableBundle>();
-                            }
-                            result.add(info.options);
-                        } else {
-                            Log.w(LOG_TAG, "Ignoring admin " + active.info
-                                    + " because it has trust options but doesn't declare "
-                                    + "KEYGUARD_DISABLE_TRUST_AGENTS");
+            final int N = admins.size();
+            for (int i = 0; i < N; i++) {
+                final ActiveAdmin active = admins.get(i);
+
+                final boolean disablesTrust = (active.disabledKeyguardFeatures
+                        & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
+                final TrustAgentInfo info = active.trustAgentInfos.get(componentName);
+                if (info != null && info.options != null && !info.options.isEmpty()) {
+                    if (disablesTrust) {
+                        if (result == null) {
+                            result = new ArrayList<>();
                         }
-                    } else if (disablesTrust) {
-                        allAdminsHaveOptions = false;
-                        break;
+                        result.add(info.options);
+                    } else {
+                        Log.w(LOG_TAG, "Ignoring admin " + active.info
+                                + " because it has trust options but doesn't declare "
+                                + "KEYGUARD_DISABLE_TRUST_AGENTS");
                     }
+                } else if (disablesTrust) {
+                    allAdminsHaveOptions = false;
+                    break;
                 }
             }
             return allAdminsHaveOptions ? result : null;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 659450e..e7ae2b0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -157,6 +157,8 @@
             "com.google.android.clockwork.ThermalObserver";
     private static final String WEAR_BLUETOOTH_SERVICE_CLASS =
             "com.google.android.clockwork.bluetooth.WearBluetoothService";
+    private static final String CONTENT_SERVICE_CLASS =
+            "com.android.server.content.ContentService$Lifecycle";
 
     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
 
@@ -574,8 +576,7 @@
             Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             traceBeginAndSlog("StartContentService");
-            contentService = ContentService.main(context,
-                    mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL);
+            mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);
             Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             traceBeginAndSlog("InstallSystemProviders");
@@ -1324,7 +1325,7 @@
                     reportWtf("starting System UI", e);
                 }
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
-                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeMountServiceReady");
+                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeNetworkScoreReady");
                 try {
                     if (networkScoreF != null) networkScoreF.systemReady();
                 } catch (Throwable e) {
@@ -1423,6 +1424,12 @@
                 } catch (Throwable e) {
                     reportWtf("Notifying MmsService running", e);
                 }
+
+                try {
+                    if (networkScoreF != null) networkScoreF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying NetworkScoreService running", e);
+                }
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
         });
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index ebbf991..f430a30 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -18,6 +18,7 @@
 
 import static android.system.OsConstants.*;
 
+import android.net.LinkProperties;
 import android.net.NetworkUtils;
 import android.net.apf.ApfGenerator;
 import android.net.apf.ApfGenerator.IllegalInstructionException;
@@ -136,6 +137,16 @@
     // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
     private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28;
 
+    private static int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
+    private static final byte[] ARP_IPV4_REQUEST_HEADER = new byte[]{
+            0, 1, // Hardware type: Ethernet (1)
+            8, 0, // Protocol type: IP (0x0800)
+            6,    // Hardware size: 6
+            4,    // Protocol size: 4
+            0, 1  // Opcode: request (1)
+    };
+    private static int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
+
     private final ApfCapabilities mApfCapabilities;
     private final IpManager.Callback mIpManagerCallback;
     private final NetworkInterface mNetworkInterface;
@@ -145,12 +156,16 @@
     private long mUniqueCounter;
     @GuardedBy("this")
     private boolean mMulticastFilter;
+    // Our IPv4 address, if we have just one, otherwise null.
+    @GuardedBy("this")
+    private byte[] mIPv4Address;
 
     private ApfFilter(ApfCapabilities apfCapabilities, NetworkInterface networkInterface,
-            IpManager.Callback ipManagerCallback) {
+            IpManager.Callback ipManagerCallback, boolean multicastFilter) {
         mApfCapabilities = apfCapabilities;
         mIpManagerCallback = ipManagerCallback;
         mNetworkInterface = networkInterface;
+        mMulticastFilter = multicastFilter;
 
         maybeStartFilter();
     }
@@ -225,6 +240,7 @@
         private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
         private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
 
+        // Note: mPacket's position() cannot be assumed to be reset.
         private final ByteBuffer mPacket;
         // List of binary ranges that include the whole packet except the lifetimes.
         // Pairs consist of offset and length.
@@ -378,17 +394,12 @@
 
         // 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;
+            if (length != mPacket.capacity()) return false;
+            byte[] referencePacket = mPacket.array();
             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;
+                for (int i = nonLifetime.first; i < (nonLifetime.first + nonLifetime.second); i++) {
+                    if (packet[i] != referencePacket[i]) return false;
+                }
             }
             return true;
         }
@@ -440,7 +451,7 @@
             String nextFilterLabel = "Ra" + getUniqueNumberLocked();
             // Skip if packet is not the right size
             gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
-            gen.addJumpIfR0NotEquals(mPacket.limit(), nextFilterLabel);
+            gen.addJumpIfR0NotEquals(mPacket.capacity(), nextFilterLabel);
             int filterLifetime = (int)(currentLifetime() / FRACTION_OF_LIFETIME_TO_FILTER);
             // Skip filter if expired
             gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
@@ -510,6 +521,33 @@
     private byte[] mLastInstalledProgram;
 
     /**
+     * Generate filter code to process ARP packets. Execution of this code ends in either the
+     * DROP_LABEL or PASS_LABEL and does not fall off the end.
+     * Preconditions:
+     *  - Packet being filtered is ARP
+     */
+    @GuardedBy("this")
+    private void generateArpFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
+        // Here's a basic summary of what the ARP filter program does:
+        //
+        // if it's not an ARP IPv4 request:
+        //   pass
+        // if it's not a request for our IPv4 address:
+        //   drop
+        // pass
+
+        // if it's not an ARP IPv4 request, pass
+        gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET);
+        gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_REQUEST_HEADER, gen.PASS_LABEL);
+        // if it's not a request for our IPv4 address, drop
+        gen.addLoadImmediate(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
+        gen.addJumpIfBytesNotEqual(Register.R0, mIPv4Address, gen.DROP_LABEL);
+
+        // Otherwise, pass
+        gen.addJump(gen.PASS_LABEL);
+    }
+
+    /**
      * Generate filter code to process IPv4 packets. Execution of this code ends in either the
      * DROP_LABEL or PASS_LABEL and does not fall off the end.
      * Preconditions:
@@ -566,7 +604,6 @@
      * DROP_LABEL or PASS_LABEL, or falls off the end for ICMPv6 packets.
      * Preconditions:
      *  - Packet being filtered is IPv6
-     *  - R1 is initialized to 0
      */
     @GuardedBy("this")
     private void generateIPv6FilterLocked(ApfGenerator gen) throws IllegalInstructionException {
@@ -598,6 +635,7 @@
     /**
      * Begin generating an APF program to:
      * <ul>
+     * <li>Drop ARP requests not for us, if mIPv4Address is set,
      * <li>Drop IPv4 broadcast packets, except DHCP destined to our MAC,
      * <li>Drop IPv4 multicast packets, if mMulticastFilter,
      * <li>Pass all other IPv4 packets,
@@ -616,16 +654,31 @@
 
         // Here's a basic summary of what the initial program does:
         //
+        // if it's ARP:
+        //   inesrt ARP filter to drop or pass these appropriately
         // if it's IPv4:
         //   insert IPv4 filter to drop or pass these appropriately
         // if it's not IPv6:
         //   pass
         // insert IPv6 filter to drop, pass, or fall off the end for ICMPv6 packets
 
+        gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
+
+        if (mIPv4Address != null) {
+            // Add ARP filters:
+            String skipArpFiltersLabel = "skipArpFilters";
+            // If not ARP, skip ARP filters
+            // NOTE: Relies on R0 containing ethertype.
+            gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel);
+            generateArpFilterLocked(gen);
+            gen.defineLabel(skipArpFiltersLabel);
+        }
+
         // Add IPv4 filters:
         String skipIPv4FiltersLabel = "skipIPv4Filters";
-        // If not IPv4, skip IPv4 filters
-        gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
+        // NOTE: Relies on R0 containing ethertype. This is safe because if we got here, we did not
+        // execute the ARP filter, since that filter does not fall through, but either drops or
+        // passes.
         gen.addJumpIfR0NotEquals(ETH_P_IP, skipIPv4FiltersLabel);
         // NOTE: Relies on R1 being initialized to 0.
         generateIPv4FilterLocked(gen);
@@ -634,8 +687,8 @@
         // Add IPv6 filters:
         // If not IPv6, pass
         // NOTE: Relies on R0 containing ethertype. This is safe because if we got here, we did not
-        // execute the IPv4 filter, since that filter does not fall through, but either drops or
-        // passes.
+        // execute the ARP or IPv4 filters, since those filters do not fall through, but either
+        // drop or pass.
         gen.addJumpIfR0NotEquals(ETH_P_IPV6, gen.PASS_LABEL);
         generateIPv6FilterLocked(gen);
         return gen;
@@ -752,7 +805,8 @@
      * filtering using APF programs.
      */
     public static ApfFilter maybeCreate(ApfCapabilities apfCapabilities,
-            NetworkInterface networkInterface, IpManager.Callback ipManagerCallback) {
+            NetworkInterface networkInterface, IpManager.Callback ipManagerCallback,
+            boolean multicastFilter) {
         if (apfCapabilities == null || networkInterface == null) return null;
         if (apfCapabilities.apfVersionSupported == 0) return null;
         if (apfCapabilities.maximumApfProgramSize < 512) {
@@ -768,7 +822,7 @@
             Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
             return null;
         }
-        return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback);
+        return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback, multicastFilter);
     }
 
     public synchronized void shutdown() {
@@ -787,10 +841,36 @@
         }
     }
 
+    // Find the single IPv4 address if there is one, otherwise return null.
+    private static byte[] findIPv4Address(LinkProperties lp) {
+        byte[] ipv4Address = null;
+        for (InetAddress inetAddr : lp.getAddresses()) {
+            byte[] addr = inetAddr.getAddress();
+            if (addr.length != 4) continue;
+            // More than one IPv4 address, abort
+            if (ipv4Address != null && !Arrays.equals(ipv4Address, addr)) return null;
+            ipv4Address = addr;
+        }
+        return ipv4Address;
+    }
+
+    public synchronized void setLinkProperties(LinkProperties lp) {
+        // NOTE: Do not keep a copy of LinkProperties as it would further duplicate state.
+        byte[] ipv4Address = findIPv4Address(lp);
+        // If ipv4Address is the same as mIPv4Address, then there's no change, just return.
+        if (Arrays.equals(ipv4Address, mIPv4Address)) return;
+        // Otherwise update mIPv4Address and install new program.
+        mIPv4Address = ipv4Address;
+        installNewProgramLocked();
+    }
+
     public synchronized void dump(IndentingPrintWriter pw) {
-        pw.println("APF version: " + mApfCapabilities.apfVersionSupported);
-        pw.println("Max program size: " + mApfCapabilities.maximumApfProgramSize);
+        pw.println("APF caps: " + mApfCapabilities);
         pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED"));
+        pw.println("Multicast filtering: " + mMulticastFilter);
+        try {
+            pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address));
+        } catch (UnknownHostException|NullPointerException e) {}
         if (mLastTimeInstalledProgram == 0) {
             pw.println("No program installed.");
             return;
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index e27f69e..a881408 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -57,6 +57,17 @@
 
     public static final int HWADDR_LEN = 16;
     public static final int MAX_OPTION_LEN = 255;
+
+    /**
+     * The minimum and maximum MTU that we are prepared to use. We set the minimum to the minimum
+     * IPv6 MTU because the IPv6 stack enters unusual codepaths when the link MTU drops below 1280,
+     * and does not recover if the MTU is brought above 1280 again. We set the maximum to 1500
+     * because in general it is risky to assume that the hardware is able to send/receive packets
+     * larger than 1500 bytes even if the network supports it.
+     */
+    private static final int MIN_MTU = 1280;
+    private static final int MAX_MTU = 1500;
+
     /**
      * IP layer definitions.
      */
@@ -917,7 +928,7 @@
                             break;
                         case DHCP_MTU:
                             expectedLen = 2;
-                            mtu = Short.valueOf(packet.getShort());
+                            mtu = packet.getShort();
                             break;
                         case DHCP_DOMAIN_NAME:
                             expectedLen = optionLen;
@@ -1106,6 +1117,8 @@
         results.serverAddress = mServerIdentifier;
         results.vendorInfo = mVendorInfo;
         results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE;
+        results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0;
+
         return results;
     }
 
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index c25fae3..54aeb3d 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -100,10 +100,6 @@
         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) {}
 
@@ -116,6 +112,14 @@
 
         // Install an APF program to filter incoming packets.
         public void installPacketFilter(byte[] filter) {}
+
+        // If multicast filtering cannot be accomplished with APF, this function will be called to
+        // actuate multicast filtering using another means.
+        public void setFallbackMulticastFilter(boolean enabled) {}
+
+        // Enabled/disable Neighbor Discover offload functionality. This is
+        // called, for example, whenever 464xlat is being started or stopped.
+        public void setNeighborDiscoveryOffload(boolean enable) {}
     }
 
     public static class WaitForProvisioningCallback extends Callback {
@@ -222,6 +226,7 @@
     private static final int EVENT_NETLINK_LINKPROPERTIES_CHANGED = 5;
     private static final int CMD_UPDATE_TCP_BUFFER_SIZES = 6;
     private static final int CMD_UPDATE_HTTP_PROXY = 7;
+    private static final int CMD_SET_MULTICAST_FILTER = 8;
 
     private static final int MAX_LOG_RECORDS = 1000;
 
@@ -258,6 +263,7 @@
     private String mTcpBufferSizes;
     private ProxyInfo mHttpProxy;
     private ApfFilter mApfFilter;
+    private boolean mMulticastFiltering;
 
     /**
      * Member variables accessed both from within the StateMachine thread
@@ -296,15 +302,20 @@
                 }) {
             @Override
             public void interfaceAdded(String iface) {
+                super.interfaceAdded(iface);
                 if (mClatInterfaceName.equals(iface)) {
-                    mCallback.on464XlatChange(true);
+                    mCallback.setNeighborDiscoveryOffload(false);
                 }
             }
 
             @Override
             public void interfaceRemoved(String iface) {
+                super.interfaceRemoved(iface);
                 if (mClatInterfaceName.equals(iface)) {
-                    mCallback.on464XlatChange(false);
+                    // TODO: consider sending a message to the IpManager main
+                    // StateMachine thread, in case "NDO enabled" state becomes
+                    // tied to more things that 464xlat operation.
+                    mCallback.setNeighborDiscoveryOffload(true);
                 }
             }
         };
@@ -390,6 +401,14 @@
         sendMessage(CMD_UPDATE_HTTP_PROXY, proxyInfo);
     }
 
+    /**
+     * Enable or disable the multicast filter.  Attempts to use APF to accomplish the filtering,
+     * if not, Callback.setFallbackMulticastFilter() is called.
+     */
+    public void setMulticastFilter(boolean enabled) {
+        sendMessage(CMD_SET_MULTICAST_FILTER, enabled);
+    }
+
     public LinkProperties getLinkProperties() {
         synchronized (mLock) {
             return new LinkProperties(mLinkProperties);
@@ -519,6 +538,7 @@
     }
 
     private void dispatchCallback(ProvisioningChange delta, LinkProperties newLp) {
+        if (mApfFilter != null) mApfFilter.setLinkProperties(newLp);
         switch (delta) {
             case GAINED_PROVISIONING:
                 if (VDBG) { Log.d(mTag, "onProvisioningSuccess()"); }
@@ -605,6 +625,10 @@
                 }
             }
             newLp.setDomains(mDhcpResults.domains);
+
+            if (mDhcpResults.mtu != 0) {
+                newLp.setMtu(mDhcpResults.mtu);
+            }
         }
 
         // [4] Add in TCP buffer sizes and HTTP Proxy config, if available.
@@ -725,6 +749,10 @@
                     handleLinkPropertiesUpdate(NO_CALLBACKS);
                     break;
 
+                case CMD_SET_MULTICAST_FILTER:
+                    mMulticastFiltering = (boolean) msg.obj;
+                    break;
+
                 case DhcpClient.CMD_ON_QUIT:
                     // Everything is already stopped.
                     Log.e(mTag, "Unexpected CMD_ON_QUIT (already stopped).");
@@ -765,7 +793,10 @@
         @Override
         public void enter() {
             mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface,
-                    mCallback);
+                    mCallback, mMulticastFiltering);
+            // TODO: investigate the effects of any multicast filtering racing/interfering with the
+            // rest of this IP configuration startup.
+            if (mApfFilter == null) mCallback.setFallbackMulticastFilter(mMulticastFiltering);
             // Set privacy extensions.
             try {
                 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
@@ -878,6 +909,16 @@
                     handleLinkPropertiesUpdate(SEND_CALLBACKS);
                     break;
 
+                case CMD_SET_MULTICAST_FILTER: {
+                    mMulticastFiltering = (boolean) msg.obj;
+                    if (mApfFilter != null) {
+                        mApfFilter.setMulticastFilter(mMulticastFiltering);
+                    } else {
+                        mCallback.setFallbackMulticastFilter(mMulticastFiltering);
+                    }
+                    break;
+                }
+
                 case DhcpClient.CMD_PRE_DHCP_ACTION:
                     if (VDBG) { Log.d(mTag, "onPreDhcpAction()"); }
                     if (mConfiguration.mRequestedPreDhcpAction) {
diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
index 876d95b..f8eaf7d 100644
--- a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
@@ -261,7 +261,7 @@
 
     private void assertDhcpResults(String ipAddress, String gateway, String dnsServersString,
             String domains, String serverAddress, String vendorInfo, int leaseDuration,
-            boolean hasMeteredHint, DhcpResults dhcpResults) throws Exception {
+            boolean hasMeteredHint, int mtu, DhcpResults dhcpResults) throws Exception {
         assertEquals(new LinkAddress(ipAddress), dhcpResults.ipAddress);
         assertEquals(v4Address(gateway), dhcpResults.gateway);
 
@@ -277,6 +277,7 @@
         assertEquals(vendorInfo, dhcpResults.vendorInfo);
         assertEquals(leaseDuration, dhcpResults.leaseDuration);
         assertEquals(hasMeteredHint, dhcpResults.hasMeteredHint());
+        assertEquals(mtu, dhcpResults.mtu);
     }
 
     @SmallTest
@@ -310,7 +311,7 @@
         assertTrue(offerPacket instanceof DhcpOfferPacket);  // Implicitly checks it's non-null.
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("192.168.159.247/20", "192.168.159.254", "8.8.8.8,8.8.4.4",
-                null, "192.168.144.3", null, 7200, false, dhcpResults);
+                null, "192.168.144.3", null, 7200, false, 0, dhcpResults);
     }
 
     @SmallTest
@@ -342,10 +343,70 @@
         assertTrue(offerPacket instanceof DhcpOfferPacket);  // Implicitly checks it's non-null.
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("192.168.43.247/24", "192.168.43.1", "192.168.43.1",
-                null, "192.168.43.1", "ANDROID_METERED", 3600, true, dhcpResults);
+                null, "192.168.43.1", "ANDROID_METERED", 3600, true, 0, dhcpResults);
         assertTrue(dhcpResults.hasMeteredHint());
     }
 
+    private byte[] mtuBytes(int mtu) {
+        // 0x1a02: option 26, length 2. 0xff: no more options.
+        if (mtu > Short.MAX_VALUE - Short.MIN_VALUE) {
+            throw new IllegalArgumentException(
+                String.format("Invalid MTU %d, must be 16-bit unsigned", mtu));
+        }
+        String hexString = String.format("1a02%04xff", mtu);
+        return HexEncoding.decode(hexString.toCharArray(), false);
+    }
+
+    private void checkMtu(ByteBuffer packet, int expectedMtu, byte[] mtuBytes) throws Exception {
+        if (mtuBytes != null) {
+            packet.position(packet.capacity() - mtuBytes.length);
+            packet.put(mtuBytes);
+            packet.clear();
+        }
+        DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+        assertTrue(offerPacket instanceof DhcpOfferPacket);  // Implicitly checks it's non-null.
+        DhcpResults dhcpResults = offerPacket.toDhcpResults();
+        assertDhcpResults("192.168.159.247/20", "192.168.159.254", "8.8.8.8,8.8.4.4",
+                null, "192.168.144.3", null, 7200, false, expectedMtu, dhcpResults);
+    }
+
+    @SmallTest
+    public void testMtu() throws Exception {
+        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+            // IP header.
+            "451001480000000080118849c0a89003c0a89ff7" +
+            // UDP header.
+            "004300440134dcfa" +
+            // BOOTP header.
+            "02010600c997a63b0000000000000000c0a89ff70000000000000000" +
+            // MAC address.
+            "30766ff2a90c00000000000000000000" +
+            // Server name.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // File.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // Options
+            "638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" +
+            "3a0400000e103b040000189cff00000000"
+        ).toCharArray(), false));
+
+        checkMtu(packet, 0, null);
+        checkMtu(packet, 0, mtuBytes(1501));
+        checkMtu(packet, 1500, mtuBytes(1500));
+        checkMtu(packet, 1499, mtuBytes(1499));
+        checkMtu(packet, 1280, mtuBytes(1280));
+        checkMtu(packet, 0, mtuBytes(1279));
+        checkMtu(packet, 0, mtuBytes(576));
+        checkMtu(packet, 0, mtuBytes(68));
+        checkMtu(packet, 0, mtuBytes(Short.MIN_VALUE));
+        checkMtu(packet, 0, mtuBytes(Short.MAX_VALUE + 3));
+        checkMtu(packet, 0, mtuBytes(-1));
+    }
+
     @SmallTest
     public void testBadHwaddrLength() throws Exception {
         final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
@@ -453,7 +514,7 @@
         assertTrue(offerPacket instanceof DhcpOfferPacket);
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("172.17.152.118/16", "172.17.1.1", "172.17.1.1",
-                null, "1.1.1.1", null, 43200, false, dhcpResults);
+                null, "1.1.1.1", null, 43200, false, 0, dhcpResults);
     }
 
     @SmallTest
@@ -484,7 +545,7 @@
         assertTrue(offerPacket instanceof DhcpOfferPacket);
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("10.63.93.4/20", "10.63.80.1", "192.0.2.1,192.0.2.2",
-                "domain123.co.uk", "192.0.2.254", null, 49094, false, dhcpResults);
+                "domain123.co.uk", "192.0.2.254", null, 49094, false, 0, dhcpResults);
     }
 
     @SmallTest
@@ -518,7 +579,7 @@
         assertEquals("BCF5AC000000", HexDump.toHexString(offerPacket.getClientMac()));
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("10.32.158.205/20", "10.32.144.1", "148.88.65.52,148.88.65.53",
-                "lancs.ac.uk", "10.32.255.128", null, 7200, false, dhcpResults);
+                "lancs.ac.uk", "10.32.255.128", null, 7200, false, 0, dhcpResults);
     }
 
     @SmallTest
@@ -554,7 +615,7 @@
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("10.15.122.242/16", "10.15.200.23",
                 "209.129.128.3,209.129.148.3,209.129.128.6",
-                "wvm.edu", "10.1.105.252", null, 86400, false, dhcpResults);
+                "wvm.edu", "10.1.105.252", null, 86400, false, 0, dhcpResults);
     }
 
     @SmallTest
@@ -621,7 +682,7 @@
         assertEquals("FC3D93000000", HexDump.toHexString(offerPacket.getClientMac()));
         DhcpResults dhcpResults = offerPacket.toDhcpResults();
         assertDhcpResults("192.168.189.49/24", "192.168.189.1", "8.8.8.8,8.8.4.4",
-                null, "192.171.189.2", null, 28800, false, dhcpResults);
+                null, "192.171.189.2", null, 28800, false, 0, dhcpResults);
     }
 
     @SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 8e11511..2f20a4b 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -59,6 +59,7 @@
 import android.os.MessageQueue;
 import android.os.Messenger;
 import android.os.MessageQueue.IdleHandler;
+import android.os.Process;
 import android.os.SystemClock;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -690,6 +691,7 @@
         assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
         // Test getActiveNetwork()
         assertNotNull(mCm.getActiveNetwork());
+        assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
         switch (transport) {
             case TRANSPORT_WIFI:
                 assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
@@ -713,6 +715,7 @@
         assertNull(mCm.getActiveNetworkInfo());
         // Test getActiveNetwork()
         assertNull(mCm.getActiveNetwork());
+        assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
         // Test getAllNetworks()
         assertEquals(0, mCm.getAllNetworks().length);
     }
diff --git a/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java b/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java
index 5b70c17..07280bc 100644
--- a/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java
@@ -62,7 +62,7 @@
         ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
 
         for (int i = nums.length - 1; i >=0; --i) {
-            root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
+            root.collectObserversLocked(uris[i], 0, null, false, 0, myUserHandle, calls);
             assertEquals(nums[i], calls.size());
             calls.clear();
         }
@@ -92,7 +92,7 @@
         ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
 
         for (int i = uris.length - 1; i >=0; --i) {
-            root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
+            root.collectObserversLocked(uris[i], 0, null, false, 0, myUserHandle, calls);
             assertEquals(nums[i], calls.size());
             calls.clear();
         }
diff --git a/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
new file mode 100644
index 0000000..83a59fd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.notification;
+
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.Notification.Builder;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.Vibrator;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.StatusBarNotification;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class BuzzBeepBlinkTest extends AndroidTestCase {
+
+    @Mock AudioManager mAudioManager;
+    @Mock Vibrator mVibrator;
+    @Mock android.media.IRingtonePlayer mRingtonePlayer;
+    @Mock Handler mHandler;
+
+    private NotificationManagerService mService;
+    private String mPkg = "com.android.server.notification";
+    private int mId = 1001;
+    private int mOtherId = 1002;
+    private String mTag = null;
+    private int mUid = 1000;
+    private int mPid = 2000;
+    private int mScore = 10;
+    private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
+
+    @Override
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mAudioManager.isAudioFocusExclusive()).thenReturn(false);
+        when(mAudioManager.getRingtonePlayer()).thenReturn(mRingtonePlayer);
+        when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10);
+        when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
+
+        mService = new NotificationManagerService(getContext());
+        mService.setAudioManager(mAudioManager);
+        mService.setVibrator(mVibrator);
+        mService.setSystemReady(true);
+        mService.setHandler(mHandler);
+    }
+
+    //
+    // Convenience functions for creating notification records
+    //
+
+    private NotificationRecord getNoisyOtherNotification() {
+        return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
+                true /* noisy */, true /* buzzy*/);
+    }
+
+    private NotificationRecord getBeepyNotification() {
+        return getNotificationRecord(mId, false /* insistent */, false /* once */,
+                true /* noisy */, false /* buzzy*/);
+    }
+
+    private NotificationRecord getBeepyOnceNotification() {
+        return getNotificationRecord(mId, false /* insistent */, true /* once */,
+                true /* noisy */, false /* buzzy*/);
+    }
+
+    private NotificationRecord getQuietNotification() {
+        return getNotificationRecord(mId, false /* insistent */, false /* once */,
+                false /* noisy */, false /* buzzy*/);
+    }
+
+    private NotificationRecord getQuietOtherNotification() {
+        return getNotificationRecord(mOtherId, false /* insistent */, false /* once */,
+                false /* noisy */, false /* buzzy*/);
+    }
+
+    private NotificationRecord getQuietOnceNotification() {
+        return getNotificationRecord(mId, false /* insistent */, true /* once */,
+                false /* noisy */, false /* buzzy*/);
+    }
+
+    private NotificationRecord getInsistentBeepyNotification() {
+        return getNotificationRecord(mId, true /* insistent */, false /* once */,
+                true /* noisy */, false /* buzzy*/);
+    }
+
+    private NotificationRecord getBuzzyNotification() {
+        return getNotificationRecord(mId, false /* insistent */, false /* once */,
+                false /* noisy */, true /* buzzy*/);
+    }
+
+    private NotificationRecord getBuzzyOnceNotification() {
+        return getNotificationRecord(mId, false /* insistent */, true /* once */,
+                false /* noisy */, true /* buzzy*/);
+    }
+
+    private NotificationRecord getInsistentBuzzyNotification() {
+        return getNotificationRecord(mId, true /* insistent */, false /* once */,
+                false /* noisy */, true /* buzzy*/);
+    }
+
+    private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
+            boolean noisy, boolean buzzy) {
+        final Builder builder = new Builder(getContext())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setPriority(Notification.PRIORITY_HIGH)
+                .setOnlyAlertOnce(once);
+
+        int defaults = 0;
+        if (noisy) {
+            defaults |= Notification.DEFAULT_SOUND;
+        }
+        if (buzzy) {
+            defaults |= Notification.DEFAULT_VIBRATE;
+        }
+        builder.setDefaults(defaults);
+
+        Notification n = builder.build();
+        if (insistent) {
+            n.flags |= Notification.FLAG_INSISTENT;
+        }
+        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid, mPid,
+                mScore, n, mUser, System.currentTimeMillis());
+        return new NotificationRecord(getContext(), sbn);
+    }
+
+    //
+    // Convenience functions for interacting with mocks
+    //
+
+    private void verifyNeverBeep() throws RemoteException {
+        verify(mRingtonePlayer, never()).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
+                anyBoolean(), (AudioAttributes) anyObject());
+    }
+
+    private void verifyBeep() throws RemoteException {
+        verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
+                eq(true), (AudioAttributes) anyObject());
+    }
+
+    private void verifyBeepLooped() throws RemoteException {
+        verify(mRingtonePlayer, times(1)).playAsync((Uri) anyObject(), (UserHandle) anyObject(),
+                eq(false), (AudioAttributes) anyObject());
+    }
+
+    private void verifyNeverStopAudio() throws RemoteException {
+        verify(mRingtonePlayer, never()).stopAsync();
+    }
+
+    private void verifyStopAudio() throws RemoteException {
+        verify(mRingtonePlayer, times(1)).stopAsync();
+    }
+
+    private void verifyNeverVibrate() {
+        verify(mVibrator, never()).vibrate(anyInt(), anyString(), (long[]) anyObject(),
+                anyInt(), (AudioAttributes) anyObject());
+    }
+
+    private void verifyVibrate() {
+        verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), (long[]) anyObject(),
+                eq(-1), (AudioAttributes) anyObject());
+    }
+
+    private void verifyVibrateLooped() {
+        verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), (long[]) anyObject(),
+                eq(0), (AudioAttributes) anyObject());
+    }
+
+    private void verifyStopVibrate() {
+        verify(mVibrator, times(1)).cancel();
+    }
+
+    private void verifyNeverStopVibrate() throws RemoteException {
+        verify(mVibrator, never()).cancel();
+    }
+
+    @SmallTest
+    public void testBeep() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyBeepLooped();
+        verifyNeverVibrate();
+    }
+
+    //
+    // Tests
+    //
+
+    @SmallTest
+    public void testBeepInsistently() throws Exception {
+        NotificationRecord r = getInsistentBeepyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyBeep();
+    }
+
+    @SmallTest
+    public void testNoInterruptionForMin() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        r.setImportance(Ranking.IMPORTANCE_MIN, "foo");
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyNeverBeep();
+        verifyNeverVibrate();
+    }
+
+    @SmallTest
+    public void testNoInterruptionForIntercepted() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        r.setIntercepted(true);
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyNeverBeep();
+        verifyNeverVibrate();
+    }
+
+    @SmallTest
+    public void testBeepTwice() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        Mockito.reset(mRingtonePlayer);
+
+        // update should beep
+        r.isUpdate = true;
+        mService.buzzBeepBlinkLocked(r);
+        verifyBeepLooped();
+    }
+
+    @SmallTest
+    public void testHonorAlertOnlyOnceForBeep() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        NotificationRecord s = getBeepyOnceNotification();
+        s.isUpdate = true;
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        Mockito.reset(mRingtonePlayer);
+
+        // update should not beep
+        mService.buzzBeepBlinkLocked(s);
+        verifyNeverBeep();
+    }
+
+    @SmallTest
+    public void testNoisyUpdateDoesNotCancelAudio() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+        r.isUpdate = true;
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyNeverStopAudio();
+    }
+
+    @SmallTest
+    public void testNoisyOnceUpdateDoesNotCancelAudio() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        NotificationRecord s = getBeepyOnceNotification();
+        s.isUpdate = true;
+
+        mService.buzzBeepBlinkLocked(r);
+        mService.buzzBeepBlinkLocked(s);
+
+        verifyNeverStopAudio();
+    }
+
+    @SmallTest
+    public void testQuietUpdateDoesNotCancelAudioFromOther() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        NotificationRecord s = getQuietNotification();
+        s.isUpdate = true;
+        NotificationRecord other = getNoisyOtherNotification();
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        mService.buzzBeepBlinkLocked(other); // this takes the audio stream
+        Mockito.reset(mRingtonePlayer);
+
+        // should not stop noise, since we no longer own it
+        mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
+        verifyNeverStopAudio();
+    }
+
+    @SmallTest
+    public void testQuietInterloperDoesNotCancelAudio() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        NotificationRecord other = getQuietOtherNotification();
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        Mockito.reset(mRingtonePlayer);
+
+        // should not stop noise, since it does not own it
+        mService.buzzBeepBlinkLocked(other);
+        verifyNeverStopAudio();
+    }
+
+    @SmallTest
+    public void testQuietUpdateCancelsAudio() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        NotificationRecord s = getQuietNotification();
+        s.isUpdate = true;
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        Mockito.reset(mRingtonePlayer);
+
+        // quiet update should stop making noise
+        mService.buzzBeepBlinkLocked(s);
+        verifyStopAudio();
+    }
+
+    @SmallTest
+    public void testQuietOnceUpdateCancelsAudio() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        NotificationRecord s = getQuietOnceNotification();
+        s.isUpdate = true;
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        Mockito.reset(mRingtonePlayer);
+
+        // stop making noise - this is a weird corner case, but quiet should override once
+        mService.buzzBeepBlinkLocked(s);
+        verifyStopAudio();
+    }
+
+    @SmallTest
+    public void testDemoteSoundToVibrate() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+
+        // the phone is quiet
+        when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+        when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyNeverBeep();
+        verifyVibrate();
+    }
+
+    @SmallTest
+    public void testDemotInsistenteSoundToVibrate() throws Exception {
+        NotificationRecord r = getInsistentBeepyNotification();
+
+        // the phone is quiet
+        when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+        when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyVibrateLooped();
+    }
+
+    @SmallTest
+    public void testVibrate() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyNeverBeep();
+        verifyVibrate();
+    }
+
+    @SmallTest
+    public void testInsistenteVibrate() throws Exception {
+        NotificationRecord r = getInsistentBuzzyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+        verifyVibrateLooped();
+    }
+
+    @SmallTest
+    public void testVibratTwice() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        Mockito.reset(mVibrator);
+
+        // update should vibrate
+        r.isUpdate = true;
+        mService.buzzBeepBlinkLocked(r);
+        verifyVibrate();
+    }
+
+    @SmallTest
+    public void testHonorAlertOnlyOnceForBuzz() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+        NotificationRecord s = getBuzzyOnceNotification();
+        s.isUpdate = true;
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        Mockito.reset(mVibrator);
+
+        // update should not beep
+        mService.buzzBeepBlinkLocked(s);
+        verifyNeverVibrate();
+    }
+
+    @SmallTest
+    public void testNoisyUpdateDoesNotCancelVibrate() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+
+        mService.buzzBeepBlinkLocked(r);
+        r.isUpdate = true;
+        mService.buzzBeepBlinkLocked(r);
+
+        verifyNeverStopVibrate();
+    }
+
+    @SmallTest
+    public void testNoisyOnceUpdateDoesNotCancelVibrate() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+        NotificationRecord s = getBuzzyOnceNotification();
+        s.isUpdate = true;
+
+        mService.buzzBeepBlinkLocked(r);
+        mService.buzzBeepBlinkLocked(s);
+
+        verifyNeverStopVibrate();
+    }
+
+    @SmallTest
+    public void testQuietUpdateDoesNotCancelVibrateFromOther() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+        NotificationRecord s = getQuietNotification();
+        s.isUpdate = true;
+        NotificationRecord other = getNoisyOtherNotification();
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        mService.buzzBeepBlinkLocked(other); // this takes the vibrate stream
+        Mockito.reset(mVibrator);
+
+        // should not stop vibrate, since we no longer own it
+        mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
+        verifyNeverStopVibrate();
+    }
+
+    @SmallTest
+    public void testQuietInterloperDoesNotCancelVibrate() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+        NotificationRecord other = getQuietOtherNotification();
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        Mockito.reset(mVibrator);
+
+        // should not stop noise, since it does not own it
+        mService.buzzBeepBlinkLocked(other);
+        verifyNeverStopVibrate();
+    }
+
+    @SmallTest
+    public void testQuietUpdateCancelsVibrate() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+        NotificationRecord s = getQuietNotification();
+        s.isUpdate = true;
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+
+        // quiet update should stop making noise
+        mService.buzzBeepBlinkLocked(s);
+        verifyStopVibrate();
+    }
+
+    @SmallTest
+    public void testQuietOnceUpdateCancelsvibrate() throws Exception {
+        NotificationRecord r = getBuzzyNotification();
+        NotificationRecord s = getQuietOnceNotification();
+        s.isUpdate = true;
+
+        // set up internal state
+        mService.buzzBeepBlinkLocked(r);
+        Mockito.reset(mVibrator);
+
+        // stop making noise - this is a weird corner case, but quiet should override once
+        mService.buzzBeepBlinkLocked(s);
+        verifyStopVibrate();
+    }
+
+    @SmallTest
+    public void testQuietUpdateCancelsDemotedVibrate() throws Exception {
+        NotificationRecord r = getBeepyNotification();
+        NotificationRecord s = getQuietNotification();
+
+        // the phone is quiet
+        when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0);
+        when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+
+        mService.buzzBeepBlinkLocked(r);
+
+        // quiet update should stop making noise
+        mService.buzzBeepBlinkLocked(s);
+        verifyStopVibrate();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutInfoTest.java
deleted file mode 100644
index c44ffa4..0000000
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutInfoTest.java
+++ /dev/null
@@ -1,271 +0,0 @@
-
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.pm;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ShortcutInfo;
-import android.graphics.drawable.Icon;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.PersistableBundle;
-import android.test.AndroidTestCase;
-
-import com.android.internal.util.Preconditions;
-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 testMissingMandatoryFields() {
-        TestUtils.assertExpectException(
-                IllegalArgumentException.class,
-                "ID must be provided",
-                () -> new ShortcutInfo.Builder(mContext).build());
-        TestUtils.assertExpectException(
-                IllegalArgumentException.class,
-                "title must be provided",
-                () -> new ShortcutInfo.Builder(mContext).setId("id").build()
-                        .enforceMandatoryFields());
-        TestUtils.assertExpectException(
-                NullPointerException.class,
-                "Intent must be provided",
-                () -> new ShortcutInfo.Builder(mContext).setId("id").setTitle("x").build()
-                        .enforceMandatoryFields());
-    }
-
-    private ShortcutInfo parceled(ShortcutInfo si) {
-        Parcel p = Parcel.obtain();
-        p.writeParcelable(si, 0);
-        p.setDataPosition(0);
-        ShortcutInfo si2 = p.readParcelable(getClass().getClassLoader());
-        p.recycle();
-        return si2;
-    }
-
-    private Intent makeIntent(String action, Object... bundleKeysAndValues) {
-        final Intent intent = new Intent(action);
-        intent.replaceExtras(ShortcutManagerTest.makeBundle(bundleKeysAndValues));
-        return intent;
-    }
-
-    public void testParcel() {
-        ShortcutInfo si = parceled(new ShortcutInfo.Builder(getContext())
-                .setId("id")
-                .setTitle("title")
-                .setIntent(makeIntent("action"))
-                .build());
-        assertEquals(getContext().getPackageName(), si.getPackageName());
-        assertEquals("id", si.getId());
-        assertEquals("title", si.getTitle());
-        assertEquals("action", si.getIntent().getAction());
-
-        PersistableBundle pb = new PersistableBundle();
-        pb.putInt("k", 1);
-
-        si = new ShortcutInfo.Builder(getContext())
-                .setId("id")
-                .setActivityComponent(new ComponentName("a", "b"))
-                .setIcon(Icon.createWithContentUri("content://a.b.c/"))
-                .setTitle("title")
-                .setText("text")
-                .setIntent(makeIntent("action", "key", "val"))
-                .setWeight(123)
-                .setExtras(pb)
-                .build();
-        si.addFlags(ShortcutInfo.FLAG_PINNED);
-        si.setBitmapPath("abc");
-        si.setIconResourceId(456);
-
-        si = parceled(si);
-
-        assertEquals(getContext().getPackageName(), si.getPackageName());
-        assertEquals("id", si.getId());
-        assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
-        assertEquals("content://a.b.c/", si.getIcon().getUriString());
-        assertEquals("title", si.getTitle());
-        assertEquals("text", si.getText());
-        assertEquals("action", si.getIntent().getAction());
-        assertEquals("val", si.getIntent().getStringExtra("key"));
-        assertEquals(123, si.getWeight());
-        assertEquals(1, si.getExtras().getInt("k"));
-
-        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
-        assertEquals("abc", si.getBitmapPath());
-        assertEquals(456, si.getIconResourceId());
-    }
-
-    public void testClone() {
-        PersistableBundle pb = new PersistableBundle();
-        pb.putInt("k", 1);
-        ShortcutInfo sorig = new ShortcutInfo.Builder(getContext())
-                .setId("id")
-                .setActivityComponent(new ComponentName("a", "b"))
-                .setIcon(Icon.createWithContentUri("content://a.b.c/"))
-                .setTitle("title")
-                .setText("text")
-                .setIntent(makeIntent("action", "key", "val"))
-                .setWeight(123)
-                .setExtras(pb)
-                .build();
-        sorig.addFlags(ShortcutInfo.FLAG_PINNED);
-        sorig.setBitmapPath("abc");
-        sorig.setIconResourceId(456);
-
-        ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
-
-        assertEquals(getContext().getPackageName(), si.getPackageName());
-        assertEquals("id", si.getId());
-        assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
-        assertEquals("content://a.b.c/", si.getIcon().getUriString());
-        assertEquals("title", si.getTitle());
-        assertEquals("text", si.getText());
-        assertEquals("action", si.getIntent().getAction());
-        assertEquals("val", si.getIntent().getStringExtra("key"));
-        assertEquals(123, si.getWeight());
-        assertEquals(1, si.getExtras().getInt("k"));
-
-        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
-        assertEquals("abc", si.getBitmapPath());
-        assertEquals(456, si.getIconResourceId());
-
-        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
-
-        assertEquals(getContext().getPackageName(), si.getPackageName());
-        assertEquals("id", si.getId());
-        assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
-        assertEquals(null, si.getIcon());
-        assertEquals("title", si.getTitle());
-        assertEquals("text", si.getText());
-        assertEquals("action", si.getIntent().getAction());
-        assertEquals("val", si.getIntent().getStringExtra("key"));
-        assertEquals(123, si.getWeight());
-        assertEquals(1, si.getExtras().getInt("k"));
-
-        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
-        assertEquals(null, si.getBitmapPath());
-        assertEquals(0, si.getIconResourceId());
-
-        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
-
-        assertEquals(getContext().getPackageName(), si.getPackageName());
-        assertEquals("id", si.getId());
-        assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
-        assertEquals(null, si.getIcon());
-        assertEquals("title", si.getTitle());
-        assertEquals("text", si.getText());
-        assertEquals(null, si.getIntent());
-        assertEquals(123, si.getWeight());
-        assertEquals(1, si.getExtras().getInt("k"));
-
-        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
-        assertEquals(null, si.getBitmapPath());
-        assertEquals(0, si.getIconResourceId());
-
-        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
-
-        assertEquals(getContext().getPackageName(), si.getPackageName());
-        assertEquals("id", si.getId());
-        assertEquals(null, si.getActivityComponent());
-        assertEquals(null, si.getIcon());
-        assertEquals(null, si.getTitle());
-        assertEquals(null, si.getText());
-        assertEquals(null, si.getIntent());
-        assertEquals(0, si.getWeight());
-        assertEquals(null, si.getExtras());
-
-        assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
-        assertEquals(null, si.getBitmapPath());
-        assertEquals(0, si.getIconResourceId());
-    }
-
-
-    public void testCopyNonNullFieldsFrom() {
-        PersistableBundle pb = new PersistableBundle();
-        pb.putInt("k", 1);
-        ShortcutInfo sorig = new ShortcutInfo.Builder(getContext())
-                .setId("id")
-                .setActivityComponent(new ComponentName("a", "b"))
-                .setIcon(Icon.createWithContentUri("content://a.b.c/"))
-                .setTitle("title")
-                .setText("text")
-                .setIntent(makeIntent("action", "key", "val"))
-                .setWeight(123)
-                .setExtras(pb)
-                .build();
-        sorig.addFlags(ShortcutInfo.FLAG_PINNED);
-        sorig.setBitmapPath("abc");
-        sorig.setIconResourceId(456);
-
-        ShortcutInfo si;
-
-        si = sorig.clone(/* flags=*/ 0);
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getContext()).setId("id")
-                .setActivityComponent(new ComponentName("x", "y")).build());
-        assertEquals(new ComponentName("x", "y"), si.getActivityComponent());
-
-        si = sorig.clone(/* flags=*/ 0);
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getContext()).setId("id")
-                .setIcon(Icon.createWithContentUri("content://x.y.z/")).build());
-        assertEquals("content://x.y.z/", si.getIcon().getUriString());
-
-        si = sorig.clone(/* flags=*/ 0);
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getContext()).setId("id")
-                .setTitle("xyz").build());
-        assertEquals("xyz", si.getTitle());
-
-        si = sorig.clone(/* flags=*/ 0);
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getContext()).setId("id")
-                .setText("xxx").build());
-        assertEquals("xxx", si.getText());
-
-        si = sorig.clone(/* flags=*/ 0);
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getContext()).setId("id")
-                .setIntent(makeIntent("action2")).build());
-        assertEquals("action2", si.getIntent().getAction());
-        assertEquals(null, si.getIntent().getStringExtra("key"));
-
-        si = sorig.clone(/* flags=*/ 0);
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getContext()).setId("id")
-                .setIntent(makeIntent("action3", "key", "x")).build());
-        assertEquals("action3", si.getIntent().getAction());
-        assertEquals("x", si.getIntent().getStringExtra("key"));
-
-        si = sorig.clone(/* flags=*/ 0);
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getContext()).setId("id")
-                .setWeight(999).build());
-        assertEquals(999, si.getWeight());
-
-
-        PersistableBundle pb2 = new PersistableBundle();
-        pb2.putInt("x", 99);
-
-        si = sorig.clone(/* flags=*/ 0);
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getContext()).setId("id")
-                .setExtras(pb2).build());
-        assertEquals(99, si.getExtras().getInt("x"));
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index 5d29242..baa5d36 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -16,8 +16,11 @@
 package com.android.server.pm;
 
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyList;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
@@ -46,6 +49,7 @@
 import android.content.pm.ShortcutManager;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.Signature;
+import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
@@ -57,7 +61,9 @@
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -66,6 +72,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Pair;
 import android.util.SparseArray;
 
 import com.android.frameworks.servicestests.R;
@@ -76,6 +83,7 @@
 import com.android.server.pm.ShortcutService.ConfigConstants;
 import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
 import com.android.server.pm.ShortcutUser.PackageWithUser;
+import com.android.server.testutis.TestUtils;
 
 import libcore.io.IoUtils;
 
@@ -96,6 +104,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
 
 /**
  * Tests for ShortcutService and ShortcutManager.
@@ -107,10 +117,8 @@
  -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?)
+ * TODO: Detailed test for hasShortcutPermissionInner().
+ * TODO: Add tests for the command line functions too.
  */
 @SmallTest
 public class ShortcutManagerTest extends InstrumentationTestCase {
@@ -122,6 +130,8 @@
      */
     private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH true
 
+    private static final boolean DUMP_IN_TEARDOWN = false; // DO NOT SUBMIT WITH true
+
     // public for mockito
     public class BaseContext extends MockContext {
         @Override
@@ -260,8 +270,7 @@
 
         @Override
         boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
-            // Sort of hack; do a simpler check.
-            return LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage);
+            return mDefaultLauncherChecker.test(callingPackage, userId);
         }
 
         @Override
@@ -279,12 +288,7 @@
         @Override
         void postToHandler(Runnable r) {
             final long token = mContext.injectClearCallingIdentity();
-            super.postToHandler(r);
-            try {
-                runTestOnUiThread(() -> {});
-            } catch (Throwable e) {
-                fail("runTestOnUiThread failed: " + e);
-            }
+            r.run();
             mContext.injectRestoreCallingIdentity(token);
         }
 
@@ -316,36 +320,11 @@
         }
 
         @Override
-        public void ensureInUserProfiles(UserHandle userToCheck, String message) {
-            if (getCallingUserId() == userToCheck.getIdentifier()) {
-                return; // okay
-            }
-            if (getCallingUserId() == USER_0 && userToCheck.getIdentifier() == USER_P0) {
-                return; // profile, okay.
-            }
-            if (getCallingUserId() == USER_P0 && userToCheck.getIdentifier() == USER_0) {
-                return; // profile, okay.
-            }
-
-            if (mInjectedCallingUid != Process.SYSTEM_UID) {
-                throw new SecurityException("To access other users, you need to be SYSTEM" +
-                        ", but current UID=" + mInjectedCallingUid);
-            }
-        }
-
-        @Override
         public void verifyCallingPackage(String callingPackage) {
             // SKIP
         }
 
         @Override
-        boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser, String debugMsg) {
-            // This requires CROSS_USER
-            assertEquals(Process.SYSTEM_UID, mInjectedCallingUid);
-            return user.getIdentifier() == listeningUser.getIdentifier();
-        }
-
-        @Override
         void postToPackageMonitorHandler(Runnable r) {
             final long token = mContext.injectClearCallingIdentity();
             r.run();
@@ -356,6 +335,18 @@
         int injectBinderCallingUid() {
             return mInjectedCallingUid;
         }
+
+        @Override
+        long injectClearCallingIdentity() {
+            final int prevCallingUid = mInjectedCallingUid;
+            mInjectedCallingUid = Process.SYSTEM_UID;
+            return prevCallingUid;
+        }
+
+        @Override
+        void injectRestoreCallingIdentity(long token) {
+            mInjectedCallingUid = (int) token;
+        }
     }
 
     private class LauncherAppsTestable extends LauncherApps {
@@ -381,7 +372,11 @@
     private ShortcutServiceInternal mInternal;
 
     private LauncherAppImplTestable mLauncherAppImpl;
-    private LauncherAppsTestable mLauncherApps;
+
+    // LauncherApps has per-instace state, so we need a differnt instance for each launcher.
+    private final Map<Pair<Integer, String>, LauncherAppsTestable>
+            mLauncherAppsMap = new HashMap<>();
+    private LauncherAppsTestable mLauncherApps; // Current one
 
     private File mInjectedFilePathRoot;
 
@@ -394,7 +389,7 @@
 
     private Map<String, PackageInfo> mInjectedPackages;
 
-    private ArrayList<PackageWithUser> mUninstalledPackages;
+    private Set<PackageWithUser> mUninstalledPackages;
 
     private PackageManager mMockPackageManager;
     private PackageManagerInternal mMockPackageManagerInternal;
@@ -409,12 +404,21 @@
     private static final String CALLING_PACKAGE_3 = "com.android.test.3";
     private static final int CALLING_UID_3 = 10003;
 
+    private static final String CALLING_PACKAGE_4 = "com.android.test.4";
+    private static final int CALLING_UID_4 = 10004;
+
     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 String LAUNCHER_3 = "com.android.launcher.3";
+    private static final int LAUNCHER_UID_3 = 10013;
+
+    private static final String LAUNCHER_4 = "com.android.launcher.4";
+    private static final int LAUNCHER_UID_4 = 10014;
+
     private static final int USER_0 = UserHandle.USER_SYSTEM;
     private static final int USER_10 = 10;
     private static final int USER_11 = 11;
@@ -425,6 +429,24 @@
     private static final UserHandle HANDLE_USER_11 = UserHandle.of(USER_11);
     private static final UserHandle HANDLE_USER_P0 = UserHandle.of(USER_P0);
 
+    private static final UserInfo USER_INFO_0 = withProfileGroupId(
+            new UserInfo(USER_0, "user0",
+                    UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED), 10);
+
+    private static final UserInfo USER_INFO_10 =
+            new UserInfo(USER_10, "user10", UserInfo.FLAG_INITIALIZED);
+
+    private static final UserInfo USER_INFO_11 =
+            new UserInfo(USER_11, "user11", UserInfo.FLAG_INITIALIZED);
+
+    private static final UserInfo USER_INFO_P0 = withProfileGroupId(
+            new UserInfo(USER_P0, "userP0",
+                    UserInfo.FLAG_MANAGED_PROFILE), 10);
+
+    private BiPredicate<String, Integer> mDefaultLauncherChecker =
+            (callingPackage, userId) ->
+            LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage)
+            || LAUNCHER_3.equals(callingPackage) || LAUNCHER_4.equals(callingPackage);
 
     private static final long START_TIME = 1440000000101L;
 
@@ -438,6 +460,13 @@
 
     private static final int MAX_ICON_DIMENSION_LOWRAM = 32;
 
+    private static final ShortcutQuery QUERY_ALL = new ShortcutQuery();
+
+    static {
+        QUERY_ALL.setQueryFlags(
+                ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -457,30 +486,83 @@
         addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 1);
         addPackage(CALLING_PACKAGE_2, CALLING_UID_2, 2);
         addPackage(CALLING_PACKAGE_3, CALLING_UID_3, 3);
+        addPackage(CALLING_PACKAGE_4, CALLING_UID_4, 10);
         addPackage(LAUNCHER_1, LAUNCHER_UID_1, 4);
         addPackage(LAUNCHER_2, LAUNCHER_UID_2, 5);
+        addPackage(LAUNCHER_3, LAUNCHER_UID_3, 6);
+        addPackage(LAUNCHER_4, LAUNCHER_UID_4, 10);
 
-        mUninstalledPackages = new ArrayList<>();
+        // CALLING_PACKAGE_3 / LAUNCHER_3 are not backup target.
+        updatePackageInfo(CALLING_PACKAGE_3,
+                pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
+        updatePackageInfo(LAUNCHER_3,
+                pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
+
+        mUninstalledPackages = new HashSet<>();
 
         mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files");
 
-        // Empty the data directory.
-        if (mInjectedFilePathRoot.exists()) {
-            Assert.assertTrue("failed to delete dir",
-                    FileUtils.deleteContents(mInjectedFilePathRoot));
-        }
-        mInjectedFilePathRoot.mkdirs();
+        deleteAllSavedFiles();
+
+        // Set up users.
+        doAnswer(inv -> {
+                assertSystem();
+                return USER_INFO_0;
+        }).when(mMockUserManager).getUserInfo(eq(USER_0));
+
+        doAnswer(inv -> {
+                assertSystem();
+                return USER_INFO_10;
+        }).when(mMockUserManager).getUserInfo(eq(USER_10));
+
+        doAnswer(inv -> {
+                assertSystem();
+                return USER_INFO_11;
+        }).when(mMockUserManager).getUserInfo(eq(USER_11));
+
+        doAnswer(inv -> {
+                assertSystem();
+                return USER_INFO_P0;
+        }).when(mMockUserManager).getUserInfo(eq(USER_P0));
+
+        // User 0 is always running.
+        when(mMockUserManager.isUserRunning(eq(USER_0))).thenReturn(true);
 
         initService();
         setCaller(CALLING_PACKAGE_1);
     }
 
+    private static UserInfo withProfileGroupId(UserInfo in, int groupId) {
+        in.profileGroupId = groupId;
+        return in;
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (DUMP_IN_TEARDOWN) dumpsysOnLogcat("Teardown");
+
+        shutdownServices();
+
+        super.tearDown();
+    }
+
     private Context getTestContext() {
         return getInstrumentation().getContext();
     }
 
+    private void deleteAllSavedFiles() {
+        // Empty the data directory.
+        if (mInjectedFilePathRoot.exists()) {
+            Assert.assertTrue("failed to delete dir",
+                    FileUtils.deleteContents(mInjectedFilePathRoot));
+        }
+        mInjectedFilePathRoot.mkdirs();
+    }
+
     /** (Re-) init the manager and the service. */
     private void initService() {
+        shutdownServices();
+
         LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
 
         // Instantiate targets.
@@ -490,12 +572,28 @@
         mInternal = LocalServices.getService(ShortcutServiceInternal.class);
 
         mLauncherAppImpl = new LauncherAppImplTestable(mServiceContext);
-        mLauncherApps = new LauncherAppsTestable(mClientContext, mLauncherAppImpl);
+        mLauncherApps = null;
+        mLauncherAppsMap.clear();
 
         // Load the setting file.
         mService.onBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
     }
 
+    private void shutdownServices() {
+        if (mService != null) {
+            // Flush all the unsaved data from the previous instance.
+            mService.saveDirtyInfo();
+        }
+        LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
+
+        mService = null;
+        mManager = null;
+        mInternal = null;
+        mLauncherAppImpl = null;
+        mLauncherApps = null;
+        mLauncherAppsMap.clear();
+    }
+
     private void addPackage(String packageName, int uid, int version) {
         addPackage(packageName, uid, version, packageName);
     }
@@ -504,6 +602,10 @@
         return Arrays.asList(array);
     }
 
+    private <T> Set<T> set(Set<T> in) {
+        return new ArraySet<T>(in);
+    }
+
     private Signature[] genSignatures(String... signatures) {
         final Signature[] sigs = new Signature[signatures.length];
         for (int i = 0; i < signatures.length; i++){
@@ -529,10 +631,24 @@
         mInjectedPackages.put(packageName, genPackage(packageName, uid, version, signatures));
     }
 
+    private void updatePackageInfo(String packageName, Consumer<PackageInfo> c) {
+        c.accept(mInjectedPackages.get(packageName));
+    }
+
     private void uninstallPackage(int userId, String packageName) {
+        if (ENABLE_DUMP) {
+            Log.i(TAG, "Unnstall package " + packageName + " / " + userId);
+        }
         mUninstalledPackages.add(PackageWithUser.of(userId, packageName));
     }
 
+    private void installPackage(int userId, String packageName) {
+        if (ENABLE_DUMP) {
+            Log.i(TAG, "Install package " + packageName + " / " + userId);
+        }
+        mUninstalledPackages.remove(PackageWithUser.of(userId, packageName));
+    }
+
     PackageInfo getInjectedPackageInfo(String packageName, @UserIdInt int userId,
             boolean getSignatures) {
         final PackageInfo pi = mInjectedPackages.get(packageName);
@@ -560,6 +676,13 @@
         mInjectedCallingUid =
                 Preconditions.checkNotNull(getInjectedPackageInfo(packageName, userId, false),
                         "Unknown package").applicationInfo.uid;
+
+        // Set up LauncherApps for this caller.
+        final Pair<Integer, String> key = Pair.create(userId, packageName);
+        if (!mLauncherAppsMap.containsKey(key)) {
+            mLauncherAppsMap.put(key, new LauncherAppsTestable(mClientContext, mLauncherAppImpl));
+        }
+        mLauncherApps = mLauncherAppsMap.get(key);
     }
 
     private void setCaller(String packageName) {
@@ -570,6 +693,10 @@
         return mInjectedClientPackage;
     }
 
+    private void setDefaultLauncherChecker(BiPredicate<String, Integer> p) {
+        mDefaultLauncherChecker = p;
+    }
+
     private void runWithCaller(String packageName, int userId, Runnable r) {
         final String previousPackage = mInjectedClientPackage;
         final int previousUserId = UserHandle.getUserId(mInjectedCallingUid);
@@ -591,14 +718,22 @@
 
     /** For debugging */
     private void dumpsysOnLogcat() {
-        if (!ENABLE_DUMP) return;
+        dumpsysOnLogcat("");
+    }
+
+    private void dumpsysOnLogcat(String message) {
+        dumpsysOnLogcat(message, false);
+    }
+
+    private void dumpsysOnLogcat(String message, boolean force) {
+        if (force || !ENABLE_DUMP) return;
 
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
         final PrintWriter pw = new PrintWriter(out);
         mService.dumpInner(pw);
         pw.close();
 
-        Log.e(TAG, "Dumping ShortcutService:");
+        Log.e(TAG, "Dumping ShortcutService: " + message);
         for (String line : out.toString().split("\n")) {
             Log.e(TAG, line);
         }
@@ -608,9 +743,13 @@
      * For debugging, dump arbitrary file on logcat.
      */
     private void dumpFileOnLogcat(String path) {
+        dumpFileOnLogcat(path, "");
+    }
+
+    private void dumpFileOnLogcat(String path, String message) {
         if (!ENABLE_DUMP) return;
 
-        Log.i(TAG, "Dumping file: " + path);
+        Log.i(TAG, "Dumping file: " + path + " " + message);
         final StringBuilder sb = new StringBuilder();
         try (BufferedReader br = new BufferedReader(new FileReader(path))) {
             String line;
@@ -636,10 +775,14 @@
      * For debugging, dump per-user state file on logcat.
      */
     private void dumpUserFile(int userId) {
+        dumpUserFile(userId, "");
+    }
+
+    private void dumpUserFile(int userId, String message) {
         mService.saveDirtyInfo();
         dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
                 + "/user-" + userId
-                + "/" + ShortcutService.FILENAME_USER_PACKAGES);
+                + "/" + ShortcutService.FILENAME_USER_PACKAGES, message);
     }
 
     private void waitOnMainThread() throws Throwable {
@@ -778,6 +921,12 @@
         return ret;
     }
 
+    private static void resetAll(Collection<?> mocks) {
+        for (Object o : mocks) {
+            reset(o);
+        }
+    }
+
     @NonNull
     private ShortcutInfo findById(List<ShortcutInfo> list, String id) {
         for (ShortcutInfo s : list) {
@@ -789,6 +938,10 @@
         return null;
     }
 
+    private void assertSystem() {
+        assertEquals("Caller must be system", Process.SYSTEM_UID, mInjectedCallingUid);
+    }
+
     private void assertResetTimes(long expectedLastResetTime, long expectedNextResetTime) {
         assertEquals(expectedLastResetTime, mService.getLastResetTimeLocked());
         assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked());
@@ -877,7 +1030,7 @@
     private List<ShortcutInfo> assertAllHaveIcon(
             @NonNull List<ShortcutInfo> actualShortcuts) {
         for (ShortcutInfo s : actualShortcuts) {
-            assertTrue("ID " + s.getId(), s.hasIconFile() || s.hasIconResource());
+            assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource());
         }
         return actualShortcuts;
     }
@@ -886,7 +1039,8 @@
     private List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
             int shortcutFlags) {
         for (ShortcutInfo s : actualShortcuts) {
-            assertTrue("ID " + s.getId(), s.hasFlags(shortcutFlags));
+            assertTrue("ID " + s.getId() + " doesn't have flags " + shortcutFlags,
+                    s.hasFlags(shortcutFlags));
         }
         return actualShortcuts;
     }
@@ -1055,11 +1209,13 @@
         return i;
     }
 
-    /**
-     * Wrap a set in an ArraySet just to get a better toString.
-     */
-    private <T> Set<T> set(Set<T> in) {
-        return new ArraySet<T>(in);
+    private ShortcutInfo parceled(ShortcutInfo si) {
+        Parcel p = Parcel.obtain();
+        p.writeParcelable(si, 0);
+        p.setDataPosition(0);
+        ShortcutInfo si2 = p.readParcelable(getClass().getClassLoader());
+        p.recycle();
+        return si2;
     }
 
     /**
@@ -1320,8 +1476,6 @@
 
         // Still 2 calls left.
         assertEquals(2, mManager.getRemainingCallCount());
-
-        // TODO Make sure pinned shortcuts won't be deleted.
     }
 
     public void testDeleteAllDynamicShortcuts() {
@@ -1351,8 +1505,6 @@
 
         // Still 1 call left
         assertEquals(1, mManager.getRemainingCallCount());
-
-        // TODO Make sure pinned shortcuts won't be deleted.
     }
 
     public void testThrottling() {
@@ -1877,9 +2029,6 @@
         });
     }
 
-    // TODO: updateShortcuts()
-    // TODO: getPinnedShortcuts()
-
     // === Test for launcher side APIs ===
 
     private static ShortcutQuery buildQuery(long changedSince,
@@ -1893,6 +2042,20 @@
         return q;
     }
 
+    private static ShortcutQuery buildAllQuery(String packageName) {
+        final ShortcutQuery q = new ShortcutQuery();
+        q.setPackage(packageName);
+        q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+        return q;
+    }
+
+    private static ShortcutQuery buildPinnedQuery(String packageName) {
+        final ShortcutQuery q = new ShortcutQuery();
+        q.setPackage(packageName);
+        q.setQueryFlags(ShortcutQuery.FLAG_GET_PINNED);
+        return q;
+    }
+
     public void testGetShortcuts() {
 
         // Set up shortcuts.
@@ -2928,12 +3091,6 @@
     }
 
     public void testLauncherCallback() throws Throwable {
-
-        // TODO Add "multi" version -- run the test with two launchers and make sure the callback
-        // argument only contains the ones that are actually visible to each launcher.
-
-        when(mMockUserManager.isUserRunning(eq(USER_0))).thenReturn(true);
-
         LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
 
         // Set listeners
@@ -2989,6 +3146,7 @@
         // Test for addDynamicShortcut.
         reset(c0);
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            dumpsysOnLogcat("before addDynamicShortcut");
             assertTrue(mManager.addDynamicShortcut(makeShortcut("s4")));
         });
 
@@ -3052,6 +3210,7 @@
 
         // Remove CALLING_PACKAGE_2
         reset(c0);
+        uninstallPackage(USER_0, CALLING_PACKAGE_2);
         mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_0, USER_0);
 
         // Should get a callback with an empty list.
@@ -3065,6 +3224,156 @@
         assertEquals(0, shortcuts.getValue().size());
     }
 
+    private void assertCallbackNotReceived(LauncherApps.Callback mock) {
+        verify(mock, times(0)).onShortcutsChanged(anyString(), anyList(),
+                any(UserHandle.class));
+    }
+
+    private void assertCallbackReceived(LauncherApps.Callback mock,
+            UserHandle user, String packageName, String... ids) {
+        ArgumentCaptor<List> shortcutsCaptor = ArgumentCaptor.forClass(List.class);
+
+        verify(mock, times(1)).onShortcutsChanged(eq(packageName), shortcutsCaptor.capture(),
+                eq(user));
+        assertShortcutIds(shortcutsCaptor.getValue(), ids);
+    }
+
+    public void testLauncherCallback_crossProfile() throws Throwable {
+        prepareCrossProfileDataSet();
+
+        final Handler h = new Handler(Looper.getMainLooper());
+
+        final LauncherApps.Callback c0_1 = mock(LauncherApps.Callback.class);
+        final LauncherApps.Callback c0_2 = mock(LauncherApps.Callback.class);
+        final LauncherApps.Callback c0_3 = mock(LauncherApps.Callback.class);
+        final LauncherApps.Callback c0_4 = mock(LauncherApps.Callback.class);
+
+        final LauncherApps.Callback cP0_1 = mock(LauncherApps.Callback.class);
+        final LauncherApps.Callback c10_1 = mock(LauncherApps.Callback.class);
+        final LauncherApps.Callback c10_2 = mock(LauncherApps.Callback.class);
+        final LauncherApps.Callback c11_1 = mock(LauncherApps.Callback.class);
+
+        final List<LauncherApps.Callback> all =
+                list(c0_1, c0_2, c0_3, c0_4, cP0_1, c10_1, c11_1);
+
+        setDefaultLauncherChecker((pkg, userId) -> {
+            switch (userId) {
+                case USER_0:
+                    return LAUNCHER_2.equals(pkg);
+                case USER_P0:
+                    return LAUNCHER_1.equals(pkg);
+                case USER_10:
+                    return LAUNCHER_1.equals(pkg);
+                case USER_11:
+                    return LAUNCHER_1.equals(pkg);
+                default:
+                    return false;
+            }
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> mLauncherApps.registerCallback(c0_1, h));
+        runWithCaller(LAUNCHER_2, USER_0, () -> mLauncherApps.registerCallback(c0_2, h));
+        runWithCaller(LAUNCHER_3, USER_0, () -> mLauncherApps.registerCallback(c0_3, h));
+        runWithCaller(LAUNCHER_4, USER_0, () -> mLauncherApps.registerCallback(c0_4, h));
+        runWithCaller(LAUNCHER_1, USER_P0, () -> mLauncherApps.registerCallback(cP0_1, h));
+        runWithCaller(LAUNCHER_1, USER_10, () -> mLauncherApps.registerCallback(c10_1, h));
+        runWithCaller(LAUNCHER_2, USER_10, () -> mLauncherApps.registerCallback(c10_2, h));
+        runWithCaller(LAUNCHER_1, USER_11, () -> mLauncherApps.registerCallback(c11_1, h));
+
+        // User 0.
+
+        resetAll(all);
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            mManager.deleteDynamicShortcut("x");
+        });
+        waitOnMainThread();
+
+        assertCallbackNotReceived(c0_1);
+        assertCallbackNotReceived(c0_3);
+        assertCallbackNotReceived(c0_4);
+        assertCallbackNotReceived(c10_1);
+        assertCallbackNotReceived(c10_2);
+        assertCallbackNotReceived(c11_1);
+        assertCallbackReceived(c0_2, HANDLE_USER_0, CALLING_PACKAGE_1, "s1", "s2", "s3");
+        assertCallbackReceived(cP0_1, HANDLE_USER_0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s4");
+
+        // User 0, different package.
+
+        resetAll(all);
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            mManager.deleteDynamicShortcut("x");
+        });
+        waitOnMainThread();
+
+        assertCallbackNotReceived(c0_1);
+        assertCallbackNotReceived(c0_3);
+        assertCallbackNotReceived(c0_4);
+        assertCallbackNotReceived(c10_1);
+        assertCallbackNotReceived(c10_2);
+        assertCallbackNotReceived(c11_1);
+        assertCallbackReceived(c0_2, HANDLE_USER_0, CALLING_PACKAGE_3, "s1", "s2", "s3", "s4");
+        assertCallbackReceived(cP0_1, HANDLE_USER_0, CALLING_PACKAGE_3,
+                "s1", "s2", "s3", "s4", "s5", "s6");
+
+        // Work profile, but not running, so don't send notifications.
+
+        resetAll(all);
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            mManager.deleteDynamicShortcut("x");
+        });
+        waitOnMainThread();
+
+        assertCallbackNotReceived(c0_1);
+        assertCallbackNotReceived(c0_2);
+        assertCallbackNotReceived(c0_3);
+        assertCallbackNotReceived(c0_4);
+        assertCallbackNotReceived(cP0_1);
+        assertCallbackNotReceived(c10_1);
+        assertCallbackNotReceived(c10_2);
+        assertCallbackNotReceived(c11_1);
+
+        // Work profile, now running.
+
+        when(mMockUserManager.isUserRunning(anyInt())).thenReturn(false);
+        when(mMockUserManager.isUserRunning(eq(USER_P0))).thenReturn(true);
+
+        resetAll(all);
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            mManager.deleteDynamicShortcut("x");
+        });
+        waitOnMainThread();
+
+        assertCallbackNotReceived(c0_1);
+        assertCallbackNotReceived(c0_3);
+        assertCallbackNotReceived(c0_4);
+        assertCallbackNotReceived(c10_1);
+        assertCallbackNotReceived(c10_2);
+        assertCallbackNotReceived(c11_1);
+        assertCallbackReceived(c0_2, HANDLE_USER_P0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s5");
+        assertCallbackReceived(cP0_1, HANDLE_USER_P0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s4");
+
+        // Normal secondary user.
+
+        when(mMockUserManager.isUserRunning(anyInt())).thenReturn(false);
+        when(mMockUserManager.isUserRunning(eq(USER_10))).thenReturn(true);
+
+        resetAll(all);
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            mManager.deleteDynamicShortcut("x");
+        });
+        waitOnMainThread();
+
+        assertCallbackNotReceived(c0_1);
+        assertCallbackNotReceived(c0_2);
+        assertCallbackNotReceived(c0_3);
+        assertCallbackNotReceived(c0_4);
+        assertCallbackNotReceived(cP0_1);
+        assertCallbackNotReceived(c10_2);
+        assertCallbackNotReceived(c11_1);
+        assertCallbackReceived(c10_1, HANDLE_USER_10, CALLING_PACKAGE_1,
+                "x1", "x2", "x3", "x4", "x5");
+    }
+
     // === Test for persisting ===
 
     public void testSaveAndLoadUser_empty() {
@@ -3299,9 +3608,9 @@
         // Check the registered packages.
         dumpsysOnLogcat();
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
-                set(user0.getPackages().keySet()));
+                set(user0.getAllPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
-                set(user10.getPackages().keySet()));
+                set(user10.getAllPackages().keySet()));
         assertEquals(
                 makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
                         PackageWithUser.of(USER_0, LAUNCHER_2)),
@@ -3326,13 +3635,14 @@
         mService.saveDirtyInfo();
 
         // Nonexistent package.
+        uninstallPackage(USER_0, "abc");
         mService.cleanUpPackageLocked("abc", USER_0, USER_0);
 
         // No changes.
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
-                set(user0.getPackages().keySet()));
+                set(user0.getAllPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
-                set(user10.getPackages().keySet()));
+                set(user10.getAllPackages().keySet()));
         assertEquals(
                 makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
                         PackageWithUser.of(USER_0, LAUNCHER_2)),
@@ -3357,12 +3667,13 @@
         mService.saveDirtyInfo();
 
         // Remove a package.
+        uninstallPackage(USER_0, CALLING_PACKAGE_1);
         mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
-                set(user0.getPackages().keySet()));
+                set(user0.getAllPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
-                set(user10.getPackages().keySet()));
+                set(user10.getAllPackages().keySet()));
         assertEquals(
                 makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
                         PackageWithUser.of(USER_0, LAUNCHER_2)),
@@ -3387,12 +3698,13 @@
         mService.saveDirtyInfo();
 
         // Remove a launcher.
+        uninstallPackage(USER_10, LAUNCHER_1);
         mService.cleanUpPackageLocked(LAUNCHER_1, USER_10, USER_10);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
-                set(user0.getPackages().keySet()));
+                set(user0.getAllPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
-                set(user10.getPackages().keySet()));
+                set(user10.getAllPackages().keySet()));
         assertEquals(
                 makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
                         PackageWithUser.of(USER_0, LAUNCHER_2)),
@@ -3414,12 +3726,13 @@
         mService.saveDirtyInfo();
 
         // Remove a package.
+        uninstallPackage(USER_10, CALLING_PACKAGE_2);
         mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10, USER_10);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
-                set(user0.getPackages().keySet()));
+                set(user0.getAllPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1),
-                set(user10.getPackages().keySet()));
+                set(user10.getAllPackages().keySet()));
         assertEquals(
                 makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
                         PackageWithUser.of(USER_0, LAUNCHER_2)),
@@ -3441,12 +3754,13 @@
         mService.saveDirtyInfo();
 
         // Remove the other launcher from user 10 too.
+        uninstallPackage(USER_10, LAUNCHER_2);
         mService.cleanUpPackageLocked(LAUNCHER_2, USER_10, USER_10);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
-                set(user0.getPackages().keySet()));
+                set(user0.getAllPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1),
-                set(user10.getPackages().keySet()));
+                set(user10.getAllPackages().keySet()));
         assertEquals(
                 makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
                         PackageWithUser.of(USER_0, LAUNCHER_2)),
@@ -3468,12 +3782,13 @@
         mService.saveDirtyInfo();
 
         // More remove.
+        uninstallPackage(USER_10, CALLING_PACKAGE_1);
         mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10, USER_10);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
-                set(user0.getPackages().keySet()));
+                set(user0.getAllPackages().keySet()));
         assertEquals(makeSet(),
-                set(user10.getPackages().keySet()));
+                set(user10.getAllPackages().keySet()));
         assertEquals(
                 makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
                         PackageWithUser.of(USER_0, LAUNCHER_2)),
@@ -3494,97 +3809,6 @@
         mService.saveDirtyInfo();
     }
 
-
-    public void testSaveAndLoadUser_forBackup() {
-        // Create some shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
-        });
-        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
-        });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
-        });
-
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
-
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
-
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
-
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
-
-        // Pin some.
-
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s1"), HANDLE_USER_0);
-
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s2"), UserHandle.of(USER_P0));
-
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    list("s3"), HANDLE_USER_0);
-        });
-
-        runWithCaller(LAUNCHER_1, USER_P0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s2"), HANDLE_USER_0);
-
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s3"), UserHandle.of(USER_P0));
-
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    list("s1"), HANDLE_USER_0);
-        });
-
-        runWithCaller(LAUNCHER_1, USER_10, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s3"), HANDLE_USER_10);
-        });
-
-        // Check the state.
-
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
-
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
-
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
-
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
-
-        // Make sure all the information is persisted.
-        mService.saveDirtyInfo();
-        initService();
-        mService.handleUnlockUser(USER_0);
-        mService.handleUnlockUser(USER_P0);
-        mService.handleUnlockUser(USER_10);
-    }
-
     public void testHandleGonePackage_crossProfile() {
         // Create some shortcuts.
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -3841,13 +4065,9 @@
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
     }
 
-    // TODO Detailed test for hasShortcutPermissionInner().
-
-    // TODO Add tests for the command line functions too.
-
     private void checkCanRestoreTo(boolean expected, ShortcutPackageInfo spi,
             int version, String... signatures) {
-        assertEquals(expected, spi.canRestoreTo(genPackage(
+        assertEquals(expected, spi.canRestoreTo(mService, genPackage(
                 "dummy", /* uid */ 0, version, signatures)));
     }
 
@@ -3919,6 +4139,7 @@
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        uninstallPackage(USER_0, CALLING_PACKAGE_1);
         mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageDeleteIntent(CALLING_PACKAGE_1, USER_0));
 
@@ -3929,6 +4150,7 @@
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
 
+        uninstallPackage(USER_10, CALLING_PACKAGE_2);
         mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageDeleteIntent(CALLING_PACKAGE_2, USER_10));
 
@@ -3961,7 +4183,1193 @@
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
     }
 
-    public void testHandlePackageUpdate() {
-        // TODO: Make sure unshadow is called.
+    private void backupAndRestore() {
+        int prevUid = mInjectedCallingUid;
+
+        mInjectedCallingUid = Process.SYSTEM_UID; // Only system can call it.
+
+        dumpsysOnLogcat("Before backup");
+
+        final byte[] payload =  mService.getBackupPayload(USER_0);
+        if (ENABLE_DUMP) {
+            final String xml = new String(payload);
+            Log.i(TAG, "Backup payload:");
+            for (String line : xml.split("\n")) {
+                Log.i(TAG, line);
+            }
+        }
+
+        // Before doing anything else, uninstall all packages.
+        for (int userId : list(USER_0, USER_P0)) {
+            for (String pkg : list(CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3,
+                    LAUNCHER_1, LAUNCHER_2, LAUNCHER_3)) {
+                uninstallPackage(userId, pkg);
+            }
+        }
+
+        shutdownServices();
+
+        deleteAllSavedFiles();
+
+        initService();
+        mService.applyRestore(payload, USER_0);
+
+        // handleUnlockUser will perform the gone package check, but it shouldn't remove
+        // shadow information.
+        mService.handleUnlockUser(USER_0);
+
+        dumpsysOnLogcat("After restore");
+
+        mInjectedCallingUid = prevUid;
+    }
+
+    private void prepareCrossProfileDataSet() {
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
+                    makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
+                    makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
+        });
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
+                    makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
+        });
+        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list()));
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
+                    makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"),
+                    makeShortcut("x4"), makeShortcut("x5"), makeShortcut("x6"))));
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s1", "s2"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s1", "s2", "s3"), HANDLE_USER_0);
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s4"), HANDLE_USER_P0);
+        });
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s2", "s3"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s2", "s3", "s4"), HANDLE_USER_0);
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s5"), HANDLE_USER_P0);
+        });
+        runWithCaller(LAUNCHER_3, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5"), HANDLE_USER_0);
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s6"), HANDLE_USER_P0);
+        });
+        runWithCaller(LAUNCHER_4, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list(), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_4, list(), HANDLE_USER_0);
+        });
+
+        // Launcher on a managed profile is referring ot user 0!
+        runWithCaller(LAUNCHER_1, USER_P0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s4"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4", "s5"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5", "s6"),
+                    HANDLE_USER_0);
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s4", "s1"), HANDLE_USER_P0);
+        });
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("x4", "x5"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("x4", "x5", "x6"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("x4", "x5", "x6", "x1"),
+                    HANDLE_USER_10);
+        });
+
+        // Then remove some dynamic shortcuts.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list()));
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"))));
+        });
+    }
+
+    private void prepareForBackupTest() {
+
+        prepareCrossProfileDataSet();
+
+        backupAndRestore();
+    }
+
+    private void assertExistsAndShadow(ShortcutPackageItem spi) {
+        assertNotNull(spi);
+        assertTrue(spi.getPackageInfo().isShadow());
+    }
+
+    /**
+     * Make sure the backup data doesn't have the following information:
+     * - Launchers on other users.
+     * - Non-backup app information.
+     *
+     * But restores all other infomation.
+     *
+     * It also omits the following pieces of information, but that's tested in
+     * {@link #testShortcutInfoSaveAndLoad_forBackup}.
+     * - Unpinned dynamic shortcuts
+     * - Bitmaps
+     */
+    public void testBackupAndRestore() {
+        prepareForBackupTest();
+
+        checkBackupAndRestore_success();
+    }
+
+    public void testBackupAndRestore_backupRestoreTwice() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        dumpsysOnLogcat("Before second backup");
+
+        backupAndRestore();
+
+        dumpsysOnLogcat("After second backup");
+
+        checkBackupAndRestore_success();
+    }
+
+    public void testBackupAndRestore_backupRestoreMultiple() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        // This also shouldn't affect the result.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
+                    makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
+        });
+
+        backupAndRestore();
+
+        checkBackupAndRestore_success();
+    }
+
+    public void testBackupAndRestore_restoreToNewVersion() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 2);
+        addPackage(LAUNCHER_1, LAUNCHER_UID_1, 5);
+
+        checkBackupAndRestore_success();
+    }
+
+    public void testBackupAndRestore_restoreToSuperSetSignatures() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        // Change package signatures.
+        addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 1, "sigx", CALLING_PACKAGE_1);
+        addPackage(LAUNCHER_1, LAUNCHER_UID_1, 4, LAUNCHER_1, "sigy");
+
+        checkBackupAndRestore_success();
+    }
+
+    private void checkBackupAndRestore_success() {
+        // Make sure non-system user is not restored.
+        final ShortcutUser userP0 = mService.getUserShortcutsLocked(USER_P0);
+        assertEquals(0, userP0.getAllPackages().size());
+        assertEquals(0, userP0.getAllLaunchers().size());
+
+        // Make sure only "allowBackup" apps are restored, and are shadow.
+        final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
+        assertExistsAndShadow(user0.getAllPackages().get(CALLING_PACKAGE_1));
+        assertExistsAndShadow(user0.getAllPackages().get(CALLING_PACKAGE_2));
+        assertExistsAndShadow(user0.getAllLaunchers().get(PackageWithUser.of(USER_0, LAUNCHER_1)));
+        assertExistsAndShadow(user0.getAllLaunchers().get(PackageWithUser.of(USER_0, LAUNCHER_2)));
+
+        assertNull(user0.getAllPackages().get(CALLING_PACKAGE_3));
+        assertNull(user0.getAllLaunchers().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
+        assertNull(user0.getAllLaunchers().get(PackageWithUser.of(USER_P0, LAUNCHER_1)));
+
+        installPackage(USER_0, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s1", "s2");
+        });
+
+        installPackage(USER_0, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    /* empty, not restored */ );
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty, not restored */ );
+
+            assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+        });
+
+        installPackage(USER_0, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s1", "s2", "s3");
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s1", "s2");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty, not restored */ );
+
+            assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+        });
+
+        // 3 shouldn't be backed up, so no pinned shortcuts.
+        installPackage(USER_0, CALLING_PACKAGE_3);
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
+
+        // Launcher on a different profile shouldn't be restored.
+        runWithCaller(LAUNCHER_1, USER_P0, () -> {
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)
+                    .size());
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)
+                            .size());
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* wasn't restored, so still empty */ );
+        });
+
+        // Package on a different profile, no restore.
+        installPackage(USER_P0, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
+
+        // Restore launcher 2 on user 0.
+        installPackage(USER_0, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
+                    "s2");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* wasn't restored, so still empty */ );
+
+            assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+        });
+
+
+        // Restoration of launcher2 shouldn't affect other packages; so do the same checks and
+        // make sure they still have the same result.
+        installPackage(USER_0, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s1", "s2");
+        });
+
+        installPackage(USER_0, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s1", "s2");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* wasn't restored, so still empty */ );
+
+            assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+        });
+
+        installPackage(USER_0, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s1", "s2", "s3");
+        });
+    }
+
+    public void testBackupAndRestore_publisherLowerVersion() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 0); // Lower version
+
+        checkBackupAndRestore_publisherNotRestored();
+    }
+
+    public void testBackupAndRestore_publisherWrongSignature() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "sigx"); // different signature
+
+        checkBackupAndRestore_publisherNotRestored();
+    }
+
+    public void testBackupAndRestore_publisherNoLongerBackupTarget() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        updatePackageInfo(CALLING_PACKAGE_1,
+                pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
+
+        checkBackupAndRestore_publisherNotRestored();
+    }
+
+    private void checkBackupAndRestore_publisherNotRestored() {
+        installPackage(USER_0, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
+
+        installPackage(USER_0, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s1", "s2", "s3");
+        });
+
+        installPackage(USER_0, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s1", "s2");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+        installPackage(USER_0, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+
+        installPackage(USER_0, CALLING_PACKAGE_3);
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s1", "s2");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+    }
+
+    public void testBackupAndRestore_launcherLowerVersion() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        addPackage(LAUNCHER_1, LAUNCHER_UID_1, 0); // Lower version
+
+        checkBackupAndRestore_launcherNotRestored();
+    }
+
+    public void testBackupAndRestore_launcherWrongSignature() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        addPackage(LAUNCHER_1, LAUNCHER_UID_1, 10, "sigx"); // different signature
+
+        checkBackupAndRestore_launcherNotRestored();
+    }
+
+    public void testBackupAndRestore_launcherNoLongerBackupTarget() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        updatePackageInfo(LAUNCHER_1,
+                pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
+
+        checkBackupAndRestore_launcherNotRestored();
+    }
+
+    private void checkBackupAndRestore_launcherNotRestored() {
+        installPackage(USER_0, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+
+            // s1 was pinned by launcher 1, which is not restored, yet, so we still see "s1" here.
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s1", "s2");
+        });
+
+        installPackage(USER_0, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s1", "s2", "s3");
+        });
+
+        // Now we try to restore launcher 1.  Then we realize it's not restorable, so L1 has no pinned
+        // shortcuts.
+        installPackage(USER_0, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+
+            // Now CALLING_PACKAGE_1 realizes "s1" is no longer pinned.
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s2");
+        });
+
+        installPackage(USER_0, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
+                    "s2");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+
+        installPackage(USER_0, CALLING_PACKAGE_3);
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
+                    "s2");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+    }
+
+    public void testBackupAndRestore_launcherAndPackageNoLongerBackupTarget() {
+        prepareForBackupTest();
+
+        // Note doing a backup & restore again here shouldn't affect the result.
+        backupAndRestore();
+
+        updatePackageInfo(CALLING_PACKAGE_1,
+                pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
+
+        updatePackageInfo(LAUNCHER_1,
+                pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
+
+        checkBackupAndRestore_publisherAndLauncherNotRestored();
+    }
+
+    private void checkBackupAndRestore_publisherAndLauncherNotRestored() {
+        installPackage(USER_0, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
+
+        installPackage(USER_0, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s1", "s2", "s3");
+        });
+
+        installPackage(USER_0, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+        installPackage(USER_0, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+
+        // Because launcher 1 wasn't restored, "s1" is no longer pinned.
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s2", "s3");
+        });
+
+        installPackage(USER_0, CALLING_PACKAGE_3);
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    /* empty */);
+        });
+    }
+
+    public void testSaveAndLoad_crossProfile() {
+        prepareCrossProfileDataSet();
+
+        dumpsysOnLogcat("Before save & load");
+
+        mService.saveDirtyInfo();
+        initService();
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
+                    "s1", "s2", "s3", "s4");
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
+                    "s1", "s2", "s3", "s4", "s5");
+        });
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
+                    "s1", "s2", "s3", "s4", "s5", "s6");
+        });
+        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts())
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts())
+                    /* empty */);
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
+                    "s1", "s2", "s3", "s4", "s5", "s6");
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_P0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts())
+                    /* empty */);
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts())
+                    /* empty */);
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
+                    "x1", "x2", "x3");
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
+                    "x4", "x5");
+        });
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0),
+                    "s1");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0),
+                    "s1", "s2");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0),
+                    "s1", "s2", "s3");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_0)
+                    /* empty */);
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
+                    "s1", "s4");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_P0)
+                    /* empty */);
+            TestUtils.assertExpectException(
+                    SecurityException.class, "", () -> {
+                        mLauncherApps.getShortcuts(
+                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
+                    });
+        });
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0),
+                    "s2");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0),
+                    "s2", "s3");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0),
+                    "s2", "s3", "s4");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_0)
+                    /* empty */);
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
+                    "s2", "s5");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_P0)
+                    /* empty */);
+        });
+        runWithCaller(LAUNCHER_3, USER_0, () -> {
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0),
+                    "s3");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0),
+                    "s3", "s4");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0),
+                    "s3", "s4", "s5");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_0)
+                    /* empty */);
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
+                    "s3", "s6");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_P0)
+                    /* empty */);
+        });
+        runWithCaller(LAUNCHER_4, USER_0, () -> {
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0)
+                    /* empty */);
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0)
+                    /* empty */);
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0)
+                    /* empty */);
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_0)
+                    /* empty */);
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0)
+                    /* empty */);
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_P0)
+                    /* empty */);
+        });
+        runWithCaller(LAUNCHER_1, USER_P0, () -> {
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0),
+                    "s3", "s4");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0),
+                    "s3", "s4", "s5");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0),
+                    "s3", "s4", "s5", "s6");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
+                    "s1", "s4");
+            TestUtils.assertExpectException(
+                    SecurityException.class, "unrelated profile", () -> {
+                        mLauncherApps.getShortcuts(
+                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
+                    });
+        });
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_10),
+                    "x4", "x5");
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_10)
+                    /* empty */);
+            assertShortcutIds(
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10)
+                    /* empty */);
+            TestUtils.assertExpectException(
+                    SecurityException.class, "unrelated profile", () -> {
+                        mLauncherApps.getShortcuts(
+                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0);
+                    });
+            TestUtils.assertExpectException(
+                    SecurityException.class, "unrelated profile", () -> {
+                        mLauncherApps.getShortcuts(
+                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_P0);
+                    });
+        });
+    }
+
+    // ShortcutInfo tests
+
+    public void testShortcutInfoMissingMandatoryFields() {
+        TestUtils.assertExpectException(
+                IllegalArgumentException.class,
+                "ID must be provided",
+                () -> new ShortcutInfo.Builder(getTestContext()).build());
+        TestUtils.assertExpectException(
+                IllegalArgumentException.class,
+                "title must be provided",
+                () -> new ShortcutInfo.Builder(getTestContext()).setId("id").build()
+                        .enforceMandatoryFields());
+        TestUtils.assertExpectException(
+                NullPointerException.class,
+                "Intent must be provided",
+                () -> new ShortcutInfo.Builder(getTestContext()).setId("id").setTitle("x").build()
+                        .enforceMandatoryFields());
+    }
+
+    public void testShortcutInfoParcel() {
+        ShortcutInfo si = parceled(new ShortcutInfo.Builder(getTestContext())
+                .setId("id")
+                .setTitle("title")
+                .setIntent(makeIntent("action", ShortcutActivity.class))
+                .build());
+        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals("id", si.getId());
+        assertEquals("title", si.getTitle());
+        assertEquals("action", si.getIntent().getAction());
+
+        PersistableBundle pb = new PersistableBundle();
+        pb.putInt("k", 1);
+
+        si = new ShortcutInfo.Builder(getTestContext())
+                .setId("id")
+                .setActivityComponent(new ComponentName("a", "b"))
+                .setIcon(Icon.createWithContentUri("content://a.b.c/"))
+                .setTitle("title")
+                .setText("text")
+                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+                .setWeight(123)
+                .setExtras(pb)
+                .build();
+        si.addFlags(ShortcutInfo.FLAG_PINNED);
+        si.setBitmapPath("abc");
+        si.setIconResourceId(456);
+
+        si = parceled(si);
+
+        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals("id", si.getId());
+        assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
+        assertEquals("content://a.b.c/", si.getIcon().getUriString());
+        assertEquals("title", si.getTitle());
+        assertEquals("text", si.getText());
+        assertEquals("action", si.getIntent().getAction());
+        assertEquals("val", si.getIntent().getStringExtra("key"));
+        assertEquals(123, si.getWeight());
+        assertEquals(1, si.getExtras().getInt("k"));
+
+        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+        assertEquals("abc", si.getBitmapPath());
+        assertEquals(456, si.getIconResourceId());
+    }
+
+    public void testShortcutInfoClone() {
+        PersistableBundle pb = new PersistableBundle();
+        pb.putInt("k", 1);
+        ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
+                .setId("id")
+                .setActivityComponent(new ComponentName("a", "b"))
+                .setIcon(Icon.createWithContentUri("content://a.b.c/"))
+                .setTitle("title")
+                .setText("text")
+                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+                .setWeight(123)
+                .setExtras(pb)
+                .build();
+        sorig.addFlags(ShortcutInfo.FLAG_PINNED);
+        sorig.setBitmapPath("abc");
+        sorig.setIconResourceId(456);
+
+        ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
+
+        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals("id", si.getId());
+        assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
+        assertEquals("content://a.b.c/", si.getIcon().getUriString());
+        assertEquals("title", si.getTitle());
+        assertEquals("text", si.getText());
+        assertEquals("action", si.getIntent().getAction());
+        assertEquals("val", si.getIntent().getStringExtra("key"));
+        assertEquals(123, si.getWeight());
+        assertEquals(1, si.getExtras().getInt("k"));
+
+        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+        assertEquals("abc", si.getBitmapPath());
+        assertEquals(456, si.getIconResourceId());
+
+        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
+
+        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals("id", si.getId());
+        assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
+        assertEquals(null, si.getIcon());
+        assertEquals("title", si.getTitle());
+        assertEquals("text", si.getText());
+        assertEquals("action", si.getIntent().getAction());
+        assertEquals("val", si.getIntent().getStringExtra("key"));
+        assertEquals(123, si.getWeight());
+        assertEquals(1, si.getExtras().getInt("k"));
+
+        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+        assertEquals(null, si.getBitmapPath());
+        assertEquals(0, si.getIconResourceId());
+
+        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
+
+        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals("id", si.getId());
+        assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
+        assertEquals(null, si.getIcon());
+        assertEquals("title", si.getTitle());
+        assertEquals("text", si.getText());
+        assertEquals(null, si.getIntent());
+        assertEquals(123, si.getWeight());
+        assertEquals(1, si.getExtras().getInt("k"));
+
+        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+        assertEquals(null, si.getBitmapPath());
+        assertEquals(0, si.getIconResourceId());
+
+        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
+
+        assertEquals(getTestContext().getPackageName(), si.getPackageName());
+        assertEquals("id", si.getId());
+        assertEquals(null, si.getActivityComponent());
+        assertEquals(null, si.getIcon());
+        assertEquals(null, si.getTitle());
+        assertEquals(null, si.getText());
+        assertEquals(null, si.getIntent());
+        assertEquals(0, si.getWeight());
+        assertEquals(null, si.getExtras());
+
+        assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
+        assertEquals(null, si.getBitmapPath());
+        assertEquals(0, si.getIconResourceId());
+    }
+
+    public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
+        PersistableBundle pb = new PersistableBundle();
+        pb.putInt("k", 1);
+        ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
+                .setId("id")
+                .setActivityComponent(new ComponentName("a", "b"))
+                .setIcon(Icon.createWithContentUri("content://a.b.c/"))
+                .setTitle("title")
+                .setText("text")
+                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+                .setWeight(123)
+                .setExtras(pb)
+                .build();
+        sorig.addFlags(ShortcutInfo.FLAG_PINNED);
+        sorig.setBitmapPath("abc");
+        sorig.setIconResourceId(456);
+
+        ShortcutInfo si;
+
+        si = sorig.clone(/* flags=*/ 0);
+        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+                .setActivityComponent(new ComponentName("x", "y")).build());
+        assertEquals(new ComponentName("x", "y"), si.getActivityComponent());
+
+        si = sorig.clone(/* flags=*/ 0);
+        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+                .setIcon(Icon.createWithContentUri("content://x.y.z/")).build());
+        assertEquals("content://x.y.z/", si.getIcon().getUriString());
+
+        si = sorig.clone(/* flags=*/ 0);
+        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+                .setTitle("xyz").build());
+        assertEquals("xyz", si.getTitle());
+
+        si = sorig.clone(/* flags=*/ 0);
+        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+                .setText("xxx").build());
+        assertEquals("xxx", si.getText());
+
+        si = sorig.clone(/* flags=*/ 0);
+        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+                .setIntent(makeIntent("action2", ShortcutActivity.class)).build());
+        assertEquals("action2", si.getIntent().getAction());
+        assertEquals(null, si.getIntent().getStringExtra("key"));
+
+        si = sorig.clone(/* flags=*/ 0);
+        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+                .setIntent(makeIntent("action3", ShortcutActivity.class, "key", "x")).build());
+        assertEquals("action3", si.getIntent().getAction());
+        assertEquals("x", si.getIntent().getStringExtra("key"));
+
+        si = sorig.clone(/* flags=*/ 0);
+        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+                .setWeight(999).build());
+        assertEquals(999, si.getWeight());
+
+
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("x", 99);
+
+        si = sorig.clone(/* flags=*/ 0);
+        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+                .setExtras(pb2).build());
+        assertEquals(99, si.getExtras().getInt("x"));
+
+        final long timestamp = si.getLastChangedTimestamp();
+        Thread.sleep(2);
+
+        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+                .setTitle("xyz").build());
+
+        assertTrue(si.getLastChangedTimestamp() > timestamp);
+    }
+
+    public void testShortcutInfoSaveAndLoad() throws InterruptedException {
+        setCaller(CALLING_PACKAGE_1, USER_0);
+
+        final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                getTestContext().getResources(), R.drawable.black_32x32));
+
+        PersistableBundle pb = new PersistableBundle();
+        pb.putInt("k", 1);
+        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
+                .setId("id")
+                .setActivityComponent(new ComponentName(mClientContext, ShortcutActivity2.class))
+                .setIcon(bmp32x32)
+                .setTitle("title")
+                .setText("text")
+                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+                .setWeight(123)
+                .setExtras(pb)
+                .build();
+
+        mManager.addDynamicShortcut(sorig);
+
+        Thread.sleep(2);
+        final long now = System.currentTimeMillis();
+
+        // Save and load.
+        mService.saveDirtyInfo();
+        initService();
+        mService.handleUnlockUser(USER_0);
+
+        ShortcutInfo si;
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
+
+        assertEquals(CALLING_PACKAGE_1, si.getPackageName());
+        assertEquals("id", si.getId());
+        assertEquals(ShortcutActivity2.class.getName(), si.getActivityComponent().getClassName());
+        assertEquals(null, si.getIcon());
+        assertEquals("title", si.getTitle());
+        assertEquals("text", si.getText());
+        assertEquals("action", si.getIntent().getAction());
+        assertEquals("val", si.getIntent().getStringExtra("key"));
+        assertEquals(123, si.getWeight());
+        assertEquals(1, si.getExtras().getInt("k"));
+
+        assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE, si.getFlags());
+        assertNotNull(si.getBitmapPath()); // Something should be set.
+        assertEquals(0, si.getIconResourceId());
+        assertTrue(si.getLastChangedTimestamp() < now);
+    }
+
+    public void testShortcutInfoSaveAndLoad_forBackup() {
+        setCaller(CALLING_PACKAGE_1, USER_0);
+
+        final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                getTestContext().getResources(), R.drawable.black_32x32));
+
+        PersistableBundle pb = new PersistableBundle();
+        pb.putInt("k", 1);
+        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
+                .setId("id")
+                .setActivityComponent(new ComponentName(mClientContext, ShortcutActivity2.class))
+                .setIcon(bmp32x32)
+                .setTitle("title")
+                .setText("text")
+                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+                .setWeight(123)
+                .setExtras(pb)
+                .build();
+
+        mManager.addDynamicShortcut(sorig);
+
+        // Dynamic shortcuts won't be backed up, so we need to pin it.
+        setCaller(LAUNCHER_1, USER_0);
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id"), HANDLE_USER_0);
+
+        // Do backup & restore.
+        backupAndRestore();
+
+        ShortcutInfo si;
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
+
+        assertEquals(CALLING_PACKAGE_1, si.getPackageName());
+        assertEquals("id", si.getId());
+        assertEquals(ShortcutActivity2.class.getName(), si.getActivityComponent().getClassName());
+        assertEquals(null, si.getIcon());
+        assertEquals("title", si.getTitle());
+        assertEquals("text", si.getText());
+        assertEquals("action", si.getIntent().getAction());
+        assertEquals("val", si.getIntent().getStringExtra("key"));
+        assertEquals(123, si.getWeight());
+        assertEquals(1, si.getExtras().getInt("k"));
+
+        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+        assertNull(si.getBitmapPath()); // No icon.
+        assertEquals(0, si.getIconResourceId());
+    }
+
+    public void testDumpsys_crossProfile() {
+        prepareCrossProfileDataSet();
+        dumpsysOnLogcat("test1", /* force= */ true);
+    }
+
+    public void testDumpsys_withIcons() {
+        testIcons();
+        // Dump after having some icons.
+        dumpsysOnLogcat("test1", /* force= */ true);
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index beec40f..0aeb96f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -144,6 +144,7 @@
     private long mLastAppIdleParoledTime;
 
     private volatile boolean mPendingOneTimeCheckIdleStates;
+    private boolean mSystemServicesReady = false;
 
     @GuardedBy("mLock")
     private AppIdleHistory mAppIdleHistory;
@@ -232,6 +233,8 @@
             if (mPendingOneTimeCheckIdleStates) {
                 postOneTimeCheckIdleStates();
             }
+
+            mSystemServicesReady = true;
         } else if (phase == PHASE_BOOT_COMPLETED) {
             setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
         }
@@ -810,28 +813,30 @@
             // retain this for safety).
             return false;
         }
-        try {
-            // We allow all whitelisted apps, including those that don't want to be whitelisted
-            // for idle mode, because app idle (aka app standby) is really not as big an issue
-            // for controlling who participates vs. doze mode.
-            if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) {
+        if (mSystemServicesReady) {
+            try {
+                // We allow all whitelisted apps, including those that don't want to be whitelisted
+                // for idle mode, because app idle (aka app standby) is really not as big an issue
+                // for controlling who participates vs. doze mode.
+                if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) {
+                    return false;
+                }
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+
+            if (isActiveDeviceAdmin(packageName, userId)) {
                 return false;
             }
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
 
-        if (isActiveDeviceAdmin(packageName, userId)) {
-            return false;
-        }
+            if (isActiveNetworkScorer(packageName)) {
+                return false;
+            }
 
-        if (isActiveNetworkScorer(packageName)) {
-            return false;
-        }
-
-        if (mAppWidgetManager != null
-                && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
-            return false;
+            if (mAppWidgetManager != null
+                    && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
+                return false;
+            }
         }
 
         if (!isAppIdleUnfiltered(packageName, userId, elapsedRealtime)) {
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index 38ede87..46ce7a0 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -127,6 +127,14 @@
         public void setReceiver(MidiReceiver receiver) {
             mReceiver = receiver;
         }
+
+        @Override
+        public void onFlush() throws IOException {
+            MidiReceiver receiver = mReceiver;
+            if (receiver != null) {
+                receiver.flush();
+            }
+        }
     }
 
     public static UsbMidiDevice create(Context context, Bundle properties, int card, int device) {
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index b56ce73..dbc2b0c 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -170,6 +170,15 @@
     public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 0x100;
 
     /**
+     * Flag indicating that for this {@link PhoneAccount}, emergency video calling is allowed.
+     * <p>
+     * When set, Telecom will allow emergency video calls to be placed.  When not set, Telecom will
+     * convert all outgoing video calls to emergency numbers to audio-only.
+     * @hide
+     */
+    public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 0x200;
+
+    /**
      * URI scheme for telephone number URIs.
      */
     public static final String SCHEME_TEL = "tel";
@@ -731,6 +740,9 @@
         if (hasCapabilities(CAPABILITY_PLACE_EMERGENCY_CALLS)) {
             sb.append("PlaceEmerg ");
         }
+        if (hasCapabilities(CAPABILITY_EMERGENCY_VIDEO_CALLING)) {
+            sb.append("EmergVideo ");
+        }
         if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) {
             sb.append("SimSub ");
         }
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 4fa8fe9..6eafb90 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1433,25 +1433,6 @@
     }
 
     /**
-     * Launches the {@link android.app.Activity} to manage blocked numbers.
-     * <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) {
-            try {
-                service.launchManageBlockedNumbersActivity(mContext.getPackageName());
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling ITelecomService#manageBlockedNumbers", e);
-            }
-        }
-    }
-
-    /**
      * 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
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 3c250f1..871565d 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -246,12 +246,6 @@
     boolean setDefaultDialer(in String packageName);
 
     /**
-    * @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 c69a360..461611d 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -252,6 +252,16 @@
     public static final String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
 
     /**
+     * Flag specifying whether WFC over IMS supports the "wifi only" option.  If false, the wifi
+     * calling settings will not include an option for "wifi only".  If true, the wifi calling
+     * settings will include an option for "wifi only"
+     * <p>
+     * By default, it is assumed that WFC supports "wifi only".
+     */
+    public static final String KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL =
+            "carrier_wfc_supports_wifi_only_bool";
+
+    /**
      * Default WFC_IMS_mode 0: WIFI_ONLY
      *                      1: CELLULAR_PREFERRED
      *                      2: WIFI_PREFERRED
@@ -628,6 +638,7 @@
         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_WFC_SUPPORTS_WIFI_ONLY_BOOL, true);
         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);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b482811..865af78 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3550,7 +3550,7 @@
      * @return the response of ISIM Authetification, or null if not available
      * @hide
      * @deprecated
-     * @see getIccSimChallengeResponse with appType=PhoneConstants.APPTYPE_ISIM
+     * @see getIccAuthentication with appType=PhoneConstants.APPTYPE_ISIM
      */
     public String getIsimChallengeResponse(String nonce){
         try {
@@ -3566,21 +3566,60 @@
         }
     }
 
+    // ICC SIM Application Types
+    public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
+    public static final int APPTYPE_USIM = PhoneConstants.APPTYPE_USIM;
+    public static final int APPTYPE_RUIM = PhoneConstants.APPTYPE_RUIM;
+    public static final int APPTYPE_CSIM = PhoneConstants.APPTYPE_CSIM;
+    public static final int APPTYPE_ISIM = PhoneConstants.APPTYPE_ISIM;
+    // authContext (parameter P2) when doing SIM challenge,
+    // per 3GPP TS 31.102 (Section 7.1.2)
+    public static final int AUTHTYPE_EAP_SIM = PhoneConstants.AUTH_CONTEXT_EAP_SIM;
+    public static final int AUTHTYPE_EAP_AKA = PhoneConstants.AUTH_CONTEXT_EAP_AKA;
+
     /**
-     * Returns the response of SIM Authentication through RIL.
-     * Returns null if the Authentication hasn't been successful
-     * @param subId subscription ID to be queried
-     * @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
-     * @param data authentication challenge data
-     * @return the response of SIM Authentication, or null if not available
-     * @hide
+     * Returns the response of authentication for the default subscription.
+     * Returns null if the authentication hasn't been successful
+     *
+     * <p>Requires that the calling app has carrier privileges or READ_PRIVILEGED_PHONE_STATE
+     * permission.
+     *
+     * @param appType the icc application type, like {@link #APPTYPE_USIM}
+     * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
+     * {@link #AUTHTYPE_EAP_SIM}
+     * @param data authentication challenge data, base64 encoded.
+     * See 3GPP TS 31.102 7.1.2 for more details.
+     * @return the response of authentication, or null if not available
+     *
+     * @see #hasCarrierPrivileges
      */
-    public String getIccSimChallengeResponse(int subId, int appType, String data) {
+    public String getIccAuthentication(int appType, int authType, String data) {
+        return getIccAuthentication(getDefaultSubscription(), appType, authType, data);
+    }
+
+    /**
+     * Returns the response of USIM Authentication for specified subId.
+     * Returns null if the authentication hasn't been successful
+     *
+     * <p>Requires that the calling app has carrier privileges.
+     *
+     * @param subId subscription ID used for authentication
+     * @param appType the icc application type, like {@link #APPTYPE_USIM}
+     * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
+     * {@link #AUTHTYPE_EAP_SIM}
+     * @param data authentication challenge data, base64 encoded.
+     * See 3GPP TS 31.102 7.1.2 for more details.
+     * @return the response of authentication, or null if not available
+     *
+     * @see #hasCarrierPrivileges
+     */
+
+    public String getIccAuthentication(int subId, int appType, int authType, String data) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getIccSimChallengeResponse(subId, appType, data);
+            return info.getIccSimChallengeResponse(subId, appType, authType, data);
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -3599,9 +3638,10 @@
      * @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
      * @param data authentication challenge data
      * @return the response of SIM Authentication, or null if not available
+     * @hide
      */
     public String getIccSimChallengeResponse(int appType, String data) {
-        return getIccSimChallengeResponse(getDefaultSubscription(), appType, data);
+        return getIccAuthentication(getDefaultSubscription(), appType, AUTHTYPE_EAP_SIM, data);
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index dc2b297..02baa34 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -196,8 +196,9 @@
      *
      * @param subId subscription ID to be queried
      * @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
+     * @param authType Authentication type, see PhoneConstants#AUTHTYPE_xxx
      * @param data authentication challenge data
      * @return challenge response
      */
-    String getIccSimChallengeResponse(int subId, int appType, String data);
+    String getIccSimChallengeResponse(int subId, int appType, int authType, String data);
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index ecd89ed..1680fe3 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -202,4 +202,10 @@
     public static final int AUDIO_OUTPUT_ENABLE_SPEAKER = 0;
     public static final int AUDIO_OUTPUT_DISABLE_SPEAKER = 1;
     public static final int AUDIO_OUTPUT_DEFAULT = AUDIO_OUTPUT_ENABLE_SPEAKER;
+
+    // authContext (parameter P2) when doing SIM challenge,
+    // per 3GPP TS 31.102 (Section 7.1.2)
+    public static final int AUTH_CONTEXT_EAP_SIM = 128;
+    public static final int AUTH_CONTEXT_EAP_AKA = 129;
+    public static final int AUTH_CONTEXT_UNDEFINED = -1;
 }
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index ed7351f8..033312b 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -62,7 +62,7 @@
     private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
     private static final String WEARABLE_ACTION_GOOGLE =
             "com.google.android.wearable.action.GOOGLE";
-    private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 7500; //7.5s to allow app to idle
+    private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 60000; //60s to allow app to idle
     private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches
     private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 2000; //2s between launching apps
 
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
index ad02d2b..c0583ce 100644
--- a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
@@ -40,6 +41,7 @@
 import java.net.InetAddress;
 import java.net.Socket;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Random;
 import java.util.UUID;
 
@@ -53,7 +55,7 @@
     static final int MSG_GENERIC_TRIGGER = 4;
 
     private Random random = new Random();
-    private ArrayList<UUID> loadedModelUuids;
+    private HashSet<UUID> loadedModelUuids;
     private ISoundTriggerService soundTriggerService;
     private SoundTriggerManager soundTriggerManager;
 
@@ -68,7 +70,7 @@
         soundTriggerManager = (SoundTriggerManager) context.getSystemService(
                 Context.SOUND_TRIGGER_SERVICE);
 
-        loadedModelUuids = new ArrayList<UUID>();
+        loadedModelUuids = new HashSet<UUID>();
     }
 
     @Override
@@ -170,6 +172,101 @@
         verify(spyCallback, timeout(100)).onGenericSoundTriggerDetected(any());
     }
 
+    /**
+     * Tests a more complicated pattern of loading, unloading, triggering, starting and stopping
+     * recognition. Intended to find unexpected errors that occur in unexpected states.
+     */
+    @LargeTest
+    public void testFuzzGenericSoundModel() throws Exception {
+        int numModels = 2;
+
+        final int STATUS_UNLOADED = 0;
+        final int STATUS_LOADED = 1;
+        final int STATUS_STARTED = 2;
+
+        class ModelInfo {
+            int status;
+            GenericSoundModel model;
+
+            public ModelInfo(GenericSoundModel model, int status) {
+                this.status = status;
+                this.model = model;
+            }
+        }
+
+        Random predictableRandom = new Random(100);
+
+        ArrayList modelInfos = new ArrayList<ModelInfo>();
+        for(int i=0; i<numModels; i++) {
+            // Create sound model
+            byte[] data = new byte[1024];
+            predictableRandom.nextBytes(data);
+            UUID modelUuid = UUID.randomUUID();
+            UUID mVendorUuid = UUID.randomUUID();
+            GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+            ModelInfo modelInfo = new ModelInfo(model, STATUS_UNLOADED);
+            modelInfos.add(modelInfo);
+        }
+
+        boolean captureTriggerAudio = true;
+        boolean allowMultipleTriggers = true;
+        RecognitionConfig config = new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
+                null, null);
+        TestRecognitionStatusCallback spyCallback = spy(new TestRecognitionStatusCallback());
+
+
+        int numOperationsToRun = 100;
+        for(int i=0; i<numOperationsToRun; i++) {
+            // Select a random model
+            int modelInfoIndex = predictableRandom.nextInt(modelInfos.size());
+            ModelInfo modelInfo = (ModelInfo) modelInfos.get(modelInfoIndex);
+
+            // Perform a random operation
+            int operation = predictableRandom.nextInt(5);
+
+            if (operation == 0 && modelInfo.status == STATUS_UNLOADED) {
+                // Update and start sound model
+                soundTriggerService.updateSoundModel(modelInfo.model);
+                loadedModelUuids.add(modelInfo.model.uuid);
+                modelInfo.status = STATUS_LOADED;
+            } else if (operation == 1 && modelInfo.status == STATUS_LOADED) {
+                // Start the sound model
+                int r = soundTriggerService.startRecognition(new ParcelUuid(modelInfo.model.uuid),
+                        spyCallback, config);
+                assertEquals("Could Not Start Recognition with code: " + r,
+                        android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
+                modelInfo.status = STATUS_STARTED;
+            } else if (operation == 2 && modelInfo.status == STATUS_STARTED) {
+                // Send trigger to stub HAL
+                Socket socket = new Socket(InetAddress.getLocalHost(), 14035);
+                DataOutputStream out = new DataOutputStream(socket.getOutputStream());
+                out.writeBytes("trig " + modelInfo.model.uuid + "\r\n");
+                out.flush();
+                socket.close();
+
+                // Verify trigger was received
+                verify(spyCallback, timeout(100)).onGenericSoundTriggerDetected(any());
+                reset(spyCallback);
+            } else if (operation == 3 && modelInfo.status == STATUS_STARTED) {
+                // Stop recognition
+                int r = soundTriggerService.stopRecognition(new ParcelUuid(modelInfo.model.uuid),
+                        spyCallback);
+                assertEquals("Could Not Stop Recognition with code: " + r,
+                        android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
+                modelInfo.status = STATUS_LOADED;
+            } else if (operation == 4 && modelInfo.status != STATUS_UNLOADED) {
+                // Delete sound model
+                soundTriggerService.deleteSoundModel(new ParcelUuid(modelInfo.model.uuid));
+                loadedModelUuids.remove(modelInfo.model.uuid);
+
+                // Confirm it was deleted
+                GenericSoundModel returnedModel =
+                        soundTriggerService.getSoundModel(new ParcelUuid(modelInfo.model.uuid));
+                assertEquals(null, returnedModel);
+                modelInfo.status = STATUS_UNLOADED;
+            }
+        }
+    }
 
     public class TestRecognitionStatusCallback extends IRecognitionStatusCallback.Stub {
         @Override
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 0bb88a7..db40416 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -492,6 +492,21 @@
     SortedVector<String8> reasons;
 };
 
+struct Feature {
+    Feature() : required(false), version(-1) {}
+    Feature(bool required, int32_t version = -1) : required(required), version(version) {}
+
+    /**
+     * Whether the feature is required.
+     */
+    bool required;
+
+    /**
+     * What version of the feature is requested.
+     */
+    int32_t version;
+};
+
 /**
  * Represents a <feature-group> tag in the AndroidManifest.xml
  */
@@ -506,7 +521,7 @@
     /**
      * Explicit features defined in the group
      */
-    KeyedVector<String8, bool> features;
+    KeyedVector<String8, Feature> features;
 
     /**
      * OpenGL ES version required
@@ -541,11 +556,18 @@
 
     const size_t numFeatures = grp.features.size();
     for (size_t i = 0; i < numFeatures; i++) {
-        const bool required = grp.features[i];
+        const Feature& feature = grp.features[i];
+        const bool required = feature.required;
+        const int32_t version = feature.version;
 
         const String8& featureName = grp.features.keyAt(i);
-        printf("  uses-feature%s: name='%s'\n", (required ? "" : "-not-required"),
+        printf("  uses-feature%s: name='%s'", (required ? "" : "-not-required"),
                 ResTable::normalizeForOutput(featureName.string()).string());
+
+        if (version > 0) {
+            printf(" version='%d'", version);
+        }
+        printf("\n");
     }
 
     const size_t numImpliedFeatures =
@@ -590,15 +612,15 @@
 static void addParentFeatures(FeatureGroup* grp, const String8& name) {
     if (name == "android.hardware.camera.autofocus" ||
             name == "android.hardware.camera.flash") {
-        grp->features.add(String8("android.hardware.camera"), true);
+        grp->features.add(String8("android.hardware.camera"), Feature(true));
     } else if (name == "android.hardware.location.gps" ||
             name == "android.hardware.location.network") {
-        grp->features.add(String8("android.hardware.location"), true);
+        grp->features.add(String8("android.hardware.location"), Feature(true));
     } else if (name == "android.hardware.touchscreen.multitouch") {
-        grp->features.add(String8("android.hardware.touchscreen"), true);
+        grp->features.add(String8("android.hardware.touchscreen"), Feature(true));
     } else if (name == "android.hardware.touchscreen.multitouch.distinct") {
-        grp->features.add(String8("android.hardware.touchscreen.multitouch"), true);
-        grp->features.add(String8("android.hardware.touchscreen"), true);
+        grp->features.add(String8("android.hardware.touchscreen.multitouch"), Feature(true));
+        grp->features.add(String8("android.hardware.touchscreen"), Feature(true));
     } else if (name == "android.hardware.opengles.aep") {
         const int openGLESVersion31 = 0x00030001;
         if (openGLESVersion31 > grp->openGLESVersion) {
@@ -727,6 +749,9 @@
         return 1;
     }
 
+    // Source for AndroidManifest.xml
+    const String8 manifestFile = String8::format("%s@AndroidManifest.xml", filename);
+
     // The dynamicRefTable can be null if there are no resources for this asset cookie.
     // This fine.
     const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);
@@ -1424,10 +1449,28 @@
                     } else if (tag == "uses-feature") {
                         String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
                         if (name != "" && error == "") {
-                            int req = AaptXml::getIntegerAttribute(tree,
-                                    REQUIRED_ATTR, 1);
+                            const char* androidSchema =
+                                    "http://schemas.android.com/apk/res/android";
 
-                            commonFeatures.features.add(name, req);
+                            int32_t req = AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1,
+                                                                       &error);
+                            if (error != "") {
+                                SourcePos(manifestFile, tree.getLineNumber()).error(
+                                        "failed to read attribute 'android:required': %s",
+                                        error.string());
+                                goto bail;
+                            }
+
+                            int32_t version = AaptXml::getIntegerAttribute(tree, androidSchema,
+                                                                           "version", 0, &error);
+                            if (error != "") {
+                                SourcePos(manifestFile, tree.getLineNumber()).error(
+                                        "failed to read attribute 'android:version': %s",
+                                        error.string());
+                                goto bail;
+                            }
+
+                            commonFeatures.features.add(name, Feature(req != 0, version));
                             if (req) {
                                 addParentFeatures(&commonFeatures, name);
                             }
@@ -1751,12 +1794,27 @@
                             }
                         }
                     } else if (withinFeatureGroup && tag == "uses-feature") {
+                        const String8 androidSchema("http://schemas.android.com/apk/res/android");
                         FeatureGroup& top = featureGroups.editTop();
 
                         String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error);
                         if (name != "" && error == "") {
-                            top.features.add(name, true);
+                            Feature feature(true);
+
+                            int32_t featureVers = AaptXml::getIntegerAttribute(
+                                    tree, androidSchema.string(), "version", 0, &error);
+                            if (error == "") {
+                                feature.version = featureVers;
+                            } else {
+                                SourcePos(manifestFile, tree.getLineNumber()).error(
+                                        "failed to read attribute 'android:version': %s",
+                                        error.string());
+                                goto bail;
+                            }
+
+                            top.features.add(name, feature);
                             addParentFeatures(&top, name);
+
                         } else {
                             int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR,
                                     &error);
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index 641c34b..d631f35 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -33,7 +33,7 @@
     ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
     ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
     ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
-    ".amr", ".awb", ".wma", ".wmv", ".webm"
+    ".amr", ".awb", ".wma", ".wmv", ".webm", ".mkv"
 };
 
 /* fwd decls, so I can write this downward */
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 85d22ff..3a1e2bb 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -54,6 +54,7 @@
 	Debug.cpp \
 	Flags.cpp \
 	java/AnnotationProcessor.cpp \
+	java/ClassDefinition.cpp \
 	java/JavaClassGenerator.cpp \
 	java/ManifestClassGenerator.cpp \
 	java/ProguardRules.cpp \
@@ -65,6 +66,7 @@
 	ResourceValues.cpp \
 	SdkConstants.cpp \
 	StringPool.cpp \
+	xml/XmlActionExecutor.cpp \
 	xml/XmlDom.cpp \
 	xml/XmlPullParser.cpp \
 	xml/XmlUtil.cpp
@@ -106,6 +108,7 @@
 	SdkConstants_test.cpp \
 	StringPool_test.cpp \
 	ValueVisitor_test.cpp \
+	xml/XmlActionExecutor_test.cpp \
 	xml/XmlDom_test.cpp \
 	xml/XmlPullParser_test.cpp \
 	xml/XmlUtil_test.cpp
@@ -128,33 +131,40 @@
 	libbase \
 	libprotobuf-cpp-lite_static
 
-# Do not add any shared libraries. AAPT2 is built to run on many
-# environments that may not have the required dependencies.
-hostSharedLibs :=
 
-ifneq ($(strip $(USE_MINGW)),)
-	hostStaticLibs += libz
-else
-	hostLdLibs += -lz
-endif
+# Statically link libz for MinGW (Win SDK under Linux),
+# and dynamically link for all others.
+hostStaticLibs_windows := libz
+hostLdLibs_linux := -lz
+hostLdLibs_darwin := -lz
 
 cFlags := -Wall -Werror -Wno-unused-parameter -UNDEBUG
+cFlags_darwin := -D_DARWIN_UNLIMITED_STREAMS
+cFlags_windows := -Wno-maybe-uninitialized # Incorrectly marking use of Maybe.value() as error.
 cppFlags := -std=c++11 -Wno-missing-field-initializers -fno-exceptions -fno-rtti
 protoIncludes := $(call generated-sources-dir-for,STATIC_LIBRARIES,libaapt2,HOST)
 
 # ==========================================================
+# NOTE: Do not add any shared libraries.
+# AAPT2 is built to run on many environments
+# that may not have the required dependencies.
+# ==========================================================
+
+# ==========================================================
 # Build the host static library: libaapt2
 # ==========================================================
 include $(CLEAR_VARS)
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
 LOCAL_MODULE := libaapt2
-
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_CFLAGS := $(cFlags)
+LOCAL_CFLAGS_darwin := $(cFlags_darwin)
+LOCAL_CFLAGS_windows := $(cFlags_windows)
+LOCAL_CPPFLAGS := $(cppFlags)
+LOCAL_C_INCLUDES := $(protoIncludes)
 LOCAL_SRC_FILES := $(sources)
-LOCAL_STATIC_LIBRARIES += $(hostStaticLibs)
-LOCAL_CFLAGS += $(cFlags)
-LOCAL_CPPFLAGS += $(cppFlags)
-LOCAL_C_INCLUDES += $(protoIncludes)
-
+LOCAL_STATIC_LIBRARIES := $(hostStaticLibs)
+LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 # ==========================================================
@@ -163,16 +173,18 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libaapt2_tests
 LOCAL_MODULE_TAGS := tests
-
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_CFLAGS := $(cFlags)
+LOCAL_CFLAGS_darwin := $(cFlags_darwin)
+LOCAL_CFLAGS_windows := $(cFlags_windows)
+LOCAL_CPPFLAGS := $(cppFlags)
+LOCAL_C_INCLUDES := $(protoIncludes)
 LOCAL_SRC_FILES := $(testSources)
-
-LOCAL_STATIC_LIBRARIES += libaapt2 $(hostStaticLibs)
-LOCAL_SHARED_LIBRARIES += $(hostSharedLibs)
-LOCAL_LDLIBS += $(hostLdLibs)
-LOCAL_CFLAGS += $(cFlags)
-LOCAL_CPPFLAGS += $(cppFlags)
-LOCAL_C_INCLUDES += $(protoIncludes)
-
+LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs)
+LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
+LOCAL_LDLIBS := $(hostLdLibs)
+LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin)
+LOCAL_LDLIBS_linux := $(hostLdLibs_linux)
 include $(BUILD_HOST_NATIVE_TEST)
 
 # ==========================================================
@@ -180,16 +192,18 @@
 # ==========================================================
 include $(CLEAR_VARS)
 LOCAL_MODULE := aapt2
-
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_CFLAGS := $(cFlags)
+LOCAL_CFLAGS_darwin := $(cFlags_darwin)
+LOCAL_CFLAGS_windows := $(cFlags_windows)
+LOCAL_CPPFLAGS := $(cppFlags)
+LOCAL_C_INCLUDES := $(protoIncludes)
 LOCAL_SRC_FILES := $(main) $(toolSources)
-
-LOCAL_STATIC_LIBRARIES += libaapt2 $(hostStaticLibs)
-LOCAL_SHARED_LIBRARIES += $(hostSharedLibs)
-LOCAL_LDLIBS += $(hostLdLibs)
-LOCAL_CFLAGS += $(cFlags)
-LOCAL_CPPFLAGS += $(cppFlags)
-LOCAL_C_INCLUDES += $(protoIncludes)
-
+LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs)
+LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
+LOCAL_LDLIBS := $(hostLdLibs)
+LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin)
+LOCAL_LDLIBS_linux := $(hostLdLibs_linux)
 include $(BUILD_HOST_EXECUTABLE)
 
 ifeq ($(ONE_SHOT_MAKEFILE),)
diff --git a/tools/aapt2/Diagnostics.h b/tools/aapt2/Diagnostics.h
index ab4d284..e86f2a8 100644
--- a/tools/aapt2/Diagnostics.h
+++ b/tools/aapt2/Diagnostics.h
@@ -21,6 +21,7 @@
 #include "util/StringPiece.h"
 #include "util/Util.h"
 
+#include <android-base/macros.h>
 #include <iostream>
 #include <sstream>
 #include <string>
@@ -46,7 +47,11 @@
     DiagMessage(const Source& src) : mSource(src) {
     }
 
-    template <typename T> DiagMessage& operator<<(const T& value) {
+    DiagMessage(size_t line) : mSource(Source().withLine(line)) {
+    }
+
+    template <typename T>
+    DiagMessage& operator<<(const T& value) {
         mMessage << value;
         return *this;
     }
@@ -59,36 +64,82 @@
 struct IDiagnostics {
     virtual ~IDiagnostics() = default;
 
-    virtual void error(const DiagMessage& message) = 0;
-    virtual void warn(const DiagMessage& message) = 0;
-    virtual void note(const DiagMessage& message) = 0;
+    enum class Level {
+        Note,
+        Warn,
+        Error
+    };
+
+    virtual void log(Level level, DiagMessageActual& actualMsg) = 0;
+
+    virtual void error(const DiagMessage& message) {
+        DiagMessageActual actual = message.build();
+        log(Level::Error, actual);
+    }
+
+    virtual void warn(const DiagMessage& message) {
+        DiagMessageActual actual = message.build();
+        log(Level::Warn, actual);
+    }
+
+    virtual void note(const DiagMessage& message) {
+        DiagMessageActual actual = message.build();
+        log(Level::Note, actual);
+    }
 };
 
-struct StdErrDiagnostics : public IDiagnostics {
+class StdErrDiagnostics : public IDiagnostics {
+public:
+    StdErrDiagnostics() = default;
+
+    void log(Level level, DiagMessageActual& actualMsg) override {
+        const char* tag;
+
+        switch (level) {
+        case Level::Error:
+            mNumErrors++;
+            if (mNumErrors > 20) {
+                return;
+            }
+            tag = "error";
+            break;
+
+        case Level::Warn:
+            tag = "warn";
+            break;
+
+        case Level::Note:
+            tag = "note";
+            break;
+        }
+
+        if (!actualMsg.source.path.empty()) {
+            std::cerr << actualMsg.source << ": ";
+        }
+        std::cerr << tag << ": " << actualMsg.message << "." << std::endl;
+    }
+
+private:
     size_t mNumErrors = 0;
 
-    void emit(const DiagMessage& msg, const char* tag) {
-        DiagMessageActual actual = msg.build();
-        if (!actual.source.path.empty()) {
-            std::cerr << actual.source << ": ";
-        }
-        std::cerr << tag << actual.message << "." << std::endl;
+    DISALLOW_COPY_AND_ASSIGN(StdErrDiagnostics);
+};
+
+class SourcePathDiagnostics : public IDiagnostics {
+public:
+    SourcePathDiagnostics(const Source& src, IDiagnostics* diag) : mSource(src), mDiag(diag) {
     }
 
-    void error(const DiagMessage& msg) override {
-        if (mNumErrors < 20) {
-            emit(msg, "error: ");
-        }
-        mNumErrors++;
+    void log(Level level, DiagMessageActual& actualMsg) override {
+        actualMsg.source.path = mSource.path;
+        mDiag->log(level, actualMsg);
     }
 
-    void warn(const DiagMessage& msg) override {
-        emit(msg, "warn: ");
-    }
+private:
+    Source mSource;
+    IDiagnostics* mDiag;
 
-    void note(const DiagMessage& msg) override {
-        emit(msg, "note: ");
-    }
+    DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics);
 };
 
 } // namespace aapt
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index 180bd11..d6c52ab 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -28,33 +28,23 @@
 
 namespace aapt {
 
-struct ResourceTableTest : public ::testing::Test {
-    struct EmptyDiagnostics : public IDiagnostics {
-        void error(const DiagMessage& msg) override {}
-        void warn(const DiagMessage& msg) override {}
-        void note(const DiagMessage& msg) override {}
-    };
-
-    EmptyDiagnostics mDiagnostics;
-};
-
-TEST_F(ResourceTableTest, FailToAddResourceWithBadName) {
+TEST(ResourceTableTest, FailToAddResourceWithBadName) {
     ResourceTable table;
 
     EXPECT_FALSE(table.addResource(
             ResourceNameRef(u"android", ResourceType::kId, u"hey,there"),
             ConfigDescription{}, "",
             test::ValueBuilder<Id>().setSource("test.xml", 21u).build(),
-            &mDiagnostics));
+            test::getDiagnostics()));
 
     EXPECT_FALSE(table.addResource(
             ResourceNameRef(u"android", ResourceType::kId, u"hey:there"),
             ConfigDescription{}, "",
             test::ValueBuilder<Id>().setSource("test.xml", 21u).build(),
-            &mDiagnostics));
+            test::getDiagnostics()));
 }
 
-TEST_F(ResourceTableTest, AddOneResource) {
+TEST(ResourceTableTest, AddOneResource) {
     ResourceTable table;
 
     EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/id"),
@@ -62,12 +52,12 @@
                                   "",
                                   test::ValueBuilder<Id>()
                                           .setSource("test/path/file.xml", 23u).build(),
-                                  &mDiagnostics));
+                                  test::getDiagnostics()));
 
     ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/id"));
 }
 
-TEST_F(ResourceTableTest, AddMultipleResources) {
+TEST(ResourceTableTest, AddMultipleResources) {
     ResourceTable table;
 
     ConfigDescription config;
@@ -79,21 +69,21 @@
             config,
             "",
             test::ValueBuilder<Id>().setSource("test/path/file.xml", 10u).build(),
-            &mDiagnostics));
+            test::getDiagnostics()));
 
     EXPECT_TRUE(table.addResource(
             test::parseNameOrDie(u"@android:attr/id"),
             config,
             "",
             test::ValueBuilder<Id>().setSource("test/path/file.xml", 12u).build(),
-            &mDiagnostics));
+            test::getDiagnostics()));
 
     EXPECT_TRUE(table.addResource(
             test::parseNameOrDie(u"@android:string/ok"),
             config,
             "",
             test::ValueBuilder<Id>().setSource("test/path/file.xml", 14u).build(),
-            &mDiagnostics));
+            test::getDiagnostics()));
 
     EXPECT_TRUE(table.addResource(
             test::parseNameOrDie(u"@android:string/ok"),
@@ -102,7 +92,7 @@
             test::ValueBuilder<BinaryPrimitive>(android::Res_value{})
                     .setSource("test/path/file.xml", 20u)
                     .build(),
-            &mDiagnostics));
+            test::getDiagnostics()));
 
     ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/layout_width"));
     ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/id"));
@@ -111,37 +101,37 @@
                                                                 languageConfig));
 }
 
-TEST_F(ResourceTableTest, OverrideWeakResourceValue) {
+TEST(ResourceTableTest, OverrideWeakResourceValue) {
     ResourceTable table;
 
     ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/foo"), ConfigDescription{},
-                                  "", util::make_unique<Attribute>(true), &mDiagnostics));
+                                  "", util::make_unique<Attribute>(true), test::getDiagnostics()));
 
     Attribute* attr = test::getValue<Attribute>(&table, u"@android:attr/foo");
     ASSERT_NE(nullptr, attr);
     EXPECT_TRUE(attr->isWeak());
 
     ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/foo"), ConfigDescription{},
-                                  "", util::make_unique<Attribute>(false), &mDiagnostics));
+                                  "", util::make_unique<Attribute>(false), test::getDiagnostics()));
 
     attr = test::getValue<Attribute>(&table, u"@android:attr/foo");
     ASSERT_NE(nullptr, attr);
     EXPECT_FALSE(attr->isWeak());
 }
 
-TEST_F(ResourceTableTest, ProductVaryingValues) {
+TEST(ResourceTableTest, ProductVaryingValues) {
     ResourceTable table;
 
     EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/foo"),
                                   test::parseConfigOrDie("land"),
                                   "tablet",
                                   util::make_unique<Id>(),
-                                  &mDiagnostics));
+                                  test::getDiagnostics()));
     EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/foo"),
                                   test::parseConfigOrDie("land"),
                                   "phone",
                                   util::make_unique<Id>(),
-                                  &mDiagnostics));
+                                  test::getDiagnostics()));
 
     EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/foo",
                                                              test::parseConfigOrDie("land"),
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index e93c2fba..2b2d348 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -20,8 +20,6 @@
 #include <gtest/gtest.h>
 #include <string>
 
-using namespace android;
-
 namespace aapt {
 
 TEST(StringPoolTest, InsertOneString) {
@@ -171,24 +169,28 @@
 }
 
 TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) {
+    using namespace android; // For NO_ERROR on Windows.
+
     StringPool pool;
     BigBuffer buffer(1024);
     StringPool::flattenUtf8(&buffer, pool);
 
     std::unique_ptr<uint8_t[]> data = util::copy(buffer);
-    android::ResStringPool test;
-    ASSERT_EQ(test.setTo(data.get(), buffer.size()), android::NO_ERROR);
+    ResStringPool test;
+    ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
 }
 
 TEST(StringPoolTest, FlattenOddCharactersUtf16) {
+    using namespace android; // For NO_ERROR on Windows.
+
     StringPool pool;
     pool.makeRef(u"\u093f");
     BigBuffer buffer(1024);
     StringPool::flattenUtf16(&buffer, pool);
 
     std::unique_ptr<uint8_t[]> data = util::copy(buffer);
-    android::ResStringPool test;
-    ASSERT_EQ(test.setTo(data.get(), buffer.size()), android::NO_ERROR);
+    ResStringPool test;
+    ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
     size_t len = 0;
     const char16_t* str = test.stringAt(0, &len);
     EXPECT_EQ(1u, len);
@@ -199,6 +201,8 @@
 constexpr const char16_t* sLongString = u"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限します。メール、SMSや、同期を使 用するその他のアプリは、起動しても更新されないことがあります。バッテリーセーバーは端末の充電中は自動的にOFFになります。";
 
 TEST(StringPoolTest, FlattenUtf8) {
+    using namespace android; // For NO_ERROR on Windows.
+
     StringPool pool;
 
     StringPool::Ref ref1 = pool.makeRef(u"hello");
@@ -219,8 +223,8 @@
 
     std::unique_ptr<uint8_t[]> data = util::copy(buffer);
     {
-        android::ResStringPool test;
-        ASSERT_EQ(test.setTo(data.get(), buffer.size()), android::NO_ERROR);
+        ResStringPool test;
+        ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
 
         EXPECT_EQ(util::getString(test, 0), u"hello");
         EXPECT_EQ(util::getString(test, 1), u"goodbye");
diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp
index be26b52..99c2077 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp
@@ -20,6 +20,8 @@
 #include "compile/PseudolocaleGenerator.h"
 #include "compile/Pseudolocalizer.h"
 
+#include <algorithm>
+
 namespace aapt {
 
 std::unique_ptr<StyledString> pseudolocalizeStyledString(StyledString* string,
diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp
index da81046..28a7928 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -24,6 +24,7 @@
 #include "util/BigBuffer.h"
 
 #include <android-base/macros.h>
+#include <algorithm>
 #include <type_traits>
 #include <numeric>
 
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index 3eac633..570cd96 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -21,6 +21,7 @@
 #include "xml/XmlDom.h"
 
 #include <androidfw/ResourceTypes.h>
+#include <algorithm>
 #include <utils/misc.h>
 #include <vector>
 
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index fef5ca3..4e6eb81 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -46,6 +46,8 @@
 
     ::testing::AssertionResult flatten(xml::XmlResource* doc, android::ResXMLTree* outTree,
                                        XmlFlattenerOptions options = {}) {
+        using namespace android; // For NO_ERROR on windows because it is a macro.
+
         BigBuffer buffer(1024);
         XmlFlattener flattener(&buffer, options);
         if (!flattener.consume(mContext.get(), doc)) {
@@ -53,7 +55,7 @@
         }
 
         std::unique_ptr<uint8_t[]> data = util::copy(buffer);
-        if (outTree->setTo(data.get(), buffer.size(), true) != android::NO_ERROR) {
+        if (outTree->setTo(data.get(), buffer.size(), true) != NO_ERROR) {
             return ::testing::AssertionFailure() << "flattened XML is corrupt";
         }
         return ::testing::AssertionSuccess();
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index 496e92e..ba74439 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -64,7 +64,7 @@
     mComment << "\n *";
 }
 
-void AnnotationProcessor::writeToStream(std::ostream* out, const StringPiece& prefix) {
+void AnnotationProcessor::writeToStream(std::ostream* out, const StringPiece& prefix) const {
     if (mHasComments) {
         std::string result = mComment.str();
         for (StringPiece line : util::tokenize<char>(result, '\n')) {
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
index fadf584..0fc5b08 100644
--- a/tools/aapt2/java/AnnotationProcessor.h
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -66,7 +66,7 @@
     /**
      * Writes the comments and annotations to the stream, with the given prefix before each line.
      */
-    void writeToStream(std::ostream* out, const StringPiece& prefix);
+    void writeToStream(std::ostream* out, const StringPiece& prefix) const;
 
 private:
     enum : uint32_t {
diff --git a/tools/aapt2/java/AnnotationProcessor_test.cpp b/tools/aapt2/java/AnnotationProcessor_test.cpp
index da96b84..d3860a5 100644
--- a/tools/aapt2/java/AnnotationProcessor_test.cpp
+++ b/tools/aapt2/java/AnnotationProcessor_test.cpp
@@ -49,16 +49,18 @@
 };
 
 TEST_F(AnnotationProcessorTest, EmitsDeprecated) {
-    ASSERT_TRUE(parse(R"EOF(
+    const char* xmlInput = R"EOF(
     <resources>
-      <declare-styleable name="foo">      
+      <declare-styleable name="foo">
         <!-- Some comment, and it should contain
              a marker word, something that marks
              this resource as nor needed.
              {@deprecated That's the marker! } -->
         <attr name="autoText" format="boolean" />
       </declare-styleable>
-    </resources>)EOF"));
+    </resources>)EOF";
+
+    ASSERT_TRUE(parse(xmlInput));
 
     Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/autoText");
     ASSERT_NE(nullptr, attr);
diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp
new file mode 100644
index 0000000..08f2c8b
--- /dev/null
+++ b/tools/aapt2/java/ClassDefinition.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "java/ClassDefinition.h"
+#include "util/StringPiece.h"
+
+#include <ostream>
+
+namespace aapt {
+
+bool ClassDefinition::empty() const {
+    for (const std::unique_ptr<ClassMember>& member : mMembers) {
+        if (!member->empty()) {
+            return false;
+        }
+    }
+    return true;
+}
+
+void ClassDefinition::writeToStream(const StringPiece& prefix, bool final,
+                                    std::ostream* out) const {
+    if (mMembers.empty() && !mCreateIfEmpty) {
+        return;
+    }
+
+    ClassMember::writeToStream(prefix, final, out);
+
+    *out << prefix << "public ";
+    if (mQualifier == ClassQualifier::Static) {
+        *out << "static ";
+    }
+    *out << "final class " << mName << " {\n";
+
+    std::string newPrefix = prefix.toString();
+    newPrefix.append(kIndent);
+
+    for (const std::unique_ptr<ClassMember>& member : mMembers) {
+        member->writeToStream(newPrefix, final, out);
+        *out << "\n";
+    }
+
+    *out << prefix << "}";
+}
+
+constexpr static const char* sWarningHeader =
+        "/* AUTO-GENERATED FILE. DO NOT MODIFY.\n"
+        " *\n"
+        " * This class was automatically generated by the\n"
+        " * aapt tool from the resource data it found. It\n"
+        " * should not be modified by hand.\n"
+        " */\n\n";
+
+bool ClassDefinition::writeJavaFile(const ClassDefinition* def,
+                                    const StringPiece& package,
+                                    bool final,
+                                    std::ostream* out) {
+    *out << sWarningHeader << "package " << package << ";\n\n";
+    def->writeToStream("", final, out);
+    return bool(*out);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
new file mode 100644
index 0000000..53e0f6f
--- /dev/null
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -0,0 +1,188 @@
+/*
+ * 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 AAPT_JAVA_CLASSDEFINITION_H
+#define AAPT_JAVA_CLASSDEFINITION_H
+
+#include "Resource.h"
+#include "java/AnnotationProcessor.h"
+#include "util/StringPiece.h"
+#include "util/Util.h"
+
+#include <android-base/macros.h>
+#include <sstream>
+#include <string>
+
+namespace aapt {
+
+// The number of attributes to emit per line in a Styleable array.
+constexpr static size_t kAttribsPerLine = 4;
+constexpr static const char* kIndent = "  ";
+
+class ClassMember {
+public:
+    virtual ~ClassMember() = default;
+
+    AnnotationProcessor* getCommentBuilder() {
+        return &mProcessor;
+    }
+
+    virtual bool empty() const = 0;
+
+    virtual void writeToStream(const StringPiece& prefix, bool final, std::ostream* out) const {
+        mProcessor.writeToStream(out, prefix);
+    }
+
+private:
+    AnnotationProcessor mProcessor;
+};
+
+template <typename T>
+class PrimitiveMember : public ClassMember {
+public:
+    PrimitiveMember(const StringPiece& name, const T& val) :
+            mName(name.toString()), mVal(val) {
+    }
+
+    bool empty() const override {
+        return false;
+    }
+
+    void writeToStream(const StringPiece& prefix, bool final, std::ostream* out) const override {
+        ClassMember::writeToStream(prefix, final, out);
+
+        *out << prefix << "public static " << (final ? "final " : "")
+             << "int " << mName << "=" << mVal << ";";
+    }
+
+private:
+    std::string mName;
+    T mVal;
+
+    DISALLOW_COPY_AND_ASSIGN(PrimitiveMember);
+};
+
+/**
+ * Specialization for strings so they get the right type and are quoted with "".
+ */
+template <>
+class PrimitiveMember<std::string> : public ClassMember {
+public:
+    PrimitiveMember(const StringPiece& name, const std::string& val) :
+            mName(name.toString()), mVal(val) {
+    }
+
+    bool empty() const override {
+        return false;
+    }
+
+    void writeToStream(const StringPiece& prefix, bool final, std::ostream* out) const override {
+        ClassMember::writeToStream(prefix, final, out);
+
+        *out << prefix << "public static " << (final ? "final " : "")
+             << "String " << mName << "=\"" << mVal << "\";";
+    }
+
+private:
+    std::string mName;
+    std::string mVal;
+
+    DISALLOW_COPY_AND_ASSIGN(PrimitiveMember);
+};
+
+using IntMember = PrimitiveMember<uint32_t>;
+using ResourceMember = PrimitiveMember<ResourceId>;
+using StringMember = PrimitiveMember<std::string>;
+
+template <typename T>
+class PrimitiveArrayMember : public ClassMember {
+public:
+    PrimitiveArrayMember(const StringPiece& name) :
+            mName(name.toString()) {
+    }
+
+    void addElement(const T& val) {
+        mElements.push_back(val);
+    }
+
+    bool empty() const override {
+        return false;
+    }
+
+    void writeToStream(const StringPiece& prefix, bool final, std::ostream* out) const override {
+        ClassMember::writeToStream(prefix, final, out);
+
+        *out << "public static final int[] " << mName << "={";
+
+        const auto begin = mElements.begin();
+        const auto end = mElements.end();
+        for (auto current = begin; current != end; ++current) {
+            if (std::distance(begin, current) % kAttribsPerLine == 0) {
+                *out << "\n" << prefix << kIndent << kIndent;
+            }
+
+            *out << *current;
+            if (std::distance(current, end) > 1) {
+                *out << ", ";
+            }
+        }
+        *out << "\n" << prefix << kIndent <<"};";
+    }
+
+private:
+    std::string mName;
+    std::vector<T> mElements;
+
+    DISALLOW_COPY_AND_ASSIGN(PrimitiveArrayMember);
+};
+
+using ResourceArrayMember = PrimitiveArrayMember<ResourceId>;
+
+enum class ClassQualifier {
+    None,
+    Static
+};
+
+class ClassDefinition : public ClassMember {
+public:
+    static bool writeJavaFile(const ClassDefinition* def,
+                              const StringPiece& package,
+                              bool final,
+                              std::ostream* out);
+
+    ClassDefinition(const StringPiece& name, ClassQualifier qualifier, bool createIfEmpty) :
+            mName(name.toString()), mQualifier(qualifier), mCreateIfEmpty(createIfEmpty) {
+    }
+
+    void addMember(std::unique_ptr<ClassMember> member) {
+        mMembers.push_back(std::move(member));
+    }
+
+    bool empty() const override;
+    void writeToStream(const StringPiece& prefix, bool final, std::ostream* out) const override;
+
+private:
+    std::string mName;
+    ClassQualifier mQualifier;
+    bool mCreateIfEmpty;
+    std::vector<std::unique_ptr<ClassMember>> mMembers;
+
+    DISALLOW_COPY_AND_ASSIGN(ClassDefinition);
+};
+
+} // namespace aapt
+
+#endif /* AAPT_JAVA_CLASSDEFINITION_H */
diff --git a/tools/aapt2/java/ClassDefinitionWriter.h b/tools/aapt2/java/ClassDefinitionWriter.h
deleted file mode 100644
index cf92c9a..0000000
--- a/tools/aapt2/java/ClassDefinitionWriter.h
+++ /dev/null
@@ -1,142 +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 AAPT_JAVA_CLASSDEFINITION_H
-#define AAPT_JAVA_CLASSDEFINITION_H
-
-#include "Resource.h"
-#include "java/AnnotationProcessor.h"
-#include "util/StringPiece.h"
-#include "util/Util.h"
-
-#include <sstream>
-#include <string>
-
-namespace aapt {
-
-struct ClassDefinitionWriterOptions {
-    bool useFinalQualifier = false;
-    bool forceCreationIfEmpty = false;
-};
-
-/**
- * Writes a class for use in R.java or Manifest.java.
- */
-class ClassDefinitionWriter {
-public:
-    ClassDefinitionWriter(const StringPiece& name, const ClassDefinitionWriterOptions& options) :
-            mName(name.toString()), mOptions(options), mStarted(false) {
-    }
-
-    ClassDefinitionWriter(const StringPiece16& name, const ClassDefinitionWriterOptions& options) :
-            mName(util::utf16ToUtf8(name)), mOptions(options), mStarted(false) {
-    }
-
-    void addIntMember(const StringPiece& name, AnnotationProcessor* processor,
-                      const uint32_t val) {
-        ensureClassDeclaration();
-        if (processor) {
-            processor->writeToStream(&mOut, kIndent);
-        }
-        mOut << kIndent << "public static " << (mOptions.useFinalQualifier ? "final " : "")
-             << "int " << name << "=" << val << ";\n";
-    }
-
-    void addStringMember(const StringPiece16& name, AnnotationProcessor* processor,
-                         const StringPiece16& val) {
-        ensureClassDeclaration();
-        if (processor) {
-            processor->writeToStream(&mOut, kIndent);
-        }
-        mOut << kIndent << "public static " << (mOptions.useFinalQualifier ? "final " : "")
-             << "String " << name << "=\"" << val << "\";\n";
-    }
-
-    void addResourceMember(const StringPiece& name, AnnotationProcessor* processor,
-                           const ResourceId id) {
-        ensureClassDeclaration();
-        if (processor) {
-            processor->writeToStream(&mOut, kIndent);
-        }
-        mOut << kIndent << "public static " << (mOptions.useFinalQualifier ? "final " : "")
-             << "int " << name << "=" << id <<";\n";
-    }
-
-    template <typename Iterator, typename FieldAccessorFunc>
-    void addArrayMember(const StringPiece& name, AnnotationProcessor* processor,
-                        const Iterator begin, const Iterator end, FieldAccessorFunc f) {
-        ensureClassDeclaration();
-        if (processor) {
-            processor->writeToStream(&mOut, kIndent);
-        }
-        mOut << kIndent << "public static final int[] " << name << "={";
-
-        for (Iterator current = begin; current != end; ++current) {
-            if (std::distance(begin, current) % kAttribsPerLine == 0) {
-                mOut << "\n" << kIndent << kIndent;
-            }
-
-            mOut << f(*current);
-            if (std::distance(current, end) > 1) {
-                mOut << ", ";
-            }
-        }
-        mOut << "\n" << kIndent <<"};\n";
-    }
-
-    void writeToStream(std::ostream* out, const StringPiece& prefix,
-                       AnnotationProcessor* processor=nullptr) {
-        if (mOptions.forceCreationIfEmpty) {
-            ensureClassDeclaration();
-        }
-
-        if (!mStarted) {
-            return;
-        }
-
-        if (processor) {
-            processor->writeToStream(out, prefix);
-        }
-
-        std::string result = mOut.str();
-        for (StringPiece line : util::tokenize<char>(result, '\n')) {
-            *out << prefix << line << "\n";
-        }
-        *out << prefix << "}\n";
-    }
-
-private:
-    constexpr static const char* kIndent = "  ";
-
-    // The number of attributes to emit per line in a Styleable array.
-    constexpr static size_t kAttribsPerLine = 4;
-
-    void ensureClassDeclaration() {
-        if (!mStarted) {
-            mStarted = true;
-            mOut << "public static final class " << mName << " {\n";
-        }
-    }
-
-    std::stringstream mOut;
-    std::string mName;
-    ClassDefinitionWriterOptions mOptions;
-    bool mStarted;
-};
-
-} // namespace aapt
-
-#endif /* AAPT_JAVA_CLASSDEFINITION_H */
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 01330dc..32b8600 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -21,7 +21,7 @@
 #include "ValueVisitor.h"
 
 #include "java/AnnotationProcessor.h"
-#include "java/ClassDefinitionWriter.h"
+#include "java/ClassDefinition.h"
 #include "java/JavaClassGenerator.h"
 #include "process/SymbolTable.h"
 #include "util/StringPiece.h"
@@ -39,16 +39,6 @@
         mContext(context), mTable(table), mOptions(options) {
 }
 
-static void generateHeader(const StringPiece16& packageNameToGenerate, std::ostream* out) {
-    *out << "/* AUTO-GENERATED FILE. DO NOT MODIFY.\n"
-            " *\n"
-            " * This class was automatically generated by the\n"
-            " * aapt tool from the resource data it found. It\n"
-            " * should not be modified by hand.\n"
-            " */\n\n"
-            "package " << packageNameToGenerate << ";\n\n";
-}
-
 static const std::set<StringPiece16> sJavaIdentifiers = {
     u"abstract", u"assert", u"boolean", u"break", u"byte",
     u"case", u"catch", u"char", u"class", u"const", u"continue",
@@ -110,15 +100,15 @@
     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>\".");
+                "\"<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;");
+                "'\\\\n' or '\\\\uxxxx' for a unicode character;");
     }
 
     if (typeMask & android::ResTable_map::TYPE_INTEGER) {
@@ -128,14 +118,14 @@
     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>\".");
+                "\"<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>\".");
+                "\"<code>#<i>argb</i></code>\", \"<code>#<i>rrggbb</i></code\", or \n"
+                "\"<code>#<i>aarrggbb</i></code>\".");
     }
 
     if (typeMask & android::ResTable_map::TYPE_FLOAT) {
@@ -146,33 +136,33 @@
     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).");
+                "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.");
+                "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>");
+                    "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");
+                                 "<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>"
@@ -214,13 +204,15 @@
     }
 }
 
-void JavaClassGenerator::writeStyleableEntryForClass(ClassDefinitionWriter* outClassDef,
-                                                     AnnotationProcessor* processor,
-                                                     const StringPiece16& packageNameToGenerate,
-                                                     const std::u16string& entryName,
-                                                     const Styleable* styleable) {
+void JavaClassGenerator::addMembersToStyleableClass(const StringPiece16& packageNameToGenerate,
+                                                    const std::u16string& entryName,
+                                                    const Styleable* styleable,
+                                                    ClassDefinition* outStyleableClassDef) {
     const std::string className = transform(entryName);
 
+    std::unique_ptr<ResourceArrayMember> styleableArrayDef =
+            util::make_unique<ResourceArrayMember>(className);
+
     // This must be sorted by resource ID.
     std::vector<StyleableAttr> sortedAttributes;
     sortedAttributes.reserve(styleable->entries.size());
@@ -230,6 +222,8 @@
         assert((!mOptions.useFinal || attr.id) && "no ID set for Styleable entry");
         assert(attr.name && "no name set for Styleable entry");
 
+        // We will need the unmangled, transformed name in the comments and the field,
+        // so create it once and cache it in this StyleableAttr data structure.
         StyleableAttr styleableAttr = {};
         styleableAttr.attrRef = &attr;
         styleableAttr.fieldName = transformNestedAttr(attr.name.value(), className,
@@ -247,6 +241,8 @@
             mangledReference.name = mangledName;
         }
 
+        // Look up the symbol so that we can write out in the comments what are possible
+        // legal values for this attribute.
         const SymbolTable::Symbol* symbol = mContext->getExternalSymbols()->findByReference(
                 mangledReference);
         if (symbol) {
@@ -254,10 +250,11 @@
         }
         sortedAttributes.push_back(std::move(styleableAttr));
     }
+
+    // Sort the attributes by ID.
     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.
@@ -267,6 +264,7 @@
         } else {
             styleableComment << "Attributes that can be used with a " << className << ".\n";
         }
+
         styleableComment <<
                 "<p>Includes the following attributes:</p>\n"
                 "<table>\n"
@@ -274,7 +272,7 @@
                 "<colgroup align=\"left\" />\n"
                 "<tr><th>Attribute</th><th>Description</th></tr>\n";
 
-        for (const auto& entry : sortedAttributes) {
+        for (const StyleableAttr& entry : sortedAttributes) {
             const ResourceName& attrName = entry.attrRef->name.value();
             styleableComment << "<tr><td>";
             styleableComment << "<code>{@link #"
@@ -292,21 +290,22 @@
             styleableComment << "</td></tr>\n";
         }
         styleableComment << "</table>\n";
-        for (const auto& entry : sortedAttributes) {
+
+        for (const StyleableAttr& entry : sortedAttributes) {
             styleableComment << "@see #" << entry.fieldName << "\n";
         }
-        processor->appendComment(styleableComment.str());
+
+        styleableArrayDef->getCommentBuilder()->appendComment(styleableComment.str());
     }
 
-    auto accessorFunc = [](const StyleableAttr& a) -> ResourceId {
-        return a.attrRef->id ? a.attrRef->id.value() : ResourceId(0);
-    };
+    // Add the ResourceIds to the array member.
+    for (const StyleableAttr& styleableAttr : sortedAttributes) {
+        styleableArrayDef->addElement(
+                styleableAttr.attrRef->id ? styleableAttr.attrRef->id.value() : ResourceId(0));
+    }
 
-    // First we emit the array containing the IDs of each attribute.
-    outClassDef->addArrayMember(className, processor,
-                                sortedAttributes.begin(),
-                                sortedAttributes.end(),
-                                accessorFunc);
+    // Add the Styleable array to the Styleable class.
+    outStyleableClassDef->addMember(std::move(styleableArrayDef));
 
     // Now we emit the indices into the array.
     for (size_t i = 0; i < attrCount; i++) {
@@ -318,7 +317,10 @@
             packageName = mContext->getCompilationPackage();
         }
 
-        AnnotationProcessor attrProcessor;
+        std::unique_ptr<IntMember> indexMember = util::make_unique<IntMember>(
+                sortedAttributes[i].fieldName, static_cast<uint32_t>(i));
+
+        AnnotationProcessor* attrProcessor = indexMember->getCommentBuilder();
 
         StringPiece16 comment = styleableAttr.attrRef->getComment();
         if (styleableAttr.attribute && comment.empty()) {
@@ -326,8 +328,8 @@
         }
 
         if (!comment.empty()) {
-            attrProcessor.appendComment("<p>\n@attr description");
-            attrProcessor.appendComment(comment);
+            attrProcessor->appendComment("<p>\n@attr description");
+            attrProcessor->appendComment(comment);
         } else {
             std::stringstream defaultComment;
             defaultComment
@@ -335,27 +337,29 @@
                     << "{@link " << packageName << ".R.attr#" << transform(attrName.entry) << "}\n"
                     << "attribute's value can be found in the "
                     << "{@link #" << className << "} array.";
-            attrProcessor.appendComment(defaultComment.str());
+            attrProcessor->appendComment(defaultComment.str());
         }
 
-        attrProcessor.appendNewLine();
+        attrProcessor->appendNewLine();
 
         if (styleableAttr.attribute) {
-            addAttributeFormatDoc(&attrProcessor, styleableAttr.attribute.get());
-            attrProcessor.appendNewLine();
+            addAttributeFormatDoc(attrProcessor, styleableAttr.attribute.get());
+            attrProcessor->appendNewLine();
         }
 
         std::stringstream doclavaName;
         doclavaName << "@attr name " << packageName << ":" << attrName.entry;;
-        attrProcessor.appendComment(doclavaName.str());
-        outClassDef->addIntMember(sortedAttributes[i].fieldName, &attrProcessor, i);
+        attrProcessor->appendComment(doclavaName.str());
+
+        outStyleableClassDef->addMember(std::move(indexMember));
     }
 }
 
-bool JavaClassGenerator::writeEntriesForClass(ClassDefinitionWriter* outClassDef,
-                                              const StringPiece16& packageNameToGenerate,
-                                              const ResourceTablePackage* package,
-                                              const ResourceTableType* type) {
+bool JavaClassGenerator::addMembersToTypeClass(const StringPiece16& packageNameToGenerate,
+                                               const ResourceTablePackage* package,
+                                               const ResourceTableType* type,
+                                               ClassDefinition* outTypeClassDef) {
+
     for (const auto& entry : type->entries) {
         if (skipSymbol(entry->symbolStatus.state)) {
             continue;
@@ -389,33 +393,41 @@
             return false;
         }
 
-        // Build the comments and annotations for this entry.
-
-        AnnotationProcessor processor;
-        if (entry->symbolStatus.state != SymbolState::kUndefined) {
-            processor.appendComment(entry->symbolStatus.comment);
-        }
-
-        for (const auto& configValue : entry->values) {
-            processor.appendComment(configValue->value->getComment());
-        }
-
-        // If this is an Attribute, append the format Javadoc.
-        if (!entry->values.empty()) {
-            if (Attribute* attr = valueCast<Attribute>(entry->values.front()->value.get())) {
-                // We list out the available values for the given attribute.
-                addAttributeFormatDoc(&processor, attr);
-            }
-        }
-
         if (type->type == ResourceType::kStyleable) {
             assert(!entry->values.empty());
+
             const Styleable* styleable = static_cast<const Styleable*>(
                     entry->values.front()->value.get());
-            writeStyleableEntryForClass(outClassDef, &processor, packageNameToGenerate,
-                                        unmangledName, styleable);
+
+            // Comments are handled within this method.
+            addMembersToStyleableClass(packageNameToGenerate, unmangledName, styleable,
+                                       outTypeClassDef);
         } else {
-            outClassDef->addResourceMember(transform(unmangledName), &processor, id);
+            std::unique_ptr<ResourceMember> resourceMember =
+                    util::make_unique<ResourceMember>(transform(unmangledName), id);
+
+            // Build the comments and annotations for this entry.
+            AnnotationProcessor* processor = resourceMember->getCommentBuilder();
+
+            // Add the comments from any <public> tags.
+            if (entry->symbolStatus.state != SymbolState::kUndefined) {
+                processor->appendComment(entry->symbolStatus.comment);
+            }
+
+            // Add the comments from all configurations of this entry.
+            for (const auto& configValue : entry->values) {
+                processor->appendComment(configValue->value->getComment());
+            }
+
+            // If this is an Attribute, append the format Javadoc.
+            if (!entry->values.empty()) {
+                if (Attribute* attr = valueCast<Attribute>(entry->values.front()->value.get())) {
+                    // We list out the available values for the given attribute.
+                    addAttributeFormatDoc(processor, attr);
+                }
+            }
+
+            outTypeClassDef->addMember(std::move(resourceMember));
         }
     }
     return true;
@@ -425,11 +437,19 @@
     return generate(packageNameToGenerate, packageNameToGenerate, out);
 }
 
+static void appendJavaDocAnnotations(const std::vector<std::string>& annotations,
+                                     AnnotationProcessor* processor) {
+    for (const std::string& annotation : annotations) {
+        std::string properAnnotation = "@";
+        properAnnotation += annotation;
+        processor->appendComment(properAnnotation);
+    }
+}
+
 bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate,
                                   const StringPiece16& outPackageName, std::ostream* out) {
-    generateHeader(outPackageName, out);
 
-    *out << "public final class R {\n";
+    ClassDefinition rClass("R", ClassQualifier::None, true);
 
     for (const auto& package : mTable->packages) {
         for (const auto& type : package->types) {
@@ -437,13 +457,15 @@
                 continue;
             }
 
-            ClassDefinitionWriterOptions classOptions;
-            classOptions.useFinalQualifier = mOptions.useFinal;
-            classOptions.forceCreationIfEmpty =
+            const bool forceCreationIfEmpty =
                     (mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic);
-            ClassDefinitionWriter classDef(toString(type->type), classOptions);
-            bool result = writeEntriesForClass(&classDef, packageNameToGenerate,
-                                               package.get(), type.get());
+
+            std::unique_ptr<ClassDefinition> classDef = util::make_unique<ClassDefinition>(
+                    util::utf16ToUtf8(toString(type->type)), ClassQualifier::Static,
+                    forceCreationIfEmpty);
+
+            bool result = addMembersToTypeClass(packageNameToGenerate, package.get(), type.get(),
+                                                classDef.get());
             if (!result) {
                 return false;
             }
@@ -452,30 +474,36 @@
                 // Also include private attributes in this same class.
                 ResourceTableType* privType = package->findType(ResourceType::kAttrPrivate);
                 if (privType) {
-                    result = writeEntriesForClass(&classDef, packageNameToGenerate,
-                                                  package.get(), privType);
+                    result = addMembersToTypeClass(packageNameToGenerate, package.get(), privType,
+                                                   classDef.get());
                     if (!result) {
                         return false;
                     }
                 }
             }
 
-            AnnotationProcessor processor;
             if (type->type == ResourceType::kStyleable &&
                     mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic) {
                 // When generating a public R class, we don't want Styleable to be part of the API.
                 // It is only emitted for documentation purposes.
-                processor.appendComment("@doconly");
+                classDef->getCommentBuilder()->appendComment("@doconly");
             }
-            classDef.writeToStream(out, "  ", &processor);
+
+            appendJavaDocAnnotations(mOptions.javadocAnnotations, classDef->getCommentBuilder());
+
+            rClass.addMember(std::move(classDef));
         }
     }
 
-    *out << "}\n";
+    appendJavaDocAnnotations(mOptions.javadocAnnotations, rClass.getCommentBuilder());
+
+    if (!ClassDefinition::writeJavaFile(&rClass, util::utf16ToUtf8(outPackageName),
+                                        mOptions.useFinal, out)) {
+        return false;
+    }
+
     out->flush();
     return true;
 }
 
-
-
 } // namespace aapt
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 7e46f8c..77e0ed7 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -28,7 +28,7 @@
 namespace aapt {
 
 class AnnotationProcessor;
-class ClassDefinitionWriter;
+class ClassDefinition;
 
 struct JavaClassGeneratorOptions {
     /*
@@ -44,6 +44,11 @@
     };
 
     SymbolTypes types = SymbolTypes::kAll;
+
+    /**
+     * A list of JavaDoc annotations to add to the comments of all generated classes.
+     */
+    std::vector<std::string> javadocAnnotations;
 };
 
 /*
@@ -70,16 +75,15 @@
     const std::string& getError() const;
 
 private:
-    bool writeEntriesForClass(ClassDefinitionWriter* outClassDef,
-                              const StringPiece16& packageNameToGenerate,
-                              const ResourceTablePackage* package,
-                              const ResourceTableType* type);
+    bool addMembersToTypeClass(const StringPiece16& packageNameToGenerate,
+                               const ResourceTablePackage* package,
+                               const ResourceTableType* type,
+                               ClassDefinition* outTypeClassDef);
 
-    void writeStyleableEntryForClass(ClassDefinitionWriter* outClassDef,
-                                     AnnotationProcessor* processor,
-                                     const StringPiece16& packageNameToGenerate,
-                                     const std::u16string& entryName,
-                                     const Styleable* styleable);
+    void addMembersToStyleableClass(const StringPiece16& packageNameToGenerate,
+                                    const std::u16string& entryName,
+                                    const Styleable* styleable,
+                                    ClassDefinition* outStyleableClassDef);
 
     bool skipSymbol(SymbolState state);
 
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 4f041b8..370e78a 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -239,13 +239,15 @@
     ASSERT_TRUE(generator.generate(u"android", &out));
     std::string actual = out.str();
 
-    EXPECT_NE(std::string::npos, actual.find(
-    R"EOF(/**
+    const char* expectedText =
+R"EOF(/**
      * This is a comment
      * @deprecated
      */
     @Deprecated
-    public static final int foo=0x01010000;)EOF"));
+    public static final int foo=0x01010000;)EOF";
+
+    EXPECT_NE(std::string::npos, actual.find(expectedText));
 }
 
 TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {
diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp
index a9b4c14..be8955e 100644
--- a/tools/aapt2/java/ManifestClassGenerator.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator.cpp
@@ -16,7 +16,7 @@
 
 #include "Source.h"
 #include "java/AnnotationProcessor.h"
-#include "java/ClassDefinitionWriter.h"
+#include "java/ClassDefinition.h"
 #include "java/ManifestClassGenerator.h"
 #include "util/Maybe.h"
 #include "xml/XmlDom.h"
@@ -58,8 +58,8 @@
     return result;
 }
 
-static bool writeSymbol(IDiagnostics* diag, ClassDefinitionWriter* outClassDef, const Source& source,
-                        xml::Element* el) {
+static bool writeSymbol(const Source& source, IDiagnostics* diag, xml::Element* el,
+                        ClassDefinition* classDef) {
     xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name");
     if (!attr) {
         diag->error(DiagMessage(source) << "<" << el->name << "> must define 'android:name'");
@@ -72,54 +72,53 @@
         return false;
     }
 
-    AnnotationProcessor processor;
-    processor.appendComment(el->comment);
-    outClassDef->addStringMember(result.value(), &processor, attr->value);
+    std::unique_ptr<StringMember> stringMember = util::make_unique<StringMember>(
+            util::utf16ToUtf8(result.value()), util::utf16ToUtf8(attr->value));
+    stringMember->getCommentBuilder()->appendComment(el->comment);
+
+    classDef->addMember(std::move(stringMember));
     return true;
 }
 
-bool ManifestClassGenerator::generate(IDiagnostics* diag, const StringPiece16& package,
-                                      xml::XmlResource* res, std::ostream* out) {
+std::unique_ptr<ClassDefinition> generateManifestClass(IDiagnostics* diag, xml::XmlResource* res) {
     xml::Element* el = xml::findRootElement(res->root.get());
     if (!el) {
-        return false;
+        diag->error(DiagMessage(res->file.source) << "no root tag defined");
+        return {};
     }
 
     if (el->name != u"manifest" && !el->namespaceUri.empty()) {
         diag->error(DiagMessage(res->file.source) << "no <manifest> root tag defined");
-        return false;
+        return {};
     }
 
-    *out << "package " << package << ";\n\n"
-         << "public final class Manifest {\n";
+    std::unique_ptr<ClassDefinition> permissionClass =
+            util::make_unique<ClassDefinition>("permission", ClassQualifier::Static, false);
+    std::unique_ptr<ClassDefinition> permissionGroupClass =
+            util::make_unique<ClassDefinition>("permission_group", ClassQualifier::Static, false);
 
     bool error = false;
+
     std::vector<xml::Element*> children = el->getChildElements();
-
-    ClassDefinitionWriterOptions classOptions;
-    classOptions.useFinalQualifier = true;
-    classOptions.forceCreationIfEmpty = false;
-
-    // First write out permissions.
-    ClassDefinitionWriter classDef("permission", classOptions);
     for (xml::Element* childEl : children) {
-        if (childEl->namespaceUri.empty() && childEl->name == u"permission") {
-            error |= !writeSymbol(diag, &classDef, res->file.source, childEl);
+        if (childEl->namespaceUri.empty()) {
+            if (childEl->name == u"permission") {
+                error |= !writeSymbol(res->file.source, diag, childEl, permissionClass.get());
+            } else if (childEl->name == u"permission-group") {
+                error |= !writeSymbol(res->file.source, diag, childEl, permissionGroupClass.get());
+            }
         }
     }
-    classDef.writeToStream(out, "  ");
 
-    // Next write out permission groups.
-    classDef = ClassDefinitionWriter("permission_group", classOptions);
-    for (xml::Element* childEl : children) {
-        if (childEl->namespaceUri.empty() && childEl->name == u"permission-group") {
-            error |= !writeSymbol(diag, &classDef, res->file.source, childEl);
-        }
+    if (error) {
+        return {};
     }
-    classDef.writeToStream(out, "  ");
 
-    *out << "}\n";
-    return !error;
+    std::unique_ptr<ClassDefinition> manifestClass =
+            util::make_unique<ClassDefinition>("Manifest", ClassQualifier::None, false);
+    manifestClass->addMember(std::move(permissionClass));
+    manifestClass->addMember(std::move(permissionGroupClass));
+    return manifestClass;
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/java/ManifestClassGenerator.h b/tools/aapt2/java/ManifestClassGenerator.h
index 226ed23..f565289 100644
--- a/tools/aapt2/java/ManifestClassGenerator.h
+++ b/tools/aapt2/java/ManifestClassGenerator.h
@@ -18,6 +18,7 @@
 #define AAPT_JAVA_MANIFESTCLASSGENERATOR_H
 
 #include "Diagnostics.h"
+#include "java/ClassDefinition.h"
 #include "util/StringPiece.h"
 #include "xml/XmlDom.h"
 
@@ -25,10 +26,7 @@
 
 namespace aapt {
 
-struct ManifestClassGenerator {
-    bool generate(IDiagnostics* diag, const StringPiece16& package, xml::XmlResource* res,
-                  std::ostream* out);
-};
+std::unique_ptr<ClassDefinition> generateManifestClass(IDiagnostics* diag, xml::XmlResource* res);
 
 } // namespace aapt
 
diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp
index fc57ae6f..e7210db 100644
--- a/tools/aapt2/java/ManifestClassGenerator_test.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp
@@ -22,6 +22,23 @@
 
 namespace aapt {
 
+static ::testing::AssertionResult getManifestClassText(IAaptContext* context, xml::XmlResource* res,
+                                                       std::string* outStr) {
+    std::unique_ptr<ClassDefinition> manifestClass = generateManifestClass(
+            context->getDiagnostics(), res);
+    if (!manifestClass) {
+        return ::testing::AssertionFailure() << "manifestClass == nullptr";
+    }
+
+    std::stringstream out;
+    if (!manifestClass->writeJavaFile(manifestClass.get(), "android", true, &out)) {
+        return ::testing::AssertionFailure() << "failed to write java file";
+    }
+
+    *outStr = out.str();
+    return ::testing::AssertionSuccess();
+}
+
 TEST(ManifestClassGeneratorTest, NameIsProperlyGeneratedFromSymbol) {
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
     std::unique_ptr<xml::XmlResource> manifest = test::buildXmlDom(R"EOF(
@@ -32,11 +49,8 @@
           <permission-group android:name="foo.bar.PERMISSION" />
         </manifest>)EOF");
 
-    std::stringstream out;
-    ManifestClassGenerator generator;
-    ASSERT_TRUE(generator.generate(context->getDiagnostics(), u"android", manifest.get(), &out));
-
-    std::string actual = out.str();
+    std::string actual;
+    ASSERT_TRUE(getManifestClassText(context.get(), manifest.get(), &actual));
 
     const size_t permissionClassPos = actual.find("public static final class permission {");
     const size_t permissionGroupClassPos =
@@ -87,34 +101,37 @@
           <permission android:name="android.permission.SECRET" />
         </manifest>)EOF");
 
-    std::stringstream out;
-    ManifestClassGenerator generator;
-    ASSERT_TRUE(generator.generate(context->getDiagnostics(), u"android", manifest.get(), &out));
+    std::string actual;
+    ASSERT_TRUE(getManifestClassText(context.get(), manifest.get(), &actual));
 
-    std::string actual = out.str();
-
-    EXPECT_NE(std::string::npos, actual.find(
+    const char* expectedAccessInternet =
 R"EOF(    /**
      * Required to access the internet.
      * Added in API 1.
      */
-    public static final String ACCESS_INTERNET="android.permission.ACCESS_INTERNET";)EOF"));
+    public static final String ACCESS_INTERNET="android.permission.ACCESS_INTERNET";)EOF";
 
-    EXPECT_NE(std::string::npos, actual.find(
+    EXPECT_NE(std::string::npos, actual.find(expectedAccessInternet));
+
+    const char* expectedPlayOutside =
 R"EOF(    /**
      * @deprecated This permission is for playing outside.
      */
     @Deprecated
-    public static final String PLAY_OUTSIDE="android.permission.PLAY_OUTSIDE";)EOF"));
+    public static final String PLAY_OUTSIDE="android.permission.PLAY_OUTSIDE";)EOF";
 
-    EXPECT_NE(std::string::npos, actual.find(
+    EXPECT_NE(std::string::npos, actual.find(expectedPlayOutside));
+
+    const char* expectedSecret =
 R"EOF(    /**
      * This is a private permission for system only!
      * @hide
      * @SystemApi
      */
     @android.annotation.SystemApi
-    public static final String SECRET="android.permission.SECRET";)EOF"));
+    public static final String SECRET="android.permission.SECRET";)EOF";
+
+    EXPECT_NE(std::string::npos, actual.find(expectedSecret));
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index b84074d..8c8bffa 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -66,6 +66,7 @@
     bool staticLib = false;
     bool noStaticLibPackages = false;
     bool generateNonFinalIds = false;
+    std::vector<std::string> javadocAnnotations;
     bool outputToDirectory = false;
     bool autoAddOverlay = false;
     bool doNotCompressAnything = false;
@@ -762,9 +763,31 @@
             return true;
         }
 
+        std::unique_ptr<ClassDefinition> manifestClass = generateManifestClass(
+                mContext->getDiagnostics(), manifestXml);
+
+        if (!manifestClass) {
+            // Something bad happened, but we already logged it, so exit.
+            return false;
+        }
+
+        if (manifestClass->empty()) {
+            // Empty Manifest class, no need to generate it.
+            return true;
+        }
+
+        // Add any JavaDoc annotations to the generated class.
+        for (const std::string& annotation : mOptions.javadocAnnotations) {
+            std::string properAnnotation = "@";
+            properAnnotation += annotation;
+            manifestClass->getCommentBuilder()->appendComment(properAnnotation);
+        }
+
+        const std::string packageUtf8 = util::utf16ToUtf8(mContext->getCompilationPackage());
+
         std::string outPath = mOptions.generateJavaClassPath.value();
-        file::appendPath(&outPath,
-                         file::packageToPath(util::utf16ToUtf8(mContext->getCompilationPackage())));
+        file::appendPath(&outPath, file::packageToPath(packageUtf8));
+
         if (!file::mkdirs(outPath)) {
             mContext->getDiagnostics()->error(
                     DiagMessage() << "failed to create directory '" << outPath << "'");
@@ -780,13 +803,7 @@
             return false;
         }
 
-        ManifestClassGenerator generator;
-        if (!generator.generate(mContext->getDiagnostics(), mContext->getCompilationPackage(),
-                                manifestXml, &fout)) {
-            return false;
-        }
-
-        if (!fout) {
+        if (!ClassDefinition::writeJavaFile(manifestClass.get(), packageUtf8, true, &fout)) {
             mContext->getDiagnostics()->error(
                     DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
             return false;
@@ -1283,6 +1300,7 @@
         if (mOptions.generateJavaClassPath) {
             JavaClassGeneratorOptions options;
             options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
+            options.javadocAnnotations = mOptions.javadocAnnotations;
 
             if (mOptions.staticLib || mOptions.generateNonFinalIds) {
                 options.useFinal = false;
@@ -1423,6 +1441,8 @@
                           &customJavaPackage)
             .optionalFlagList("--extra-packages", "Generate the same R.java but with different "
                               "package names", &extraJavaPackages)
+            .optionalFlagList("--add-javadoc-annotation", "Adds a JavaDoc annotation to all "
+                            "generated Java classes", &options.javadocAnnotations)
             .optionalSwitch("--auto-add-overlay", "Allows the addition of new resources in "
                             "overlays without <add-resource> tags", &options.autoAddOverlay)
             .optionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml",
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 9baf1d8..3779638 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -17,66 +17,199 @@
 #include "ResourceUtils.h"
 #include "link/ManifestFixer.h"
 #include "util/Util.h"
+#include "xml/XmlActionExecutor.h"
 #include "xml/XmlDom.h"
 
 namespace aapt {
 
-static bool verifyManifest(IAaptContext* context, const Source& source, xml::Element* manifestEl) {
-    xml::Attribute* attr = manifestEl->findAttribute({}, u"package");
-    if (!attr) {
-        context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
-                                         << "missing 'package' attribute");
-    } else if (ResourceUtils::isReference(attr->value)) {
-        context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
-                                         << "value for attribute 'package' must not be a "
-                                            "reference");
-    } else if (!util::isJavaPackageName(attr->value)) {
-        context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
-                                         << "invalid package name '" << attr->value << "'");
-    } else {
-        return true;
+/**
+ * This is how PackageManager builds class names from AndroidManifest.xml entries.
+ */
+static bool nameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
+                                SourcePathDiagnostics* diag) {
+    std::u16string className = attr->value;
+    if (className.find(u'.') == std::u16string::npos) {
+        // There is no '.', so add one to the beginning.
+        className = u".";
+        className += attr->value;
     }
+
+    // We allow unqualified class names (ie: .HelloActivity)
+    // Since we don't know the package name, we can just make a fake one here and
+    // the test will be identical as long as the real package name is valid too.
+    Maybe<std::u16string> fullyQualifiedClassName =
+            util::getFullyQualifiedClassName(u"a", className);
+
+    StringPiece16 qualifiedClassName = fullyQualifiedClassName
+            ? fullyQualifiedClassName.value() : className;
+    if (!util::isJavaClassName(qualifiedClassName)) {
+        diag->error(DiagMessage(el->lineNumber)
+                    << "attribute 'android:name' in <"
+                    << el->name << "> tag must be a valid Java class name");
+        return false;
+    }
+    return true;
+}
+
+static bool optionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
+    if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name")) {
+        return nameIsJavaClassName(el, attr, diag);
+    }
+    return true;
+}
+
+static bool requiredNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
+    if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name")) {
+        return nameIsJavaClassName(el, attr, diag);
+    }
+    diag->error(DiagMessage(el->lineNumber)
+                << "<" << el->name << "> is missing attribute 'android:name'");
     return false;
 }
 
-static bool includeVersionName(IAaptContext* context, const Source& source,
-                               const StringPiece16& versionName, xml::Element* manifestEl) {
-    if (manifestEl->findAttribute(xml::kSchemaAndroid, u"versionName")) {
-        return true;
+static bool verifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
+    xml::Attribute* attr = el->findAttribute({}, u"package");
+    if (!attr) {
+        diag->error(DiagMessage(el->lineNumber) << "<manifest> tag is missing 'package' attribute");
+        return false;
+    } else if (ResourceUtils::isReference(attr->value)) {
+        diag->error(DiagMessage(el->lineNumber)
+                    << "attribute 'package' in <manifest> tag must not be a reference");
+        return false;
+    } else if (!util::isJavaPackageName(attr->value)) {
+        diag->error(DiagMessage(el->lineNumber)
+                    << "attribute 'package' in <manifest> tag is not a valid Java package name: '"
+                    << attr->value << "'");
+        return false;
     }
-
-    manifestEl->attributes.push_back(xml::Attribute{
-            xml::kSchemaAndroid, u"versionName", versionName.toString() });
     return true;
 }
 
-static bool includeVersionCode(IAaptContext* context, const Source& source,
-                               const StringPiece16& versionCode, xml::Element* manifestEl) {
-    if (manifestEl->findAttribute(xml::kSchemaAndroid, u"versionCode")) {
+bool ManifestFixer::buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag) {
+    // First verify some options.
+    if (mOptions.renameManifestPackage) {
+        if (!util::isJavaPackageName(mOptions.renameManifestPackage.value())) {
+            diag->error(DiagMessage() << "invalid manifest package override '"
+                        << mOptions.renameManifestPackage.value() << "'");
+            return false;
+        }
+    }
+
+    if (mOptions.renameInstrumentationTargetPackage) {
+        if (!util::isJavaPackageName(mOptions.renameInstrumentationTargetPackage.value())) {
+            diag->error(DiagMessage() << "invalid instrumentation target package override '"
+                        << mOptions.renameInstrumentationTargetPackage.value() << "'");
+            return false;
+        }
+    }
+
+    // Common intent-filter actions.
+    xml::XmlNodeAction intentFilterAction;
+    intentFilterAction[u"action"];
+    intentFilterAction[u"category"];
+    intentFilterAction[u"data"];
+
+    // Common meta-data actions.
+    xml::XmlNodeAction metaDataAction;
+
+    // Manifest actions.
+    xml::XmlNodeAction& manifestAction = (*executor)[u"manifest"];
+    manifestAction.action(verifyManifest);
+    manifestAction.action([&](xml::Element* el) -> bool {
+        if (mOptions.versionNameDefault) {
+            if (el->findAttribute(xml::kSchemaAndroid, u"versionName") == nullptr) {
+                el->attributes.push_back(xml::Attribute{
+                        xml::kSchemaAndroid,
+                        u"versionName",
+                        mOptions.versionNameDefault.value() });
+            }
+        }
+
+        if (mOptions.versionCodeDefault) {
+            if (el->findAttribute(xml::kSchemaAndroid, u"versionCode") == nullptr) {
+                el->attributes.push_back(xml::Attribute{
+                        xml::kSchemaAndroid,
+                        u"versionCode",
+                        mOptions.versionCodeDefault.value() });
+            }
+        }
         return true;
-    }
+    });
 
-    manifestEl->attributes.push_back(xml::Attribute{
-            xml::kSchemaAndroid, u"versionCode", versionCode.toString() });
-    return true;
-}
+    // Uses-sdk actions.
+    manifestAction[u"uses-sdk"].action([&](xml::Element* el) -> bool {
+        if (mOptions.minSdkVersionDefault &&
+                el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion") == nullptr) {
+            // There was no minSdkVersion defined and we have a default to assign.
+            el->attributes.push_back(xml::Attribute{
+                    xml::kSchemaAndroid, u"minSdkVersion",
+                    mOptions.minSdkVersionDefault.value() });
+        }
 
-static bool fixUsesSdk(IAaptContext* context, const Source& source, xml::Element* el,
-                       const ManifestFixerOptions& options) {
-    if (options.minSdkVersionDefault &&
-            el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion") == nullptr) {
-        // There was no minSdkVersion defined and we have a default to assign.
-        el->attributes.push_back(xml::Attribute{
-                xml::kSchemaAndroid, u"minSdkVersion", options.minSdkVersionDefault.value() });
-    }
+        if (mOptions.targetSdkVersionDefault &&
+                el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion") == nullptr) {
+            // There was no targetSdkVersion defined and we have a default to assign.
+            el->attributes.push_back(xml::Attribute{
+                    xml::kSchemaAndroid, u"targetSdkVersion",
+                    mOptions.targetSdkVersionDefault.value() });
+        }
+        return true;
+    });
 
-    if (options.targetSdkVersionDefault &&
-            el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion") == nullptr) {
-        // There was no targetSdkVersion defined and we have a default to assign.
-        el->attributes.push_back(xml::Attribute{
-                xml::kSchemaAndroid, u"targetSdkVersion",
-                options.targetSdkVersionDefault.value() });
-    }
+    // Instrumentation actions.
+    manifestAction[u"instrumentation"].action([&](xml::Element* el) -> bool {
+        if (!mOptions.renameInstrumentationTargetPackage) {
+            return true;
+        }
+
+        if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"targetPackage")) {
+            attr->value = mOptions.renameInstrumentationTargetPackage.value();
+        }
+        return true;
+    });
+
+    manifestAction[u"eat-comment"];
+    manifestAction[u"protected-broadcast"];
+    manifestAction[u"uses-permission"];
+    manifestAction[u"permission"];
+    manifestAction[u"permission-tree"];
+    manifestAction[u"permission-group"];
+
+    manifestAction[u"uses-configuration"];
+    manifestAction[u"uses-feature"];
+    manifestAction[u"uses-library"];
+    manifestAction[u"supports-screens"];
+    manifestAction[u"compatible-screens"];
+    manifestAction[u"supports-gl-texture"];
+
+    // Application actions.
+    xml::XmlNodeAction& applicationAction = (*executor)[u"manifest"][u"application"];
+    applicationAction.action(optionalNameIsJavaClassName);
+
+    // Activity actions.
+    applicationAction[u"activity"].action(requiredNameIsJavaClassName);
+    applicationAction[u"activity"][u"intent-filter"] = intentFilterAction;
+    applicationAction[u"activity"][u"meta-data"] = metaDataAction;
+
+    // Activity alias actions.
+    applicationAction[u"activity-alias"][u"intent-filter"] = intentFilterAction;
+    applicationAction[u"activity-alias"][u"meta-data"] = metaDataAction;
+
+    // Service actions.
+    applicationAction[u"service"].action(requiredNameIsJavaClassName);
+    applicationAction[u"service"][u"intent-filter"] = intentFilterAction;
+    applicationAction[u"service"][u"meta-data"] = metaDataAction;
+
+    // Receiver actions.
+    applicationAction[u"receiver"].action(requiredNameIsJavaClassName);
+    applicationAction[u"receiver"][u"intent-filter"] = intentFilterAction;
+    applicationAction[u"receiver"][u"meta-data"] = metaDataAction;
+
+    // Provider actions.
+    applicationAction[u"provider"].action(requiredNameIsJavaClassName);
+    applicationAction[u"provider"][u"grant-uri-permissions"];
+    applicationAction[u"provider"][u"meta-data"] = metaDataAction;
+    applicationAction[u"provider"][u"path-permissions"];
     return true;
 }
 
@@ -103,14 +236,7 @@
     StringPiece16 mPackage;
 };
 
-static bool renameManifestPackage(IAaptContext* context, const Source& source,
-                                  const StringPiece16& packageOverride, xml::Element* manifestEl) {
-    if (!util::isJavaPackageName(packageOverride)) {
-        context->getDiagnostics()->error(DiagMessage() << "invalid manifest package override '"
-                                         << packageOverride << "'");
-        return false;
-    }
-
+static bool renameManifestPackage(const StringPiece16& packageOverride, xml::Element* manifestEl) {
     xml::Attribute* attr = manifestEl->findAttribute({}, u"package");
 
     // We've already verified that the manifest element is present, with a package name specified.
@@ -124,32 +250,6 @@
     return true;
 }
 
-static bool renameInstrumentationTargetPackage(IAaptContext* context, const Source& source,
-                                               const StringPiece16& packageOverride,
-                                               xml::Element* manifestEl) {
-    if (!util::isJavaPackageName(packageOverride)) {
-        context->getDiagnostics()->error(DiagMessage()
-                                         << "invalid instrumentation target package override '"
-                                         << packageOverride << "'");
-        return false;
-    }
-
-    xml::Element* instrumentationEl = manifestEl->findChild({}, u"instrumentation");
-    if (!instrumentationEl) {
-        // No error if there is no work to be done.
-        return true;
-    }
-
-    xml::Attribute* attr = instrumentationEl->findAttribute(xml::kSchemaAndroid, u"targetPackage");
-    if (!attr) {
-        // No error if there is no work to be done.
-        return true;
-    }
-
-    attr->value = packageOverride.toString();
-    return true;
-}
-
 bool ManifestFixer::consume(IAaptContext* context, xml::XmlResource* doc) {
     xml::Element* root = xml::findRootElement(doc->root.get());
     if (!root || !root->namespaceUri.empty() || root->name != u"manifest") {
@@ -158,59 +258,31 @@
         return false;
     }
 
-    if (!verifyManifest(context, doc->file.source, root)) {
-        return false;
-    }
-
-    if (mOptions.versionCodeDefault) {
-        if (!includeVersionCode(context, doc->file.source, mOptions.versionCodeDefault.value(),
-                                root)) {
-            return false;
-        }
-    }
-
-    if (mOptions.versionNameDefault) {
-        if (!includeVersionName(context, doc->file.source, mOptions.versionNameDefault.value(),
-                                root)) {
-            return false;
-        }
-    }
-
-    if (mOptions.renameManifestPackage) {
-        // Rename manifest package.
-        if (!renameManifestPackage(context, doc->file.source,
-                                   mOptions.renameManifestPackage.value(), root)) {
-            return false;
-        }
-    }
-
-    if (mOptions.renameInstrumentationTargetPackage) {
-        if (!renameInstrumentationTargetPackage(context, doc->file.source,
-                                                mOptions.renameInstrumentationTargetPackage.value(),
-                                                root)) {
-            return false;
-        }
-    }
-
-    bool foundUsesSdk = false;
-    for (xml::Element* el : root->getChildElements()) {
-        if (!el->namespaceUri.empty()) {
-            continue;
-        }
-
-        if (el->name == u"uses-sdk") {
-            foundUsesSdk = true;
-            fixUsesSdk(context, doc->file.source, el, mOptions);
-        }
-    }
-
-    if (!foundUsesSdk && (mOptions.minSdkVersionDefault || mOptions.targetSdkVersionDefault)) {
+    if ((mOptions.minSdkVersionDefault || mOptions.targetSdkVersionDefault)
+            && root->findChild({}, u"uses-sdk") == nullptr) {
+        // Auto insert a <uses-sdk> element.
         std::unique_ptr<xml::Element> usesSdk = util::make_unique<xml::Element>();
         usesSdk->name = u"uses-sdk";
-        fixUsesSdk(context, doc->file.source, usesSdk.get(), mOptions);
         root->addChild(std::move(usesSdk));
     }
 
+    xml::XmlActionExecutor executor;
+    if (!buildRules(&executor, context->getDiagnostics())) {
+        return false;
+    }
+
+    if (!executor.execute(xml::XmlActionExecutorPolicy::Whitelist, context->getDiagnostics(),
+                          doc)) {
+        return false;
+    }
+
+    if (mOptions.renameManifestPackage) {
+        // Rename manifest package outside of the XmlActionExecutor.
+        // We need to extract the old package name and FullyQualify all class names.
+        if (!renameManifestPackage(mOptions.renameManifestPackage.value(), root)) {
+            return false;
+        }
+    }
     return true;
 }
 
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index b8d9c83..4d9356a 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -19,6 +19,7 @@
 
 #include "process/IResourceTableConsumer.h"
 #include "util/Maybe.h"
+#include "xml/XmlActionExecutor.h"
 #include "xml/XmlDom.h"
 
 #include <string>
@@ -38,13 +39,17 @@
  * Verifies that the manifest is correctly formed and inserts defaults
  * where specified with ManifestFixerOptions.
  */
-struct ManifestFixer : public IXmlResourceConsumer {
-    ManifestFixerOptions mOptions;
-
+class ManifestFixer : public IXmlResourceConsumer {
+public:
     ManifestFixer(const ManifestFixerOptions& options) : mOptions(options) {
     }
 
     bool consume(IAaptContext* context, xml::XmlResource* doc) override;
+
+private:
+    bool buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag);
+
+    ManifestFixerOptions mOptions;
 };
 
 } // namespace aapt
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 18c47df..f993720 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -166,9 +166,9 @@
     std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                 package="android">
-        <application name=".MainApplication" text="hello">
-          <activity name=".activity.Start" />
-          <receiver name="com.google.android.Receiver" />
+        <application android:name=".MainApplication" text="hello">
+          <activity android:name=".activity.Start" />
+          <receiver android:name="com.google.android.Receiver" />
         </application>
       </manifest>)EOF", options);
     ASSERT_NE(nullptr, doc);
@@ -185,7 +185,7 @@
     xml::Element* applicationEl = manifestEl->findChild({}, u"application");
     ASSERT_NE(nullptr, applicationEl);
 
-    attr = applicationEl->findAttribute({}, u"name");
+    attr = applicationEl->findAttribute(xml::kSchemaAndroid, u"name");
     ASSERT_NE(nullptr, attr);
     EXPECT_EQ(std::u16string(u"android.MainApplication"), attr->value);
 
@@ -197,14 +197,14 @@
     el = applicationEl->findChild({}, u"activity");
     ASSERT_NE(nullptr, el);
 
-    attr = el->findAttribute({}, u"name");
+    attr = el->findAttribute(xml::kSchemaAndroid, u"name");
     ASSERT_NE(nullptr, el);
     EXPECT_EQ(std::u16string(u"android.activity.Start"), attr->value);
 
     el = applicationEl->findChild({}, u"receiver");
     ASSERT_NE(nullptr, el);
 
-    attr = el->findAttribute({}, u"name");
+    attr = el->findAttribute(xml::kSchemaAndroid, u"name");
     ASSERT_NE(nullptr, el);
     EXPECT_EQ(std::u16string(u"com.google.android.Receiver"), attr->value);
 }
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 86883f8..82e4fb0 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -388,6 +388,10 @@
 std::unique_ptr<ResourceTable> deserializeTableFromPb(const pb::ResourceTable& pbTable,
                                                       const Source& source,
                                                       IDiagnostics* diag) {
+    // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
+    // causes errors when qualifying it with android::
+    using namespace android;
+
     std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
 
     if (!pbTable.has_string_pool()) {
@@ -395,29 +399,29 @@
         return {};
     }
 
-    android::ResStringPool valuePool;
-    android::status_t result = valuePool.setTo(pbTable.string_pool().data().data(),
-                                               pbTable.string_pool().data().size());
-    if (result != android::NO_ERROR) {
+    ResStringPool valuePool;
+    status_t result = valuePool.setTo(pbTable.string_pool().data().data(),
+                                      pbTable.string_pool().data().size());
+    if (result != NO_ERROR) {
         diag->error(DiagMessage(source) << "invalid string pool");
         return {};
     }
 
-    android::ResStringPool sourcePool;
+    ResStringPool sourcePool;
     if (pbTable.has_source_pool()) {
         result = sourcePool.setTo(pbTable.source_pool().data().data(),
                                   pbTable.source_pool().data().size());
-        if (result != android::NO_ERROR) {
+        if (result != NO_ERROR) {
             diag->error(DiagMessage(source) << "invalid source pool");
             return {};
         }
     }
 
-    android::ResStringPool symbolPool;
+    ResStringPool symbolPool;
     if (pbTable.has_symbol_pool()) {
         result = symbolPool.setTo(pbTable.symbol_pool().data().data(),
                                   pbTable.symbol_pool().data().size());
-        if (result != android::NO_ERROR) {
+        if (result != NO_ERROR) {
             diag->error(DiagMessage(source) << "invalid symbol pool");
             return {};
         }
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 0f7649b..4bfdb12 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -18,6 +18,7 @@
 #include "ResourceTable.h"
 #include "split/TableSplitter.h"
 
+#include <algorithm>
 #include <map>
 #include <set>
 #include <unordered_map>
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 8c56ebc..8eb4bc8 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -238,7 +238,7 @@
     std::stringstream in;
     in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str;
     StdErrDiagnostics diag;
-    std::unique_ptr<xml::XmlResource> doc = xml::inflate(&in, &diag, {});
+    std::unique_ptr<xml::XmlResource> doc = xml::inflate(&in, &diag, Source("test.xml"));
     assert(doc);
     return doc;
 }
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index 348c32a..faccd477 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -41,15 +41,20 @@
 namespace test {
 
 struct DummyDiagnosticsImpl : public IDiagnostics {
-    void error(const DiagMessage& message) override {
-        DiagMessageActual actual = message.build();
-        std::cerr << actual.source << ": error: " << actual.message << "." << std::endl;
+    void log(Level level, DiagMessageActual& actualMsg) override {
+        switch (level) {
+        case Level::Note:
+            return;
+
+        case Level::Warn:
+            std::cerr << actualMsg.source << ": warn: " << actualMsg.message << "." << std::endl;
+            break;
+
+        case Level::Error:
+            std::cerr << actualMsg.source << ": error: " << actualMsg.message << "." << std::endl;
+            break;
+        }
     }
-    void warn(const DiagMessage& message) override {
-        DiagMessageActual actual = message.build();
-        std::cerr << actual.source << ": warn: " << actual.message << "." << std::endl;
-    }
-    void note(const DiagMessage& message) override {}
 };
 
 inline IDiagnostics* getDiagnostics() {
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp
index 33b505e..ec46751 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.cpp
+++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp
@@ -26,7 +26,7 @@
 #include <androidfw/ResourceTypes.h>
 #include <androidfw/TypeWrappers.h>
 #include <android-base/macros.h>
-
+#include <algorithm>
 #include <map>
 #include <string>
 
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 6428e98..bb093ab 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -17,6 +17,7 @@
 #include "util/Files.h"
 #include "util/Util.h"
 
+#include <algorithm>
 #include <cerrno>
 #include <cstdio>
 #include <dirent.h>
diff --git a/tools/aapt2/util/Maybe.h b/tools/aapt2/util/Maybe.h
index 10a2803..595db96 100644
--- a/tools/aapt2/util/Maybe.h
+++ b/tools/aapt2/util/Maybe.h
@@ -17,6 +17,8 @@
 #ifndef AAPT_MAYBE_H
 #define AAPT_MAYBE_H
 
+#include "util/TypeTraits.h"
+
 #include <cassert>
 #include <type_traits>
 #include <utility>
@@ -276,13 +278,15 @@
 }
 
 /**
- * Define the == operator between Maybe<T> and Maybe<U> if the operator T == U is defined.
- * Otherwise this won't be defined and the compiler will yell at the callsite instead of inside
- * Maybe.h.
+ * Define the == operator between Maybe<T> and Maybe<U> only if the operator T == U is defined.
+ * That way the compiler will show an error at the callsite when comparing two Maybe<> objects
+ * whose inner types can't be compared.
  */
 template <typename T, typename U>
-auto operator==(const Maybe<T>& a, const Maybe<U>& b)
--> decltype(std::declval<T> == std::declval<U>) {
+typename std::enable_if<
+        has_eq_op<T, U>::value,
+        bool
+>::type operator==(const Maybe<T>& a, const Maybe<U>& b) {
     if (a && b) {
         return a.value() == b.value();
     } else if (!a && !b) {
@@ -295,8 +299,10 @@
  * Same as operator== but negated.
  */
 template <typename T, typename U>
-auto operator!=(const Maybe<T>& a, const Maybe<U>& b)
--> decltype(std::declval<T> == std::declval<U>) {
+typename std::enable_if<
+        has_eq_op<T, U>::value,
+        bool
+>::type operator!=(const Maybe<T>& a, const Maybe<U>& b) {
     return !(a == b);
 }
 
diff --git a/tools/aapt2/xml/XmlActionExecutor.cpp b/tools/aapt2/xml/XmlActionExecutor.cpp
new file mode 100644
index 0000000..0ef67ea
--- /dev/null
+++ b/tools/aapt2/xml/XmlActionExecutor.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "xml/XmlActionExecutor.h"
+
+namespace aapt {
+namespace xml {
+
+static bool wrapperOne(XmlNodeAction::ActionFunc& f, Element* el, SourcePathDiagnostics*) {
+    return f(el);
+}
+
+static bool wrapperTwo(XmlNodeAction::ActionFuncWithDiag& f, Element* el,
+                       SourcePathDiagnostics* diag) {
+    return f(el, diag);
+}
+
+void XmlNodeAction::action(XmlNodeAction::ActionFunc f) {
+    mActions.emplace_back(std::bind(wrapperOne, std::move(f),
+                                    std::placeholders::_1,
+                                    std::placeholders::_2));
+}
+
+void XmlNodeAction::action(XmlNodeAction::ActionFuncWithDiag f) {
+    mActions.emplace_back(std::bind(wrapperTwo, std::move(f),
+                                    std::placeholders::_1,
+                                    std::placeholders::_2));
+}
+
+static void printElementToDiagMessage(const Element* el, DiagMessage* msg) {
+    *msg << "<";
+    if (!el->namespaceUri.empty()) {
+        *msg << el->namespaceUri << ":";
+    }
+    *msg << el->name << ">";
+}
+
+bool XmlNodeAction::execute(XmlActionExecutorPolicy policy, SourcePathDiagnostics* diag,
+                            Element* el) const {
+    bool error = false;
+    for (const ActionFuncWithDiag& action : mActions) {
+        error |= !action(el, diag);
+    }
+
+    for (Element* childEl : el->getChildElements()) {
+        if (childEl->namespaceUri.empty()) {
+            std::map<std::u16string, XmlNodeAction>::const_iterator iter =
+                    mMap.find(childEl->name);
+            if (iter != mMap.end()) {
+                error |= !iter->second.execute(policy, diag, childEl);
+                continue;
+            }
+        }
+
+        if (policy == XmlActionExecutorPolicy::Whitelist) {
+            DiagMessage errorMsg(childEl->lineNumber);
+            errorMsg << "unknown element ";
+            printElementToDiagMessage(childEl, &errorMsg);
+            errorMsg << " found";
+            diag->error(errorMsg);
+            error = true;
+        }
+    }
+    return !error;
+}
+
+bool XmlActionExecutor::execute(XmlActionExecutorPolicy policy, IDiagnostics* diag,
+                                XmlResource* doc) const {
+    SourcePathDiagnostics sourceDiag(doc->file.source, diag);
+
+    Element* el = findRootElement(doc);
+    if (!el) {
+        if (policy == XmlActionExecutorPolicy::Whitelist) {
+            sourceDiag.error(DiagMessage() << "no root XML tag found");
+            return false;
+        }
+        return true;
+    }
+
+    if (el->namespaceUri.empty()) {
+        std::map<std::u16string, XmlNodeAction>::const_iterator iter = mMap.find(el->name);
+        if (iter != mMap.end()) {
+            return iter->second.execute(policy, &sourceDiag, el);
+        }
+    }
+
+    if (policy == XmlActionExecutorPolicy::Whitelist) {
+        DiagMessage errorMsg(el->lineNumber);
+        errorMsg << "unknown element ";
+        printElementToDiagMessage(el, &errorMsg);
+        errorMsg << " found";
+        sourceDiag.error(errorMsg);
+        return false;
+    }
+    return true;
+}
+
+} // namespace xml
+} // namespace aapt
diff --git a/tools/aapt2/xml/XmlActionExecutor.h b/tools/aapt2/xml/XmlActionExecutor.h
new file mode 100644
index 0000000..36b94db
--- /dev/null
+++ b/tools/aapt2/xml/XmlActionExecutor.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_XML_XMLPATTERN_H
+#define AAPT_XML_XMLPATTERN_H
+
+#include "Diagnostics.h"
+#include "xml/XmlDom.h"
+
+#include <android-base/macros.h>
+#include <functional>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace aapt {
+namespace xml {
+
+enum class XmlActionExecutorPolicy {
+    /**
+     * Actions on run if elements are matched, errors occur only when actions return false.
+     */
+    None,
+
+    /**
+     * The actions defined must match and run. If an element is found that does not match
+     * an action, an error occurs.
+     */
+    Whitelist,
+};
+
+/**
+ * Contains the actions to perform at this XML node. This is a recursive data structure that
+ * holds XmlNodeActions for child XML nodes.
+ */
+class XmlNodeAction {
+public:
+    using ActionFuncWithDiag = std::function<bool(Element*, SourcePathDiagnostics*)>;
+    using ActionFunc = std::function<bool(Element*)>;
+
+    /**
+     * Find or create a child XmlNodeAction that will be performed for the child element
+     * with the name `name`.
+     */
+    XmlNodeAction& operator[](const std::u16string& name) {
+        return mMap[name];
+    }
+
+    /**
+     * Add an action to be performed at this XmlNodeAction.
+     */
+    void action(ActionFunc f);
+    void action(ActionFuncWithDiag);
+
+private:
+    friend class XmlActionExecutor;
+
+    bool execute(XmlActionExecutorPolicy policy, SourcePathDiagnostics* diag, Element* el) const;
+
+    std::map<std::u16string, XmlNodeAction> mMap;
+    std::vector<ActionFuncWithDiag> mActions;
+};
+
+/**
+ * Allows the definition of actions to execute at specific XML elements defined by their
+ * hierarchy.
+ */
+class XmlActionExecutor {
+public:
+    XmlActionExecutor() = default;
+
+    /**
+     * Find or create a root XmlNodeAction that will be performed for the root XML element
+     * with the name `name`.
+     */
+    XmlNodeAction& operator[](const std::u16string& name) {
+        return mMap[name];
+    }
+
+    /**
+     * Execute the defined actions for this XmlResource.
+     * Returns true if all actions return true, otherwise returns false.
+     */
+    bool execute(XmlActionExecutorPolicy policy, IDiagnostics* diag, XmlResource* doc) const;
+
+private:
+    std::map<std::u16string, XmlNodeAction> mMap;
+
+    DISALLOW_COPY_AND_ASSIGN(XmlActionExecutor);
+};
+
+} // namespace xml
+} // namespace aapt
+
+#endif /* AAPT_XML_XMLPATTERN_H */
diff --git a/tools/aapt2/xml/XmlActionExecutor_test.cpp b/tools/aapt2/xml/XmlActionExecutor_test.cpp
new file mode 100644
index 0000000..ebf287a
--- /dev/null
+++ b/tools/aapt2/xml/XmlActionExecutor_test.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "xml/XmlActionExecutor.h"
+
+namespace aapt {
+namespace xml {
+
+TEST(XmlActionExecutorTest, BuildsAccessibleNestedPattern) {
+    XmlActionExecutor executor;
+    XmlNodeAction& manifestAction = executor[u"manifest"];
+    XmlNodeAction& applicationAction = manifestAction[u"application"];
+
+    Element* manifestEl = nullptr;
+    manifestAction.action([&](Element* manifest) -> bool {
+        manifestEl = manifest;
+        return true;
+    });
+
+    Element* applicationEl = nullptr;
+    applicationAction.action([&](Element* application) -> bool {
+        applicationEl = application;
+        return true;
+    });
+
+    std::unique_ptr<XmlResource> doc = test::buildXmlDom("<manifest><application /></manifest>");
+
+    StdErrDiagnostics diag;
+    ASSERT_TRUE(executor.execute(XmlActionExecutorPolicy::None, &diag, doc.get()));
+    ASSERT_NE(nullptr, manifestEl);
+    EXPECT_EQ(std::u16string(u"manifest"), manifestEl->name);
+
+    ASSERT_NE(nullptr, applicationEl);
+    EXPECT_EQ(std::u16string(u"application"), applicationEl->name);
+}
+
+TEST(XmlActionExecutorTest, FailsWhenUndefinedHierarchyExists) {
+    XmlActionExecutor executor;
+    executor[u"manifest"][u"application"];
+
+    std::unique_ptr<XmlResource> doc = test::buildXmlDom(
+            "<manifest><application /><activity /></manifest>");
+    StdErrDiagnostics diag;
+    ASSERT_FALSE(executor.execute(XmlActionExecutorPolicy::Whitelist, &diag, doc.get()));
+}
+
+} // namespace xml
+} // namespace aapt
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index d27b62fd..0ce333a 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -228,20 +228,24 @@
 
 std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag,
                                      const Source& source) {
+    // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
+    // causes errors when qualifying it with android::
+    using namespace android;
+
     std::unique_ptr<Node> root;
     std::stack<Node*> nodeStack;
 
-    android::ResXMLTree tree;
-    if (tree.setTo(data, dataLen) != android::NO_ERROR) {
+    ResXMLTree tree;
+    if (tree.setTo(data, dataLen) != NO_ERROR) {
         return {};
     }
 
-    android::ResXMLParser::event_code_t code;
-    while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
-            code != android::ResXMLParser::END_DOCUMENT) {
+    ResXMLParser::event_code_t code;
+    while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
+            code != ResXMLParser::END_DOCUMENT) {
         std::unique_ptr<Node> newNode;
         switch (code) {
-            case android::ResXMLParser::START_NAMESPACE: {
+            case ResXMLParser::START_NAMESPACE: {
                 std::unique_ptr<Namespace> node = util::make_unique<Namespace>();
                 size_t len;
                 const char16_t* str16 = tree.getNamespacePrefix(&len);
@@ -257,7 +261,7 @@
                 break;
             }
 
-            case android::ResXMLParser::START_TAG: {
+            case ResXMLParser::START_TAG: {
                 std::unique_ptr<Element> node = util::make_unique<Element>();
                 size_t len;
                 const char16_t* str16 = tree.getElementNamespace(&len);
@@ -276,7 +280,7 @@
                 break;
             }
 
-            case android::ResXMLParser::TEXT: {
+            case ResXMLParser::TEXT: {
                 std::unique_ptr<Text> node = util::make_unique<Text>();
                 size_t len;
                 const char16_t* str16 = tree.getText(&len);
@@ -287,8 +291,8 @@
                 break;
             }
 
-            case android::ResXMLParser::END_NAMESPACE:
-            case android::ResXMLParser::END_TAG:
+            case ResXMLParser::END_NAMESPACE:
+            case ResXMLParser::END_TAG:
                 assert(!nodeStack.empty());
                 nodeStack.pop();
                 break;
diff --git a/tools/aapt2/xml/XmlUtil_test.cpp b/tools/aapt2/xml/XmlUtil_test.cpp
index 7796b3e..319e770 100644
--- a/tools/aapt2/xml/XmlUtil_test.cpp
+++ b/tools/aapt2/xml/XmlUtil_test.cpp
@@ -33,22 +33,22 @@
             xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/res/a");
     AAPT_ASSERT_TRUE(p);
     EXPECT_EQ(std::u16string(u"a"), p.value().package);
-    EXPECT_EQ(false, p.value().privateNamespace);
+    EXPECT_FALSE(p.value().privateNamespace);
 
     p = xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/prv/res/android");
     AAPT_ASSERT_TRUE(p);
     EXPECT_EQ(std::u16string(u"android"), p.value().package);
-    EXPECT_EQ(true, p.value().privateNamespace);
+    EXPECT_TRUE(p.value().privateNamespace);
 
     p = xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/prv/res/com.test");
     AAPT_ASSERT_TRUE(p);
     EXPECT_EQ(std::u16string(u"com.test"), p.value().package);
-    EXPECT_EQ(true, p.value().privateNamespace);
+    EXPECT_TRUE(p.value().privateNamespace);
 
     p = xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/res-auto");
     AAPT_ASSERT_TRUE(p);
     EXPECT_EQ(std::u16string(), p.value().package);
-    EXPECT_EQ(true, p.value().privateNamespace);
+    EXPECT_TRUE(p.value().privateNamespace);
 }
 
 } // namespace aapt
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index f5938cf..265ebd1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -423,21 +423,13 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_offset(long nPath, float dx, float dy, long dst_path) {
+    /*package*/ static void native_offset(long nPath, float dx, float dy) {
         Path_Delegate pathDelegate = sManager.getDelegate(nPath);
         if (pathDelegate == null) {
             return;
         }
 
-        // could be null if the int is 0;
-        Path_Delegate dstDelegate = sManager.getDelegate(dst_path);
-
-        pathDelegate.offset(dx, dy, dstDelegate);
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static void native_offset(long nPath, float dx, float dy) {
-        native_offset(nPath, dx, dy, 0);
+        pathDelegate.offset(dx, dy);
     }
 
     @LayoutlibDelegate
@@ -860,21 +852,14 @@
      *
      * @param dx  The amount in the X direction to offset the entire path
      * @param dy  The amount in the Y direction to offset the entire path
-     * @param dst The translated path is written here. If this is null, then
-     *            the original path is modified.
      */
-    public void offset(float dx, float dy, Path_Delegate dst) {
+    public void offset(float dx, float dy) {
         GeneralPath newPath = new GeneralPath();
 
         PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy));
 
         newPath.append(iterator, false /*connect*/);
-
-        if (dst != null) {
-            dst.mPath = newPath;
-        } else {
-            mPath = newPath;
-        }
+        mPath = newPath;
     }
 
     /**
diff --git a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
index 01af669..381eb1f 100644
--- a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java
@@ -15,8 +15,11 @@
  */
 package android.view;
 
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
+import java.lang.reflect.Field;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
@@ -64,4 +67,18 @@
 
         thisChoreographer.doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
     }
+
+    public static void dispose() {
+        try {
+            Field threadInstanceField = Choreographer.class.getDeclaredField("sThreadInstance");
+            threadInstanceField.setAccessible(true);
+            @SuppressWarnings("unchecked") ThreadLocal<Choreographer> threadInstance =
+                    (ThreadLocal<Choreographer>) threadInstanceField.get(null);
+            threadInstance.remove();
+        } catch (ReflectiveOperationException e) {
+            assert false;
+            Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                    "Unable to clear Choreographer memory.", e, null);
+        }
+    }
 }
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 7faee1b..f9e008e 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -403,8 +403,15 @@
     }
 
     @Override
-    public void setNewConfiguration(Configuration arg0) throws RemoteException {
+    public int[] setNewConfiguration(Configuration arg0) throws RemoteException {
         // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Rect getBoundsForNewConfiguration(int stackId) throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
     }
 
     @Override
diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
index 30512aa..ea9a255 100644
--- a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
+++ b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
@@ -44,6 +44,11 @@
     private static final float PERPENDICULAR_ANGLE = 90f;
 
     public static void paintShadow(Outline viewOutline, float elevation, Canvas canvas) {
+        Rect outline = new Rect();
+        if (!viewOutline.getRect(outline)) {
+            throw new IllegalArgumentException("Outline is not a rect shadow");
+        }
+
         float shadowSize = elevationToShadow(elevation);
         int saved = modifyCanvas(canvas, shadowSize);
         if (saved == -1) {
@@ -54,8 +59,7 @@
             cornerPaint.setStyle(Style.FILL);
             Paint edgePaint = new Paint(cornerPaint);
             edgePaint.setAntiAlias(false);
-            Rect outline = viewOutline.mRect;
-            float radius = viewOutline.mRadius;
+            float radius = viewOutline.getRadius();
             float outerArcRadius = radius + shadowSize;
             int[] colors = {START_COLOR, START_COLOR, END_COLOR};
             cornerPaint.setShader(new RadialGradient(0, 0, outerArcRadius, colors,
diff --git a/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java b/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java
index 1465f50..24f7887 100644
--- a/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java
@@ -55,7 +55,7 @@
     private String mName;
 
     @LayoutlibDelegate
-    /*package*/ static long nCreate(String name) {
+    /*package*/ static long nCreate(RenderNode thisRenderNode, String name) {
         RenderNode_Delegate renderNodeDelegate = new RenderNode_Delegate();
         renderNodeDelegate.mName = name;
         return sManager.addNewDelegate(renderNodeDelegate);
diff --git a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
index 51d32e3..23caaf8 100644
--- a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
@@ -64,7 +64,7 @@
     private static void drawShadow(ViewGroup parent, Canvas canvas, View child,
             Outline outline) {
         float elevation = getElevation(child, parent);
-        if(outline.mRect != null) {
+        if(outline.mMode == Outline.MODE_ROUND_RECT && outline.mRect != null) {
             RectShadowPainter.paintShadow(outline, elevation, canvas);
             return;
         }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index c8e3d03..9e50ee8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -24,6 +24,7 @@
 import com.android.ide.common.rendering.api.Result;
 import com.android.ide.common.rendering.api.Result.Status;
 import com.android.ide.common.rendering.api.SessionParams;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
 import com.android.layoutlib.bridge.impl.RenderDrawable;
 import com.android.layoutlib.bridge.impl.RenderSessionImpl;
 import com.android.layoutlib.bridge.util.DynamicIdMap;
@@ -408,7 +409,9 @@
     /**
      * Starts a layout session by inflating and rendering it. The method returns a
      * {@link RenderSession} on which further actions can be taken.
-     *
+     * <p/>
+     * If {@link SessionParams} includes the {@link RenderParamsFlags#FLAG_DO_NOT_RENDER_ON_CREATE},
+     * this method will only inflate the layout but will NOT render it.
      * @param params the {@link SessionParams} object with all the information necessary to create
      *           the scene.
      * @return a new {@link RenderSession} object that contains the result of the layout.
@@ -424,7 +427,10 @@
                 lastResult = scene.init(params.getTimeout());
                 if (lastResult.isSuccess()) {
                     lastResult = scene.inflate();
-                    if (lastResult.isSuccess()) {
+
+                    boolean doNotRenderOnCreate = Boolean.TRUE.equals(
+                            params.getFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE));
+                    if (lastResult.isSuccess() && !doNotRenderOnCreate) {
                         lastResult = scene.render(true /*freshRender*/);
                     }
                 }
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 4161307..89272fa 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
@@ -110,13 +110,13 @@
 public final class BridgeContext extends Context {
 
     /** The map adds cookies to each view so that IDE can link xml tags to views. */
-    private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
+    private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
     /**
      * In some cases, when inflating an xml, some objects are created. Then later, the objects are
      * converted to views. This map stores the mapping from objects to cookies which can then be
      * used to populate the mViewKeyMap.
      */
-    private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<Object, Object>();
+    private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>();
     private final BridgeAssetManager mAssets;
     private Resources mSystemResources;
     private final Object mProjectKey;
@@ -132,8 +132,7 @@
 
     private Resources.Theme mTheme;
 
-    private final Map<Object, Map<String, String>> mDefaultPropMaps =
-        new IdentityHashMap<Object, Map<String,String>>();
+    private final Map<Object, PropertiesMap> mDefaultPropMaps = new IdentityHashMap<>();
 
     // maps for dynamically generated id representing style objects (StyleResourceValue)
     @Nullable
@@ -142,13 +141,12 @@
     private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
 
     // cache for TypedArray generated from StyleResourceValue object
-    private Map<int[], Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>
-            mTypedArrayCache;
+    private TypedArrayCache mTypedArrayCache;
     private BridgeInflater mBridgeInflater;
 
     private BridgeContentResolver mContentResolver;
 
-    private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>();
+    private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>();
     private SharedPreferences mSharedPreferences;
     private ClassLoader mClassLoader;
     private IBinder mBinder;
@@ -162,7 +160,7 @@
      * This a map from value to attribute name. Warning for missing references shouldn't be logged
      * if value and attr name pair is the same as an entry in this map.
      */
-    private static Map<String, String> RTL_ATTRS = new HashMap<String, String>(10);
+    private static Map<String, String> RTL_ATTRS = new HashMap<>(10);
 
     static {
         RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart");
@@ -325,11 +323,11 @@
         return mParserStack.get(mParserStack.size() - 2);
     }
 
-    public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
-        Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid);
+    public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) {
+        Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resId);
         boolean isFrameworkRes = true;
         if (resourceInfo == null) {
-            resourceInfo = mLayoutlibCallback.resolveResourceId(resid);
+            resourceInfo = mLayoutlibCallback.resolveResourceId(resId);
             isFrameworkRes = false;
         }
 
@@ -602,23 +600,20 @@
 
     @Override
     public final BridgeTypedArray obtainStyledAttributes(int[] attrs) {
-        // No style is specified here, so create the typed array based on the default theme
-        // and the styles already applied to it. A null value of style indicates that the default
-        // theme should be used.
-        return createStyleBasedTypedArray(null, attrs);
+        return obtainStyledAttributes(0, attrs);
     }
 
     @Override
-    public final BridgeTypedArray obtainStyledAttributes(int resid, int[] attrs)
+    public final BridgeTypedArray obtainStyledAttributes(int resId, int[] attrs)
             throws Resources.NotFoundException {
         StyleResourceValue style = null;
         // get the StyleResourceValue based on the resId;
-        if (resid != 0) {
-            style = getStyleByDynamicId(resid);
+        if (resId != 0) {
+            style = getStyleByDynamicId(resId);
 
             if (style == null) {
                 // In some cases, style may not be a dynamic id, so we do a full search.
-                ResourceReference ref = resolveId(resid);
+                ResourceReference ref = resolveId(resId);
                 if (ref != null) {
                     style = mRenderResources.getStyle(ref.getName(), ref.isFramework());
                 }
@@ -629,41 +624,34 @@
             }
         }
 
-        // The map is from
-        // attrs (int[]) -> context's current themes (List<StyleRV>) -> resid (int) -> typed array.
         if (mTypedArrayCache == null) {
-            mTypedArrayCache = new IdentityHashMap<int[],
-                    Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>();
+            mTypedArrayCache = new TypedArrayCache();
         }
 
-        // get the 2nd map
-        Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>> map2 =
-                mTypedArrayCache.get(attrs);
-        if (map2 == null) {
-            map2 = new HashMap<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>();
-            mTypedArrayCache.put(attrs, map2);
-        }
-
-        // get the 3rd map
         List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes();
-        Map<Integer, BridgeTypedArray> map3 = map2.get(currentThemes);
-        if (map3 == null) {
-            map3 = new HashMap<Integer, BridgeTypedArray>();
-            // Create a copy of the list before adding it to the map. This allows reusing the
-            // existing list.
-            currentThemes = new ArrayList<StyleResourceValue>(currentThemes);
-            map2.put(currentThemes, map3);
+
+        Pair<BridgeTypedArray, PropertiesMap> typeArrayAndPropertiesPair =
+                mTypedArrayCache.get(attrs, currentThemes, resId);
+
+        if (typeArrayAndPropertiesPair == null) {
+            typeArrayAndPropertiesPair = createStyleBasedTypedArray(style, attrs);
+            mTypedArrayCache.put(attrs, currentThemes, resId, typeArrayAndPropertiesPair);
         }
-
-        // get the array from the 3rd map
-        BridgeTypedArray ta = map3.get(resid);
-
-        if (ta == null) {
-            ta = createStyleBasedTypedArray(style, attrs);
-            map3.put(resid, ta);
+        // Add value to defaultPropsMap if needed
+        if (typeArrayAndPropertiesPair.getSecond() != null) {
+            BridgeXmlBlockParser parser = getCurrentParser();
+            Object key = parser != null ? parser.getViewCookie() : null;
+            if (key != null) {
+                PropertiesMap defaultPropMap = mDefaultPropMaps.get(key);
+                if (defaultPropMap == null) {
+                    defaultPropMap = typeArrayAndPropertiesPair.getSecond();
+                    mDefaultPropMaps.put(key, defaultPropMap);
+                } else {
+                    defaultPropMap.putAll(typeArrayAndPropertiesPair.getSecond());
+                }
+            }
         }
-
-        return ta;
+        return typeArrayAndPropertiesPair.getFirst();
     }
 
     @Override
@@ -675,7 +663,7 @@
     public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
             int defStyleAttr, int defStyleRes) {
 
-        Map<String, String> defaultPropMap = null;
+        PropertiesMap defaultPropMap = null;
         boolean isPlatformFile = true;
 
         // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
@@ -689,7 +677,7 @@
             if (key != null) {
                 defaultPropMap = mDefaultPropMaps.get(key);
                 if (defaultPropMap == null) {
-                    defaultPropMap = new HashMap<String, String>();
+                    defaultPropMap = new PropertiesMap();
                     mDefaultPropMaps.put(key, defaultPropMap);
                 }
             }
@@ -937,32 +925,33 @@
      *
      * @see #obtainStyledAttributes(int, int[])
      */
-    private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style,
-            int[] attrs) throws Resources.NotFoundException {
-
+    private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray(
+            @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
         List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
 
-        BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length,
-                false);
+        BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
 
+        PropertiesMap defaultPropMap = new PropertiesMap();
         // for each attribute, get its name so that we can search it in the style
-        for (int i = 0 ; i < attrs.length ; i++) {
+        for (int i = 0; i < attrs.length; i++) {
             Pair<String, Boolean> attribute = attributes.get(i);
 
             if (attribute != null) {
                 // look for the value in the given style
                 ResourceValue resValue;
+                String attrName = attribute.getFirst();
                 if (style != null) {
-                    resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(),
+                    resValue = mRenderResources.findItemInStyle(style, attrName,
                             attribute.getSecond());
                 } else {
-                    resValue = mRenderResources.findItemInTheme(attribute.getFirst(),
-                            attribute.getSecond());
+                    resValue = mRenderResources.findItemInTheme(attrName, attribute.getSecond());
                 }
 
                 if (resValue != null) {
+                    // Add it to defaultPropMap before resolving
+                    defaultPropMap.put(attrName, resValue.getValue());
                     // resolve it to make sure there are no references left.
-                    ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(),
+                    ta.bridgeSetValue(i, attrName, attribute.getSecond(),
                             mRenderResources.resolveResValue(resValue));
                 }
             }
@@ -970,7 +959,7 @@
 
         ta.sealArray();
 
-        return ta;
+        return Pair.of(ta, defaultPropMap);
     }
 
     /**
@@ -982,7 +971,7 @@
      * @return List of attribute information.
      */
     private List<Pair<String, Boolean>> searchAttrs(int[] attrs) {
-        List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length);
+        List<Pair<String, Boolean>> results = new ArrayList<>(attrs.length);
 
         // for each attribute, get its name so that we can search it in the style
         for (int attr : attrs) {
@@ -1011,7 +1000,7 @@
      * @return A (name, isFramework) pair describing the attribute if found. Returns null
      *         if nothing is found.
      */
-    public Pair<String, Boolean> searchAttr(int attr) {
+    private Pair<String, Boolean> searchAttr(int attr) {
         Pair<ResourceType, String> info = Bridge.resolveResourceId(attr);
         if (info != null) {
             return Pair.of(info.getSecond(), Boolean.TRUE);
@@ -1028,8 +1017,8 @@
     public int getDynamicIdByStyle(StyleResourceValue resValue) {
         if (mDynamicIdToStyleMap == null) {
             // create the maps.
-            mDynamicIdToStyleMap = new HashMap<Integer, StyleResourceValue>();
-            mStyleToDynamicIdMap = new HashMap<StyleResourceValue, Integer>();
+            mDynamicIdToStyleMap = new HashMap<>();
+            mStyleToDynamicIdMap = new HashMap<>();
         }
 
         // look for an existing id
@@ -1868,4 +1857,69 @@
     public boolean isCredentialProtectedStorage() {
         return false;
     }
+
+
+    /**
+     * The cached value depends on
+     * <ol>
+     * <li>{@code int[]}: the attributes for which TypedArray is created </li>
+     * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of
+     * creation of the TypedArray</li>
+     * <li>{@code Integer}: the default style used at the time of creation</li>
+     * </ol>
+     *
+     * The class is created by using nested maps resolving one dependency at a time.
+     * <p/>
+     * The final value of the nested maps is a pair of the typed array and a map of properties
+     * that should be added to {@link #mDefaultPropMaps}, if needed.
+     */
+    private static class TypedArrayCache {
+
+        private Map<int[],
+                Map<List<StyleResourceValue>,
+                        Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache;
+
+        public TypedArrayCache() {
+            mCache = new IdentityHashMap<>();
+        }
+
+        public Pair<BridgeTypedArray, PropertiesMap> get(int[] attrs,
+                List<StyleResourceValue> themes, int resId) {
+            Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
+                    cacheFromThemes = mCache.get(attrs);
+            if (cacheFromThemes != null) {
+                Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
+                        cacheFromThemes.get(themes);
+                if (cacheFromResId != null) {
+                    return cacheFromResId.get(resId);
+                }
+            }
+            return null;
+        }
+
+        public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
+                Pair<BridgeTypedArray, PropertiesMap> value) {
+            Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
+                    cacheFromThemes = mCache.get(attrs);
+            if (cacheFromThemes == null) {
+                cacheFromThemes = new HashMap<>();
+                mCache.put(attrs, cacheFromThemes);
+            }
+            Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
+                    cacheFromThemes.get(themes);
+            if (cacheFromResId == null) {
+                cacheFromResId = new HashMap<>();
+                cacheFromThemes.put(themes, cacheFromResId);
+            }
+            cacheFromResId.put(resId, value);
+        }
+
+    }
+
+    /**
+     * An alias used for the value in {@code {@link #mDefaultPropMaps}}
+     */
+    private static class PropertiesMap extends HashMap<String, String> {
+    }
+
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
index bd17a2f..051de90 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
@@ -53,6 +53,12 @@
      */
     public static final Key<Boolean> FLAG_KEY_XML_FILE_PARSER_SUPPORT =
             new Key<Boolean>("xmlFileParser", Boolean.class);
+    /**
+     * To tell LayoutLib to not render when creating a new session. This allows controlling when the first
+     * layout rendering will happen.
+     */
+    public static final Key<Boolean> FLAG_DO_NOT_RENDER_ON_CREATE =
+            new Key<Boolean>("doNotRenderOnCreate", Boolean.class);
 
     // Disallow instances.
     private RenderParamsFlags() {}
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 016825a..866b248 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
@@ -267,6 +267,34 @@
     }
 
     /**
+     * Renders the given view hierarchy to the passed canvas and returns the result of the render
+     * operation.
+     * @param canvas an optional canvas to render the views to. If null, only the measure and
+     * layout steps will be executed.
+     */
+    private static Result render(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot,
+            @Nullable Canvas canvas, int width, int height) {
+        // measure again with the size we need
+        // This must always be done before the call to layout
+        measureView(viewRoot, null /*measuredView*/,
+                width, MeasureSpec.EXACTLY,
+                height, MeasureSpec.EXACTLY);
+
+        // now do the layout.
+        viewRoot.layout(0, 0, width, height);
+        handleScrolling(context, viewRoot);
+
+        if (canvas == null) {
+            return SUCCESS.createResult();
+        }
+
+        AttachInfo_Accessor.dispatchOnPreDraw(viewRoot);
+        viewRoot.draw(canvas);
+
+        return SUCCESS.createResult();
+    }
+
+    /**
      * Renders the scene.
      * <p>
      * {@link #acquire(long)} must have been called before this.
@@ -367,24 +395,12 @@
                 }
             }
 
-            // measure again with the size we need
-            // This must always be done before the call to layout
-            measureView(mViewRoot, null /*measuredView*/,
-                    mMeasuredScreenWidth, MeasureSpec.EXACTLY,
-                    mMeasuredScreenHeight, MeasureSpec.EXACTLY);
-
-            // now do the layout.
-            mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
-
-            handleScrolling(mViewRoot);
-
+            Result renderResult = SUCCESS.createResult();
             if (params.isLayoutOnly()) {
                 // delete the canvas and image to reset them on the next full rendering
                 mImage = null;
                 mCanvas = null;
             } else {
-                AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
-
                 // draw the views
                 // create the BufferedImage into which the layout will be rendered.
                 boolean newImage = false;
@@ -446,6 +462,9 @@
                 if (mElapsedFrameTimeNanos >= 0) {
                     long initialTime = System_Delegate.nanoTime();
                     if (!mFirstFrameExecuted) {
+                        // We need to run an initial draw call to initialize the animations
+                        render(getContext(), mViewRoot, mCanvas, 0, 0);
+
                         // The first frame will initialize the animations
                         Choreographer_Delegate.doFrame(initialTime);
                         mFirstFrameExecuted = true;
@@ -453,14 +472,15 @@
                     // Second frame will move the animations
                     Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos);
                 }
-                mViewRoot.draw(mCanvas);
+                renderResult = render(getContext(), mViewRoot, mCanvas, mMeasuredScreenWidth,
+                        mMeasuredScreenHeight);
             }
 
             mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
                     false);
 
             // success!
-            return SUCCESS.createResult();
+            return renderResult;
         } catch (Throwable e) {
             // get the real cause of the exception.
             Throwable t = e;
@@ -488,7 +508,7 @@
      * @return the measured width/height if measuredView is non-null, null otherwise.
      */
     @SuppressWarnings("deprecation")  // For the use of Pair
-    private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
+    private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
             int width, int widthMode, int height, int heightMode) {
         int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
         int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
@@ -1061,8 +1081,7 @@
      * the component supports nested scrolling attempt that first, then use the unconsumed scroll
      * part to scroll the content in the component.
      */
-    private void handleScrolling(View view) {
-        BridgeContext context = getContext();
+    private static void handleScrolling(BridgeContext context, View view) {
         int scrollPosX = context.getScrollXPos(view);
         int scrollPosY = context.getScrollYPos(view);
         if (scrollPosX != 0 || scrollPosY != 0) {
@@ -1080,7 +1099,7 @@
                 }
             }
             if (scrollPosX != 0 || scrollPosY != 0) {
-                view.scrollBy(scrollPosX, scrollPosY);
+                view.scrollTo(scrollPosX, scrollPosY);
             }
         }
 
@@ -1090,7 +1109,7 @@
         ViewGroup group = (ViewGroup) view;
         for (int i = 0; i < group.getChildCount(); i++) {
             View child = group.getChildAt(i);
-            handleScrolling(child);
+            handleScrolling(context, child);
         }
     }
 
@@ -1434,6 +1453,7 @@
 
         if (createdLooper) {
             Bridge.cleanupThread();
+            Choreographer_Delegate.dispose();
         }
     }
 }
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index d8ead23..0e788e0c 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
index 65d1dc5..bad296b 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
index 2da2cb9..adb58a3 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
@@ -197,6 +197,14 @@
         android:inputType="numberPassword"
         android:text="numeric password" />
 
+    <ToggleButton
+        android:id="@+id/toggleButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignTop="@id/editText4"
+        android:layout_toEndOf="@id/editText4"
+        android:text="New ToggleButton" />
+
     <EditText
         android:id="@id/editText5"
         android:layout_width="wrap_content"
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml
index a5ebc2e..a07498c 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml
@@ -2,8 +2,8 @@
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:orientation="vertical"
-              android:scrollX="10px"
-              android:scrollY="30px">
+              android:scrollX="30px"
+              android:scrollY="90px">
     <LinearLayout
         android:layout_width="60dp"
         android:layout_height="60dp"
@@ -29,8 +29,8 @@
         android:layout_width="200dp"
         android:layout_height="400dp"
         android:orientation="vertical"
-        android:scrollX="-30px"
-        android:scrollY="150px">
+        android:scrollX="-90px"
+        android:scrollY="450px">
         <LinearLayout
             android:layout_width="fill_parent"
             android:layout_height="60dp"
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 09dd5f0..8f570ae 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
@@ -30,8 +30,9 @@
 import com.android.io.FolderWrapper;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.RenderAction;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
 import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.RenderAction;
 import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
 import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback;
 import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
@@ -41,8 +42,12 @@
 import com.android.utils.ILogger;
 
 import org.junit.AfterClass;
+import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -55,9 +60,12 @@
 import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.concurrent.TimeUnit;
 
+import com.google.android.collect.Lists;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -104,6 +112,21 @@
     private static  ILogger sLogger;
     private static Bridge sBridge;
 
+    /** List of log messages generated by a render call. It can be used to find specific errors */
+    private static ArrayList<String> sRenderMessages = Lists.newArrayList();
+
+    @Rule
+    public static TestWatcher sRenderMessageWatcher = new TestWatcher() {
+        @Override
+        protected void succeeded(Description description) {
+            // We only check error messages if the rest of the test case was successful.
+            if (!sRenderMessages.isEmpty()) {
+                fail(description.getMethodName() + " render error message: " + sRenderMessages.get
+                        (0));
+            }
+        }
+    };
+
     static {
         // Test that System Properties are properly set.
         PLATFORM_DIR = getPlatformDir();
@@ -278,6 +301,11 @@
                 ConfigGenerator.getEnumMap(attrs), getLayoutLog());
     }
 
+    @Before
+    public void beforeTestCase() {
+        sRenderMessages.clear();
+    }
+
     /** Test activity.xml */
     @Test
     public void testActivity() throws ClassNotFoundException {
@@ -288,6 +316,9 @@
     @Test
     public void testAllWidgets() throws ClassNotFoundException {
         renderAndVerify("allwidgets.xml", "allwidgets.png");
+
+        // We expect fidelity warnings for Path.isConvex. Fail for anything else.
+        sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported."));
     }
 
     @Test
@@ -298,6 +329,9 @@
     @Test
     public void testAllWidgetsTablet() throws ClassNotFoundException {
         renderAndVerify("allwidgets.xml", "allwidgets_tab.png", ConfigGenerator.NEXUS_7_2012);
+
+        // We expect fidelity warnings for Path.isConvex. Fail for anything else.
+        sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported."));
     }
 
     private static void gc() {
@@ -564,7 +598,7 @@
                         sFrameworkRepo.getConfiguredResources(config),
                         themeName, isProjectTheme);
 
-        return new SessionParams(
+        SessionParams sessionParams = new SessionParams(
                 layoutParser,
                 renderingMode,
                 null /*used for caching*/,
@@ -574,6 +608,8 @@
                 0,
                 targetSdk,
                 getLayoutLog());
+        sessionParams.setFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true);
+        return sessionParams;
     }
 
     private static LayoutLog getLayoutLog() {
@@ -646,6 +682,6 @@
     }
 
     private static void failWithMsg(@NonNull String msgFormat, Object... args) {
-        fail(args == null ? "" : String.format(msgFormat, args));
+        sRenderMessages.add(args == null ? msgFormat : String.format(msgFormat, args));
     }
 }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 1c7a308..0f84506 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -149,12 +149,11 @@
     void setAllowScansWithTraffic(int enabled);
     int getAllowScansWithTraffic();
 
-    void setHalBasedAutojoinOffload(int enabled);
-    int getHalBasedAutojoinOffload();
-
     boolean enableAutoJoinWhenAssociated(boolean enabled);
     boolean getEnableAutoJoinWhenAssociated();
 
+    void enableWifiConnectivityManager(boolean enabled);
+
     WifiConnectionStatistics getConnectionStatistics();
 
     void disableEphemeralNetwork(String SSID);
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 9e15d60..394934f 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -719,7 +719,7 @@
      * Get CA certificates.
      */
     @Nullable public X509Certificate[] getCaCertificates() {
-        if (mCaCerts != null || mCaCerts.length > 0) {
+        if (mCaCerts != null && mCaCerts.length > 0) {
             return mCaCerts;
         } else {
             return null;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 8c1fbc3..6984fe2 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -28,7 +28,6 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
@@ -43,7 +42,6 @@
 import com.android.server.net.NetworkPinner;
 
 import java.net.InetAddress;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 
@@ -2721,25 +2719,14 @@
             throw e.rethrowFromSystemServer();
         }
     }
-    /**
-     * Set setting for enabling autojoin Offload thru Wifi HAL layer
-     * @hide
-     */
-    public void setHalBasedAutojoinOffload(int enabled) {
-        try {
-            mService.setHalBasedAutojoinOffload(enabled);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
 
     /**
-     * Get setting for enabling autojoin Offload thru Wifi HAL layer
+     * Enable/disable WifiConnectivityManager
      * @hide
      */
-    public int getHalBasedAutojoinOffload() {
+    public void enableWifiConnectivityManager(boolean enabled) {
         try {
-            return mService.getHalBasedAutojoinOffload();
+            mService.enableWifiConnectivityManager(enabled);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 73ddbbc..f8c1ea3 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -810,19 +810,17 @@
     }
     /**
      * 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) {
+    public void stopPnoScan(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);
+        sAsyncChannel.sendMessage(CMD_STOP_PNO_SCAN, 0, key);
     }
 
     /** specifies information about an access point of interest */