Merge "Add flag to "am start" to enable native debugging"
diff --git a/Android.mk b/Android.mk
index ad164e20..6ec434c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -136,6 +136,7 @@
 	core/java/android/content/ISyncStatusObserver.aidl \
 	core/java/android/content/pm/ILauncherApps.aidl \
 	core/java/android/content/pm/IOnAppsChangedListener.aidl \
+	core/java/android/content/pm/IOtaDexopt.aidl \
 	core/java/android/content/pm/IPackageDataObserver.aidl \
 	core/java/android/content/pm/IPackageDeleteObserver.aidl \
 	core/java/android/content/pm/IPackageDeleteObserver2.aidl \
@@ -335,8 +336,8 @@
 	location/java/android/location/IGeofenceProvider.aidl \
 	location/java/android/location/IGnssStatusListener.aidl \
 	location/java/android/location/IGnssStatusProvider.aidl \
-	location/java/android/location/IGpsMeasurementsListener.aidl \
-	location/java/android/location/IGpsNavigationMessageListener.aidl \
+	location/java/android/location/IGnssMeasurementsListener.aidl \
+	location/java/android/location/IGnssNavigationMessageListener.aidl \
 	location/java/android/location/ILocationListener.aidl \
 	location/java/android/location/ILocationManager.aidl \
 	location/java/android/location/IFusedGeofenceHardware.aidl \
@@ -519,7 +520,7 @@
 	frameworks/base/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl \
 	frameworks/base/wifi/java/android/net/wifi/WpsInfo.aidl \
 	frameworks/base/wifi/java/android/net/wifi/ScanResult.aidl \
-        frameworks/base/wifi/java/android/net/wifi/ScanInfo.aidl \
+	frameworks/base/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.aidl \
 	frameworks/base/wifi/java/android/net/wifi/WifiEnterpriseConfig.aidl \
 	frameworks/base/wifi/java/android/net/wifi/WifiConfiguration.aidl \
 	frameworks/base/wifi/java/android/net/wifi/WifiInfo.aidl \
@@ -1192,6 +1193,11 @@
 
 LOCAL_DX_FLAGS := --core-library
 
+ifneq ($(INCREMENTAL_BUILDS),)
+    LOCAL_PROGUARD_ENABLED := disabled
+    LOCAL_JACK_ENABLED := incremental
+endif
+
 include $(BUILD_JAVA_LIBRARY)
 
 
diff --git a/api/current.txt b/api/current.txt
index dfc561d..5c0628c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28,7 +28,6 @@
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
-    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -68,7 +67,7 @@
     field public static final java.lang.String DUMP = "android.permission.DUMP";
     field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
     field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
-    field public static final deprecated java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
+    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 deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";
@@ -198,6 +197,7 @@
 
   public static final class R.attr {
     ctor public R.attr();
+    field public static final int abiOverride = 16844054; // 0x1010516
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -305,6 +305,7 @@
     field public static final int baselineAlignBottom = 16843042; // 0x1010122
     field public static final int baselineAligned = 16843046; // 0x1010126
     field public static final int baselineAlignedChildIndex = 16843047; // 0x1010127
+    field public static final int bitmap = 16844055; // 0x1010517
     field public static final int borderlessButtonStyle = 16843563; // 0x101032b
     field public static final int bottom = 16843184; // 0x10101b0
     field public static final int bottomBright = 16842957; // 0x10100cd
@@ -646,6 +647,8 @@
     field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
     field public static final int horizontalSpacing = 16843028; // 0x1010114
     field public static final int host = 16842792; // 0x1010028
+    field public static final int hotSpotX = 16844056; // 0x1010518
+    field public static final int hotSpotY = 16844057; // 0x1010519
     field public static final int hyphenationFrequency = 16843998; // 0x10104de
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
@@ -3408,7 +3411,7 @@
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
-    method public void enterPictureInPictureMode();
+    method public void enterPictureInPicture();
     method public android.view.View findViewById(int);
     method public void finish();
     method public void finishActivity(int);
@@ -3448,8 +3451,8 @@
     method public android.view.Window getWindow();
     method public android.view.WindowManager getWindowManager();
     method public boolean hasWindowFocus();
-    method public boolean inMultiWindowMode();
-    method public boolean inPictureInPictureMode();
+    method public boolean inMultiWindow();
+    method public boolean inPictureInPicture();
     method public void invalidateOptionsMenu();
     method public boolean isChangingConfigurations();
     method public final boolean isChild();
@@ -3503,7 +3506,7 @@
     method public void onLowMemory();
     method public boolean onMenuItemSelected(int, android.view.MenuItem);
     method public boolean onMenuOpened(int, android.view.Menu);
-    method public void onMultiWindowModeChanged(boolean);
+    method public void onMultiWindowChanged(boolean);
     method public boolean onNavigateUp();
     method public boolean onNavigateUpFromChild(android.app.Activity);
     method protected void onNewIntent(android.content.Intent);
@@ -3511,7 +3514,7 @@
     method public void onOptionsMenuClosed(android.view.Menu);
     method public void onPanelClosed(int, android.view.Menu);
     method protected void onPause();
-    method public void onPictureInPictureModeChanged(boolean);
+    method public void onPictureInPictureChanged(boolean);
     method protected void onPostCreate(android.os.Bundle);
     method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
     method protected void onPostResume();
@@ -4422,9 +4425,11 @@
     method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
     method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
     method public void onLowMemory();
+    method public void onMultiWindowChanged(boolean);
     method public boolean onOptionsItemSelected(android.view.MenuItem);
     method public void onOptionsMenuClosed(android.view.Menu);
     method public void onPause();
+    method public void onPictureInPictureChanged(boolean);
     method public void onPrepareOptionsMenu(android.view.Menu);
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method public void onResume();
@@ -4505,9 +4510,11 @@
     method public void dispatchDestroy();
     method public void dispatchDestroyView();
     method public void dispatchLowMemory();
+    method public void dispatchMultiWindowChanged(boolean);
     method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
     method public void dispatchOptionsMenuClosed(android.view.Menu);
     method public void dispatchPause();
+    method public void dispatchPictureInPictureChanged(boolean);
     method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
     method public void dispatchResume();
     method public void dispatchStart();
@@ -5705,6 +5712,7 @@
     method public static android.app.WallpaperManager getInstance(android.content.Context);
     method public android.app.WallpaperInfo getWallpaperInfo();
     method public boolean hasResourceWallpaper(int);
+    method public boolean isWallpaperSettingAllowed();
     method public boolean isWallpaperSupported();
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
@@ -6314,6 +6322,22 @@
     field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
   }
 
+  public class DataUsagePolicy {
+    field public final int networkType;
+    field public final java.lang.String[] subscriberIds;
+    field public final long thresholdInBytes;
+    field public final int[] uids;
+  }
+
+  public static class DataUsagePolicy.Builder {
+    ctor public DataUsagePolicy.Builder();
+    method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
+    method public android.app.usage.DataUsagePolicy.Builder addUid(int);
+    method public android.app.usage.DataUsagePolicy build();
+    method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
+    method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
+  }
+
   public final class NetworkStats implements java.lang.AutoCloseable {
     method public void close();
     method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
@@ -6328,6 +6352,7 @@
     method public long getRxPackets();
     method public long getStartTimeStamp();
     method public int getState();
+    method public int getTag();
     method public long getTxBytes();
     method public long getTxPackets();
     method public int getUid();
@@ -6337,6 +6362,8 @@
     field public static final int STATE_ALL = -1; // 0xffffffff
     field public static final int STATE_DEFAULT = 1; // 0x1
     field public static final int STATE_FOREGROUND = 2; // 0x2
+    field public static final int TAG_ALL = 0; // 0x0
+    field public static final int TAG_ANY = -1; // 0xffffffff
     field public static final int UID_ALL = -1; // 0xffffffff
     field public static final int UID_REMOVED = -4; // 0xfffffffc
     field public static final int UID_TETHERING = -5; // 0xfffffffb
@@ -6345,9 +6372,20 @@
   public class NetworkStatsManager {
     method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
+    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback);
+    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
+    method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
+  }
+
+  public static class NetworkStatsManager.DataUsageCallback {
+    ctor public NetworkStatsManager.DataUsageCallback();
+    method public void onLimitReached();
   }
 
   public final class UsageEvents implements android.os.Parcelable {
@@ -7870,6 +7908,7 @@
     field public static final java.lang.String SYNC_EXTRAS_INITIALIZE = "initialize";
     field public static final java.lang.String SYNC_EXTRAS_MANUAL = "force";
     field public static final java.lang.String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
+    field public static final java.lang.String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging";
     field public static final java.lang.String SYNC_EXTRAS_UPLOAD = "upload";
     field public static final int SYNC_OBSERVER_TYPE_ACTIVE = 4; // 0x4
     field public static final int SYNC_OBSERVER_TYPE_PENDING = 2; // 0x2
@@ -8048,6 +8087,7 @@
     field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10
     field public static final int BIND_AUTO_CREATE = 1; // 0x1
     field public static final int BIND_DEBUG_UNBIND = 2; // 0x2
+    field public static final int BIND_EXTERNAL_SERVICE = -2147483648; // 0x80000000
     field public static final int BIND_IMPORTANT = 64; // 0x40
     field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
     field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20
@@ -9060,6 +9100,7 @@
     method public android.content.SyncRequest.Builder setIgnoreSettings(boolean);
     method public android.content.SyncRequest.Builder setManual(boolean);
     method public android.content.SyncRequest.Builder setNoRetry(boolean);
+    method public android.content.SyncRequest.Builder setRequiresCharging(boolean);
     method public android.content.SyncRequest.Builder setSyncAdapter(android.accounts.Account, java.lang.String);
     method public android.content.SyncRequest.Builder syncOnce();
     method public android.content.SyncRequest.Builder syncPeriodic(long, long);
@@ -9730,6 +9771,7 @@
     field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
     field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
     field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
+    field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
     field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
     field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
     field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
@@ -9901,6 +9943,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     field public static final android.os.Parcelable.Creator<android.content.pm.ServiceInfo> CREATOR;
+    field public static final int FLAG_EXTERNAL_SERVICE = 4; // 0x4
     field public static final int FLAG_ISOLATED_PROCESS = 2; // 0x2
     field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
     field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1
@@ -19101,38 +19144,7 @@
     method public static boolean isPresent();
   }
 
-  public abstract interface GnssNmeaListener {
-    method public abstract void onNmeaReceived(long, java.lang.String);
-  }
-
-  public final class GnssStatus {
-    method public float getAzimuth(int);
-    method public int getConstellationType(int);
-    method public float getElevation(int);
-    method public int getNumSatellites();
-    method public int getPrn(int);
-    method public float getSnr(int);
-    method public boolean hasAlmanac(int);
-    method public boolean hasEphemeris(int);
-    method public boolean usedInFix(int);
-    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
-    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
-    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
-    field public static final int CONSTELLATION_GPS = 1; // 0x1
-    field public static final int CONSTELLATION_QZSS = 4; // 0x4
-    field public static final int CONSTELLATION_SBAS = 2; // 0x2
-    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
-  }
-
-  public 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 final class GpsClock implements android.os.Parcelable {
+  public final class GnssClock implements android.os.Parcelable {
     method public int describeContents();
     method public double getBiasInNs();
     method public double getBiasUncertaintyInNs();
@@ -19159,7 +19171,7 @@
     method public void resetFullBiasInNs();
     method public void resetLeapSecond();
     method public void resetTimeUncertaintyInNs();
-    method public void set(android.location.GpsClock);
+    method public void set(android.location.GnssClock);
     method public void setBiasInNs(double);
     method public void setBiasUncertaintyInNs(double);
     method public void setDriftInNsPerSec(double);
@@ -19174,13 +19186,13 @@
     field public static final byte CLOCK_TYPE_GPS_TIME = 2; // 0x2
     field public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1; // 0x1
     field public static final byte CLOCK_TYPE_UNKNOWN = 0; // 0x0
-    field public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
 
-  public static abstract class GpsClock.GpsClockType implements java.lang.annotation.Annotation {
+  public static abstract class GnssClock.GnssClockType implements java.lang.annotation.Annotation {
   }
 
-  public final class GpsMeasurement implements android.os.Parcelable {
+  public final class GnssMeasurement implements android.os.Parcelable {
     method public int describeContents();
     method public double getAccumulatedDeltaRangeInMeters();
     method public short getAccumulatedDeltaRangeState();
@@ -19251,7 +19263,7 @@
     method public void resetPseudorangeUncertaintyInMeters();
     method public void resetSnrInDb();
     method public void resetTimeFromLastBitInMs();
-    method public void set(android.location.GpsMeasurement);
+    method public void set(android.location.GnssMeasurement);
     method public void setAccumulatedDeltaRangeInMeters(double);
     method public void setAccumulatedDeltaRangeState(short);
     method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
@@ -19290,7 +19302,7 @@
     field public static final short ADR_STATE_RESET = 2; // 0x2
     field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
     field public static final short ADR_STATE_VALID = 1; // 0x1
-    field public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
     field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
     field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
     field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
@@ -19305,34 +19317,34 @@
     field public static final short STATE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GpsMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+  public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
   }
 
-  public static abstract class GpsMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
+  public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
   }
 
-  public final class GpsMeasurementsEvent implements android.os.Parcelable {
-    ctor public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
+  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.GpsClock getClock();
-    method public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
+    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.GpsMeasurementsEvent> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
     field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract class GpsMeasurementsEvent.Callback {
-    ctor public GpsMeasurementsEvent.Callback();
-    method public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
+  public static abstract class GnssMeasurementsEvent.Callback {
+    ctor public GnssMeasurementsEvent.Callback();
+    method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GpsMeasurementsEvent.GpsMeasurementsStatus implements java.lang.annotation.Annotation {
+  public static abstract class GnssMeasurementsEvent.GnssMeasurementsStatus implements java.lang.annotation.Annotation {
   }
 
-  public final class GpsNavigationMessage implements android.os.Parcelable {
+  public final class GnssNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
@@ -19341,7 +19353,7 @@
     method public short getSubmessageId();
     method public byte getType();
     method public void reset();
-    method public void set(android.location.GpsNavigationMessage);
+    method public void set(android.location.GnssNavigationMessage);
     method public void setData(byte[]);
     method public void setMessageId(short);
     method public void setPrn(byte);
@@ -19349,7 +19361,7 @@
     method public void setSubmessageId(short);
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
     field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
     field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
     field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
@@ -19360,27 +19372,58 @@
     field public static final short STATUS_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GpsNavigationMessage.GpsNavigationMessageType implements java.lang.annotation.Annotation {
+  public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
   }
 
-  public final class GpsNavigationMessageEvent implements android.os.Parcelable {
-    ctor public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
+  public final class GnssNavigationMessageEvent implements android.os.Parcelable {
+    ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
     method public int describeContents();
-    method public android.location.GpsNavigationMessage getNavigationMessage();
+    method public android.location.GnssNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
     field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract class GpsNavigationMessageEvent.Callback {
-    ctor public GpsNavigationMessageEvent.Callback();
-    method public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
+  public static abstract class GnssNavigationMessageEvent.Callback {
+    ctor public GnssNavigationMessageEvent.Callback();
+    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GpsNavigationMessageEvent.GpsNavigationMessageStatus implements java.lang.annotation.Annotation {
+  public static abstract class GnssNavigationMessageEvent.GnssNavigationMessageStatus implements java.lang.annotation.Annotation {
+  }
+
+  public abstract interface GnssNmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public final class GnssStatus {
+    method public float getAzimuth(int);
+    method public int getConstellationType(int);
+    method public float getElevation(int);
+    method public int getNumSatellites();
+    method public int getPrn(int);
+    method public float getSnr(int);
+    method public boolean hasAlmanac(int);
+    method public boolean hasEphemeris(int);
+    method public boolean usedInFix(int);
+    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+    field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_QZSS = 4; // 0x4
+    field public static final int CONSTELLATION_SBAS = 2; // 0x2
+    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+  }
+
+  public 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 final class GpsSatellite {
@@ -19484,12 +19527,12 @@
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
     method public boolean isProviderEnabled(java.lang.String);
+    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean 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 registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
-    method public boolean registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback, android.os.Handler);
-    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback);
-    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.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);
@@ -19510,9 +19553,9 @@
     method public void setTestProviderEnabled(java.lang.String, boolean);
     method public void setTestProviderLocation(java.lang.String, android.location.Location);
     method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
+    method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
-    method public void unregisterGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
-    method public void unregisterGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.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";
@@ -23380,6 +23423,7 @@
     method public void unregisterNetworkCallback(android.app.PendingIntent);
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
     field public static final java.lang.String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
+    field public static final java.lang.String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED";
     field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
     field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
     field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
@@ -23429,6 +23473,12 @@
     method public int getUid();
   }
 
+  public class DataUsageRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR;
+  }
+
   public class DhcpInfo implements android.os.Parcelable {
     ctor public DhcpInfo();
     method public int describeContents();
@@ -24295,22 +24345,6 @@
 
 package android.net.wifi {
 
-  public class ScanInfo implements android.os.Parcelable {
-    ctor public ScanInfo(android.net.wifi.ScanResult);
-    ctor public ScanInfo(long, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int);
-    method public int describeContents();
-    method public long getBssid();
-    method public byte[] getIconData();
-    method public java.lang.String getIconType();
-    method public java.lang.String getName();
-    method public int getOsuIdentity();
-    method public int getRssi();
-    method public android.net.wifi.ScanResult getScanResult();
-    method public java.lang.String getServiceDescription();
-    method public java.lang.String getSsid();
-    method public void writeToParcel(android.os.Parcel, int);
-  }
-
   public class ScanResult implements android.os.Parcelable {
     method public int describeContents();
     method public boolean is80211mcResponder();
@@ -24471,6 +24505,7 @@
     field public static final int SIM = 4; // 0x4
     field public static final int TLS = 1; // 0x1
     field public static final int TTLS = 2; // 0x2
+    field public static final int UNAUTH_TLS = 7; // 0x7
   }
 
   public static final class WifiEnterpriseConfig.Phase2 {
@@ -24513,7 +24548,6 @@
     method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
     method public android.net.wifi.WifiInfo getConnectionInfo();
     method public android.net.DhcpInfo getDhcpInfo();
-    method public java.util.List<android.net.wifi.ScanInfo> getScanInfos();
     method public java.util.List<android.net.wifi.ScanResult> getScanResults();
     method public int getWifiState();
     method public boolean is5GHzBandSupported();
@@ -24529,7 +24563,6 @@
     method public boolean reconnect();
     method public boolean removeNetwork(int);
     method public boolean saveConfiguration();
-    method public void setOsuSelection(int);
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
     method public boolean setWifiEnabled(boolean);
@@ -28526,6 +28559,7 @@
     field public static java.lang.String DIRECTORY_DCIM;
     field public static java.lang.String DIRECTORY_DOCUMENTS;
     field public static java.lang.String DIRECTORY_DOWNLOADS;
+    field public static java.lang.String DIRECTORY_HOME;
     field public static java.lang.String DIRECTORY_MOVIES;
     field public static java.lang.String DIRECTORY_MUSIC;
     field public static java.lang.String DIRECTORY_NOTIFICATIONS;
@@ -29261,6 +29295,7 @@
     field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
     field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
     field public static final java.lang.String DISALLOW_SET_USER_ICON = "no_set_user_icon";
+    field public static final java.lang.String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
     field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
     field public static final java.lang.String DISALLOW_SMS = "no_sms";
     field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
@@ -30124,6 +30159,7 @@
   }
 
   public class BlockedNumberContract {
+    method public static boolean canCurrentUserBlockNumbers(android.content.Context);
     method public static boolean isBlocked(android.content.Context, java.lang.String);
     field public static final java.lang.String AUTHORITY = "com.android.blockednumber";
     field public static final android.net.Uri AUTHORITY_URI;
@@ -30133,7 +30169,6 @@
     field public static final java.lang.String COLUMN_E164_NUMBER = "e164_number";
     field public static final java.lang.String COLUMN_ID = "_id";
     field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number";
-    field public static final java.lang.String COLUMN_STRIPPED_NUMBER = "stripped_number";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
     field public static final android.net.Uri CONTENT_URI;
@@ -31644,14 +31679,13 @@
     field public static final java.lang.String COLUMN_MIME_TYPE = "mime_type";
     field public static final java.lang.String COLUMN_SIZE = "_size";
     field public static final java.lang.String COLUMN_SUMMARY = "summary";
-    field public static final int FLAG_ARCHIVE = 1024; // 0x400
     field public static final int FLAG_DIR_PREFERS_GRID = 16; // 0x10
     field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
     field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
     field public static final int FLAG_SUPPORTS_COPY = 128; // 0x80
     field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
     field public static final int FLAG_SUPPORTS_MOVE = 256; // 0x100
-    field public static final int FLAG_SUPPORTS_REMOVE = 2048; // 0x800
+    field public static final int FLAG_SUPPORTS_REMOVE = 1024; // 0x400
     field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40
     field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
     field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
@@ -32077,6 +32111,7 @@
     field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
     field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
     field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
+    field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
     field public static final java.lang.String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS = "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
@@ -34333,6 +34368,9 @@
     ctor public MediaBrowserService.BrowserRoot(java.lang.String, android.os.Bundle);
     method public android.os.Bundle getExtras();
     method public java.lang.String getRootId();
+    field public static final java.lang.String EXTRA_OFFLINE = "android.service.media.extra.OFFLINE";
+    field public static final java.lang.String EXTRA_RECENT = "android.service.media.extra.RECENT";
+    field public static final java.lang.String EXTRA_SUGGESTED = "android.service.media.extra.SUGGESTED";
   }
 
   public class MediaBrowserService.Result {
@@ -34345,6 +34383,7 @@
 package android.service.notification {
 
   public class Condition implements android.os.Parcelable {
+    ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
     method public android.service.notification.Condition copy();
     method public int describeContents();
@@ -34376,7 +34415,6 @@
     method public final void notifyConditions(android.service.notification.Condition...);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract void onConnected();
-    method public abstract void onRequestConditions(int);
     method public abstract void onSubscribe(android.net.Uri);
     method public abstract void onUnsubscribe(android.net.Uri);
     field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
@@ -34386,38 +34424,6 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
-  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
-    ctor public NotificationAssistantService();
-    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
-    method public final void clearAnnotation(java.lang.String);
-    method public void onNotificationActionClick(java.lang.String, long, int);
-    method public void onNotificationClick(java.lang.String, long);
-    method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
-    method public void onNotificationRemoved(java.lang.String, long, int);
-    method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
-    method public final void setAnnotation(java.lang.String, android.app.Notification);
-    field public static final int REASON_APP_CANCEL = 8; // 0x8
-    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
-    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
-    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
-    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
-    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
-    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
-    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
-    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
-    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
-    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
-    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
-    field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
-    field public static final int REASON_TOPIC_BANNED = 14; // 0xe
-    field public static final int REASON_USER_STOPPED = 6; // 0x6
-    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
-  }
-
-  public class NotificationAssistantService.Adjustment {
-    ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
-  }
-
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -36317,6 +36323,7 @@
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
+    method public void launchManageBlockedNumbersActivity();
     method public void placeCall(android.net.Uri, android.os.Bundle);
     method public void registerPhoneAccount(android.telecom.PhoneAccount);
     method public void showInCallScreen(boolean);
@@ -36437,6 +36444,7 @@
     field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
     field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
+    field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int";
     field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
     field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
     field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
@@ -40032,7 +40040,6 @@
     method public static android.util.LocaleList getDefault();
     method public static android.util.LocaleList getEmptyLocaleList();
     method public java.util.Locale getFirstMatch(java.lang.String[]);
-    method public java.util.Locale getPrimary();
     method public int indexOf(java.util.Locale);
     method public boolean isEmpty();
     method public static void setDefault(android.util.LocaleList);
@@ -43241,7 +43248,7 @@
     method public abstract void setNavigationBarColor(int);
     method public void setReenterTransition(android.transition.Transition);
     method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
-    method public final void setRestrictedCaptionAreaListener(android.view.Window.RestrictedCaptionAreaListener);
+    method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
     method public void setReturnTransition(android.transition.Transition);
     method public void setSharedElementEnterTransition(android.transition.Transition);
     method public void setSharedElementExitTransition(android.transition.Transition);
@@ -43328,7 +43335,7 @@
     method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
   }
 
-  public static abstract interface Window.RestrictedCaptionAreaListener {
+  public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
     method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
   }
 
@@ -43676,6 +43683,7 @@
     method public boolean isEnabled();
     method public boolean isFocusable();
     method public boolean isFocused();
+    method public boolean isImportantForAccessibility();
     method public boolean isLongClickable();
     method public boolean isMultiLine();
     method public boolean isPassword();
@@ -43714,6 +43722,7 @@
     method public void setError(java.lang.CharSequence);
     method public void setFocusable(boolean);
     method public void setFocused(boolean);
+    method public void setImportantForAccessibility(boolean);
     method public void setInputType(int);
     method public void setLabelFor(android.view.View);
     method public void setLabelFor(android.view.View, int);
@@ -50168,13 +50177,16 @@
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method public T getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
@@ -50705,7 +50717,10 @@
   public class Package implements java.lang.reflect.AnnotatedElement {
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getImplementationTitle();
     method public java.lang.String getImplementationVendor();
     method public java.lang.String getImplementationVersion();
@@ -51399,7 +51414,10 @@
     ctor protected AccessibleObject();
     method public T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public boolean isAccessible();
     method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException;
@@ -51409,7 +51427,10 @@
   public abstract interface AnnotatedElement {
     method public abstract T getAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getAnnotations();
+    method public abstract T[] getAnnotationsByType(java.lang.Class<T>);
+    method public abstract java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public abstract T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public abstract boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
   }
 
@@ -52524,7 +52545,6 @@
     method public static void setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory);
     method public java.lang.String toExternalForm();
     method public java.net.URI toURI() throws java.net.URISyntaxException;
-    method public java.net.URI toURILenient() throws java.net.URISyntaxException;
   }
 
   public class URLClassLoader extends java.security.SecureClassLoader implements java.io.Closeable {
diff --git a/api/removed.txt b/api/removed.txt
index 2c6729d..0bf6594 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -199,6 +199,14 @@
 
 }
 
+package android.service.notification {
+
+  public abstract class ConditionProviderService extends android.app.Service {
+    method public void onRequestConditions(int);
+  }
+
+}
+
 package android.test.mock {
 
   public deprecated class MockPackageManager extends android.content.pm.PackageManager {
diff --git a/api/system-current.txt b/api/system-current.txt
index 979ef2f..2adb1e6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -41,7 +41,6 @@
     field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
     field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
-    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -91,12 +90,13 @@
     field public static final java.lang.String DEVICE_POWER = "android.permission.DEVICE_POWER";
     field public static final java.lang.String DIAGNOSTIC = "android.permission.DIAGNOSTIC";
     field public static final java.lang.String DISABLE_KEYGUARD = "android.permission.DISABLE_KEYGUARD";
+    field public static final java.lang.String DISPATCH_PROVISIONING_MESSAGE = "android.permission.DISPATCH_PROVISIONING_MESSAGE";
     field public static final java.lang.String DUMP = "android.permission.DUMP";
     field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
     field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
     field public static final java.lang.String FORCE_BACK = "android.permission.FORCE_BACK";
     field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
-    field public static final deprecated java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
+    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_APP_OPS_STATS = "android.permission.GET_APP_OPS_STATS";
     field public static final java.lang.String GET_PACKAGE_IMPORTANCE = "android.permission.GET_PACKAGE_IMPORTANCE";
@@ -293,6 +293,7 @@
 
   public static final class R.attr {
     ctor public R.attr();
+    field public static final int abiOverride = 16844054; // 0x1010516
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -400,6 +401,7 @@
     field public static final int baselineAlignBottom = 16843042; // 0x1010122
     field public static final int baselineAligned = 16843046; // 0x1010126
     field public static final int baselineAlignedChildIndex = 16843047; // 0x1010127
+    field public static final int bitmap = 16844055; // 0x1010517
     field public static final int borderlessButtonStyle = 16843563; // 0x101032b
     field public static final int bottom = 16843184; // 0x10101b0
     field public static final int bottomBright = 16842957; // 0x10100cd
@@ -741,6 +743,8 @@
     field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
     field public static final int horizontalSpacing = 16843028; // 0x1010114
     field public static final int host = 16842792; // 0x1010028
+    field public static final int hotSpotX = 16844056; // 0x1010518
+    field public static final int hotSpotY = 16844057; // 0x1010519
     field public static final int hyphenationFrequency = 16843998; // 0x10104de
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
@@ -3523,7 +3527,7 @@
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
-    method public void enterPictureInPictureMode();
+    method public void enterPictureInPicture();
     method public android.view.View findViewById(int);
     method public void finish();
     method public void finishActivity(int);
@@ -3563,8 +3567,8 @@
     method public android.view.Window getWindow();
     method public android.view.WindowManager getWindowManager();
     method public boolean hasWindowFocus();
-    method public boolean inMultiWindowMode();
-    method public boolean inPictureInPictureMode();
+    method public boolean inMultiWindow();
+    method public boolean inPictureInPicture();
     method public void invalidateOptionsMenu();
     method public boolean isBackgroundVisibleBehind();
     method public boolean isChangingConfigurations();
@@ -3620,7 +3624,7 @@
     method public void onLowMemory();
     method public boolean onMenuItemSelected(int, android.view.MenuItem);
     method public boolean onMenuOpened(int, android.view.Menu);
-    method public void onMultiWindowModeChanged(boolean);
+    method public void onMultiWindowChanged(boolean);
     method public boolean onNavigateUp();
     method public boolean onNavigateUpFromChild(android.app.Activity);
     method protected void onNewIntent(android.content.Intent);
@@ -3628,7 +3632,7 @@
     method public void onOptionsMenuClosed(android.view.Menu);
     method public void onPanelClosed(int, android.view.Menu);
     method protected void onPause();
-    method public void onPictureInPictureModeChanged(boolean);
+    method public void onPictureInPictureChanged(boolean);
     method protected void onPostCreate(android.os.Bundle);
     method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
     method protected void onPostResume();
@@ -4554,9 +4558,11 @@
     method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
     method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
     method public void onLowMemory();
+    method public void onMultiWindowChanged(boolean);
     method public boolean onOptionsItemSelected(android.view.MenuItem);
     method public void onOptionsMenuClosed(android.view.Menu);
     method public void onPause();
+    method public void onPictureInPictureChanged(boolean);
     method public void onPrepareOptionsMenu(android.view.Menu);
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method public void onResume();
@@ -4637,9 +4643,11 @@
     method public void dispatchDestroy();
     method public void dispatchDestroyView();
     method public void dispatchLowMemory();
+    method public void dispatchMultiWindowChanged(boolean);
     method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
     method public void dispatchOptionsMenuClosed(android.view.Menu);
     method public void dispatchPause();
+    method public void dispatchPictureInPictureChanged(boolean);
     method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
     method public void dispatchResume();
     method public void dispatchStart();
@@ -5838,6 +5846,7 @@
     method public static android.app.WallpaperManager getInstance(android.content.Context);
     method public android.app.WallpaperInfo getWallpaperInfo();
     method public boolean hasResourceWallpaper(int);
+    method public boolean isWallpaperSettingAllowed();
     method public boolean isWallpaperSupported();
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
@@ -6094,6 +6103,7 @@
     field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
     field public static final java.lang.String ACTION_PROVISION_MANAGED_DEVICE = "android.app.action.PROVISION_MANAGED_DEVICE";
+    field public static final java.lang.String ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE = "android.app.action.PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE";
     field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
     field public static final java.lang.String ACTION_SET_NEW_PARENT_PROFILE_PASSWORD = "android.app.action.SET_NEW_PARENT_PROFILE_PASSWORD";
     field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
@@ -6571,6 +6581,22 @@
     field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
   }
 
+  public class DataUsagePolicy {
+    field public final int networkType;
+    field public final java.lang.String[] subscriberIds;
+    field public final long thresholdInBytes;
+    field public final int[] uids;
+  }
+
+  public static class DataUsagePolicy.Builder {
+    ctor public DataUsagePolicy.Builder();
+    method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
+    method public android.app.usage.DataUsagePolicy.Builder addUid(int);
+    method public android.app.usage.DataUsagePolicy build();
+    method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
+    method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
+  }
+
   public final class NetworkStats implements java.lang.AutoCloseable {
     method public void close();
     method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
@@ -6585,6 +6611,7 @@
     method public long getRxPackets();
     method public long getStartTimeStamp();
     method public int getState();
+    method public int getTag();
     method public long getTxBytes();
     method public long getTxPackets();
     method public int getUid();
@@ -6594,6 +6621,8 @@
     field public static final int STATE_ALL = -1; // 0xffffffff
     field public static final int STATE_DEFAULT = 1; // 0x1
     field public static final int STATE_FOREGROUND = 2; // 0x2
+    field public static final int TAG_ALL = 0; // 0x0
+    field public static final int TAG_ANY = -1; // 0xffffffff
     field public static final int UID_ALL = -1; // 0xffffffff
     field public static final int UID_REMOVED = -4; // 0xfffffffc
     field public static final int UID_TETHERING = -5; // 0xfffffffb
@@ -6602,9 +6631,20 @@
   public class NetworkStatsManager {
     method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
+    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback);
+    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
+    method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
+  }
+
+  public static class NetworkStatsManager.DataUsageCallback {
+    ctor public NetworkStatsManager.DataUsageCallback();
+    method public void onLimitReached();
   }
 
   public final class UsageEvents implements android.os.Parcelable {
@@ -8158,6 +8198,7 @@
     field public static final java.lang.String SYNC_EXTRAS_INITIALIZE = "initialize";
     field public static final java.lang.String SYNC_EXTRAS_MANUAL = "force";
     field public static final java.lang.String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
+    field public static final java.lang.String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging";
     field public static final java.lang.String SYNC_EXTRAS_UPLOAD = "upload";
     field public static final int SYNC_OBSERVER_TYPE_ACTIVE = 4; // 0x4
     field public static final int SYNC_OBSERVER_TYPE_PENDING = 2; // 0x2
@@ -9374,6 +9415,7 @@
     method public android.content.SyncRequest.Builder setIgnoreSettings(boolean);
     method public android.content.SyncRequest.Builder setManual(boolean);
     method public android.content.SyncRequest.Builder setNoRetry(boolean);
+    method public android.content.SyncRequest.Builder setRequiresCharging(boolean);
     method public android.content.SyncRequest.Builder setSyncAdapter(android.accounts.Account, java.lang.String);
     method public android.content.SyncRequest.Builder syncOnce();
     method public android.content.SyncRequest.Builder syncPeriodic(long, long);
@@ -10087,6 +10129,7 @@
     field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
     field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
     field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
+    field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
     field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
     field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
     field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
@@ -10302,6 +10345,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     field public static final android.os.Parcelable.Creator<android.content.pm.ServiceInfo> CREATOR;
+    field public static final int FLAG_EXTERNAL_SERVICE = 4; // 0x4
     field public static final int FLAG_ISOLATED_PROCESS = 2; // 0x2
     field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
     field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1
@@ -20281,38 +20325,7 @@
     method public static boolean isPresent();
   }
 
-  public abstract interface GnssNmeaListener {
-    method public abstract void onNmeaReceived(long, java.lang.String);
-  }
-
-  public final class GnssStatus {
-    method public float getAzimuth(int);
-    method public int getConstellationType(int);
-    method public float getElevation(int);
-    method public int getNumSatellites();
-    method public int getPrn(int);
-    method public float getSnr(int);
-    method public boolean hasAlmanac(int);
-    method public boolean hasEphemeris(int);
-    method public boolean usedInFix(int);
-    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
-    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
-    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
-    field public static final int CONSTELLATION_GPS = 1; // 0x1
-    field public static final int CONSTELLATION_QZSS = 4; // 0x4
-    field public static final int CONSTELLATION_SBAS = 2; // 0x2
-    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
-  }
-
-  public 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 final class GpsClock implements android.os.Parcelable {
+  public final class GnssClock implements android.os.Parcelable {
     method public int describeContents();
     method public double getBiasInNs();
     method public double getBiasUncertaintyInNs();
@@ -20339,7 +20352,7 @@
     method public void resetFullBiasInNs();
     method public void resetLeapSecond();
     method public void resetTimeUncertaintyInNs();
-    method public void set(android.location.GpsClock);
+    method public void set(android.location.GnssClock);
     method public void setBiasInNs(double);
     method public void setBiasUncertaintyInNs(double);
     method public void setDriftInNsPerSec(double);
@@ -20354,13 +20367,13 @@
     field public static final byte CLOCK_TYPE_GPS_TIME = 2; // 0x2
     field public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1; // 0x1
     field public static final byte CLOCK_TYPE_UNKNOWN = 0; // 0x0
-    field public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
 
-  public static abstract class GpsClock.GpsClockType implements java.lang.annotation.Annotation {
+  public static abstract class GnssClock.GnssClockType implements java.lang.annotation.Annotation {
   }
 
-  public final class GpsMeasurement implements android.os.Parcelable {
+  public final class GnssMeasurement implements android.os.Parcelable {
     method public int describeContents();
     method public double getAccumulatedDeltaRangeInMeters();
     method public short getAccumulatedDeltaRangeState();
@@ -20431,7 +20444,7 @@
     method public void resetPseudorangeUncertaintyInMeters();
     method public void resetSnrInDb();
     method public void resetTimeFromLastBitInMs();
-    method public void set(android.location.GpsMeasurement);
+    method public void set(android.location.GnssMeasurement);
     method public void setAccumulatedDeltaRangeInMeters(double);
     method public void setAccumulatedDeltaRangeState(short);
     method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
@@ -20470,6 +20483,279 @@
     field public static final short ADR_STATE_RESET = 2; // 0x2
     field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
     field public static final short ADR_STATE_VALID = 1; // 0x1
+    field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
+    field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
+    field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
+    field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
+    field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+    field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+    field public static final short STATE_BIT_SYNC = 2; // 0x2
+    field public static final short STATE_CODE_LOCK = 1; // 0x1
+    field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
+    field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
+    field public static final short STATE_TOW_DECODED = 8; // 0x8
+    field public static final short STATE_UNKNOWN = 0; // 0x0
+  }
+
+  public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
+  }
+
+  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_GPS_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);
+  }
+
+  public static abstract class GnssMeasurementsEvent.GnssMeasurementsStatus implements java.lang.annotation.Annotation {
+  }
+
+  public final class GnssNavigationMessage implements android.os.Parcelable {
+    method public int describeContents();
+    method public byte[] getData();
+    method public short getMessageId();
+    method public byte getPrn();
+    method public short getStatus();
+    method public short getSubmessageId();
+    method public byte getType();
+    method public void reset();
+    method public void set(android.location.GnssNavigationMessage);
+    method public void setData(byte[]);
+    method public void setMessageId(short);
+    method public void setPrn(byte);
+    method public void setStatus(short);
+    method public void setSubmessageId(short);
+    method public void setType(byte);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
+    field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
+    field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
+    field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
+    field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3
+    field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0
+    field public static final short STATUS_PARITY_PASSED = 1; // 0x1
+    field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
+    field public static final short STATUS_UNKNOWN = 0; // 0x0
+  }
+
+  public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
+  }
+
+  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_GPS_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 static abstract class GnssNavigationMessageEvent.GnssNavigationMessageStatus implements java.lang.annotation.Annotation {
+  }
+
+  public abstract interface GnssNmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public final class GnssStatus {
+    method public float getAzimuth(int);
+    method public int getConstellationType(int);
+    method public float getElevation(int);
+    method public int getNumSatellites();
+    method public int getPrn(int);
+    method public float getSnr(int);
+    method public boolean hasAlmanac(int);
+    method public boolean hasEphemeris(int);
+    method public boolean usedInFix(int);
+    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+    field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_QZSS = 4; // 0x4
+    field public static final int CONSTELLATION_SBAS = 2; // 0x2
+    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+  }
+
+  public 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 GpsClock implements android.os.Parcelable {
+    method public int describeContents();
+    method public double getBiasInNs();
+    method public double getBiasUncertaintyInNs();
+    method public double getDriftInNsPerSec();
+    method public double getDriftUncertaintyInNsPerSec();
+    method public long getFullBiasInNs();
+    method public short getLeapSecond();
+    method public long getTimeInNs();
+    method public double getTimeUncertaintyInNs();
+    method public byte getType();
+    method public boolean hasBiasInNs();
+    method public boolean hasBiasUncertaintyInNs();
+    method public boolean hasDriftInNsPerSec();
+    method public boolean hasDriftUncertaintyInNsPerSec();
+    method public boolean hasFullBiasInNs();
+    method public boolean hasLeapSecond();
+    method public boolean hasTimeUncertaintyInNs();
+    method public void reset();
+    method public void resetBiasInNs();
+    method public void resetBiasUncertaintyInNs();
+    method public void resetDriftInNsPerSec();
+    method public void resetDriftUncertaintyInNsPerSec();
+    method public void resetFullBiasInNs();
+    method public void resetLeapSecond();
+    method public void resetTimeUncertaintyInNs();
+    method public void set(android.location.GpsClock);
+    method public void setBiasInNs(double);
+    method public void setBiasUncertaintyInNs(double);
+    method public void setDriftInNsPerSec(double);
+    method public void setDriftUncertaintyInNsPerSec(double);
+    method public void setFullBiasInNs(long);
+    method public void setLeapSecond(short);
+    method public void setTimeInNs(long);
+    method public void setTimeUncertaintyInNs(double);
+    method public void setType(byte);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
+    field public static final byte TYPE_GPS_TIME = 2; // 0x2
+    field public static final byte TYPE_LOCAL_HW_TIME = 1; // 0x1
+    field public static final byte TYPE_UNKNOWN = 0; // 0x0
+  }
+
+  public class GpsMeasurement implements android.os.Parcelable {
+    method public int describeContents();
+    method public double getAccumulatedDeltaRangeInMeters();
+    method public short getAccumulatedDeltaRangeState();
+    method public double getAccumulatedDeltaRangeUncertaintyInMeters();
+    method public double getAzimuthInDeg();
+    method public double getAzimuthUncertaintyInDeg();
+    method public int getBitNumber();
+    method public long getCarrierCycles();
+    method public float getCarrierFrequencyInHz();
+    method public double getCarrierPhase();
+    method public double getCarrierPhaseUncertainty();
+    method public double getCn0InDbHz();
+    method public double getCodePhaseInChips();
+    method public double getCodePhaseUncertaintyInChips();
+    method public double getDopplerShiftInHz();
+    method public double getDopplerShiftUncertaintyInHz();
+    method public double getElevationInDeg();
+    method public double getElevationUncertaintyInDeg();
+    method public byte getLossOfLock();
+    method public byte getMultipathIndicator();
+    method public byte getPrn();
+    method public double getPseudorangeInMeters();
+    method public double getPseudorangeRateInMetersPerSec();
+    method public double getPseudorangeRateUncertaintyInMetersPerSec();
+    method public double getPseudorangeUncertaintyInMeters();
+    method public long getReceivedGpsTowInNs();
+    method public long getReceivedGpsTowUncertaintyInNs();
+    method public double getSnrInDb();
+    method public short getState();
+    method public short getTimeFromLastBitInMs();
+    method public double getTimeOffsetInNs();
+    method public boolean hasAzimuthInDeg();
+    method public boolean hasAzimuthUncertaintyInDeg();
+    method public boolean hasBitNumber();
+    method public boolean hasCarrierCycles();
+    method public boolean hasCarrierFrequencyInHz();
+    method public boolean hasCarrierPhase();
+    method public boolean hasCarrierPhaseUncertainty();
+    method public boolean hasCodePhaseInChips();
+    method public boolean hasCodePhaseUncertaintyInChips();
+    method public boolean hasDopplerShiftInHz();
+    method public boolean hasDopplerShiftUncertaintyInHz();
+    method public boolean hasElevationInDeg();
+    method public boolean hasElevationUncertaintyInDeg();
+    method public boolean hasPseudorangeInMeters();
+    method public boolean hasPseudorangeUncertaintyInMeters();
+    method public boolean hasSnrInDb();
+    method public boolean hasTimeFromLastBitInMs();
+    method public boolean isPseudorangeRateCorrected();
+    method public boolean isUsedInFix();
+    method public void reset();
+    method public void resetAzimuthInDeg();
+    method public void resetAzimuthUncertaintyInDeg();
+    method public void resetBitNumber();
+    method public void resetCarrierCycles();
+    method public void resetCarrierFrequencyInHz();
+    method public void resetCarrierPhase();
+    method public void resetCarrierPhaseUncertainty();
+    method public void resetCodePhaseInChips();
+    method public void resetCodePhaseUncertaintyInChips();
+    method public void resetDopplerShiftInHz();
+    method public void resetDopplerShiftUncertaintyInHz();
+    method public void resetElevationInDeg();
+    method public void resetElevationUncertaintyInDeg();
+    method public void resetPseudorangeInMeters();
+    method public void resetPseudorangeUncertaintyInMeters();
+    method public void resetSnrInDb();
+    method public void resetTimeFromLastBitInMs();
+    method public void set(android.location.GpsMeasurement);
+    method public void setAccumulatedDeltaRangeInMeters(double);
+    method public void setAccumulatedDeltaRangeState(short);
+    method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
+    method public void setAzimuthInDeg(double);
+    method public void setAzimuthUncertaintyInDeg(double);
+    method public void setBitNumber(int);
+    method public void setCarrierCycles(long);
+    method public void setCarrierFrequencyInHz(float);
+    method public void setCarrierPhase(double);
+    method public void setCarrierPhaseUncertainty(double);
+    method public void setCn0InDbHz(double);
+    method public void setCodePhaseInChips(double);
+    method public void setCodePhaseUncertaintyInChips(double);
+    method public void setDopplerShiftInHz(double);
+    method public void setDopplerShiftUncertaintyInHz(double);
+    method public void setElevationInDeg(double);
+    method public void setElevationUncertaintyInDeg(double);
+    method public void setLossOfLock(byte);
+    method public void setMultipathIndicator(byte);
+    method public void setPrn(byte);
+    method public void setPseudorangeInMeters(double);
+    method public void setPseudorangeRateInMetersPerSec(double);
+    method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
+    method public void setPseudorangeUncertaintyInMeters(double);
+    method public void setReceivedGpsTowInNs(long);
+    method public void setReceivedGpsTowUncertaintyInNs(long);
+    method public void setSnrInDb(double);
+    method public void setState(short);
+    method public void setTimeFromLastBitInMs(short);
+    method public void setTimeOffsetInNs(double);
+    method public void setUsedInFix(boolean);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
+    field public static final short ADR_STATE_RESET = 2; // 0x2
+    field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
+    field public static final short ADR_STATE_VALID = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
     field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
     field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
@@ -20485,13 +20771,7 @@
     field public static final short STATE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GpsMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
-  }
-
-  public static abstract class GpsMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
-  }
-
-  public final class GpsMeasurementsEvent implements android.os.Parcelable {
+  public class GpsMeasurementsEvent implements android.os.Parcelable {
     ctor public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
     method public int describeContents();
     method public android.location.GpsClock getClock();
@@ -20503,16 +20783,12 @@
     field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract class GpsMeasurementsEvent.Callback {
-    ctor public GpsMeasurementsEvent.Callback();
-    method public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
-    method public void onStatusChanged(int);
+  public static abstract interface GpsMeasurementsEvent.Listener {
+    method public abstract void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
+    method public abstract void onStatusChanged(int);
   }
 
-  public static abstract class GpsMeasurementsEvent.GpsMeasurementsStatus implements java.lang.annotation.Annotation {
-  }
-
-  public final class GpsNavigationMessage implements android.os.Parcelable {
+  public class GpsNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
@@ -20530,37 +20806,30 @@
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
-    field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
-    field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
-    field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
-    field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3
-    field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0
     field public static final short STATUS_PARITY_PASSED = 1; // 0x1
     field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
     field public static final short STATUS_UNKNOWN = 0; // 0x0
+    field public static final byte TYPE_CNAV2 = 4; // 0x4
+    field public static final byte TYPE_L1CA = 1; // 0x1
+    field public static final byte TYPE_L2CNAV = 2; // 0x2
+    field public static final byte TYPE_L5CNAV = 3; // 0x3
+    field public static final byte TYPE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GpsNavigationMessage.GpsNavigationMessageType implements java.lang.annotation.Annotation {
-  }
-
-  public final class GpsNavigationMessageEvent implements android.os.Parcelable {
+  public class GpsNavigationMessageEvent implements android.os.Parcelable {
     ctor public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
     method public int describeContents();
     method public android.location.GpsNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
-    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
-    field public static final int STATUS_READY = 1; // 0x1
+    field public static int STATUS_GPS_LOCATION_DISABLED;
+    field public static int STATUS_NOT_SUPPORTED;
+    field public static int STATUS_READY;
   }
 
-  public static abstract class GpsNavigationMessageEvent.Callback {
-    ctor public GpsNavigationMessageEvent.Callback();
-    method public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
-    method public void onStatusChanged(int);
-  }
-
-  public static abstract class GpsNavigationMessageEvent.GpsNavigationMessageStatus implements java.lang.annotation.Annotation {
+  public static abstract interface GpsNavigationMessageEvent.Listener {
+    method public abstract void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
+    method public abstract void onStatusChanged(int);
   }
 
   public final class GpsSatellite {
@@ -20667,6 +20936,8 @@
   }
 
   public class LocationManager {
+    method public deprecated boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
+    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);
@@ -20684,12 +20955,14 @@
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
     method public boolean isProviderEnabled(java.lang.String);
+    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean 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 registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
-    method public boolean registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback, android.os.Handler);
-    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback);
-    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.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);
@@ -20712,9 +20985,9 @@
     method public void setTestProviderEnabled(java.lang.String, boolean);
     method public void setTestProviderLocation(java.lang.String, android.location.Location);
     method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
+    method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
-    method public void unregisterGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
-    method public void unregisterGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.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";
@@ -24947,6 +25220,7 @@
     method public void unregisterNetworkCallback(android.app.PendingIntent);
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
     field public static final java.lang.String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
+    field public static final java.lang.String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED";
     field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
     field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
     field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
@@ -25005,6 +25279,12 @@
     method public int getUid();
   }
 
+  public class DataUsageRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR;
+  }
+
   public class DhcpInfo implements android.os.Parcelable {
     ctor public DhcpInfo();
     method public int describeContents();
@@ -26114,22 +26394,6 @@
     field public byte id;
   }
 
-  public class ScanInfo implements android.os.Parcelable {
-    ctor public ScanInfo(android.net.wifi.ScanResult);
-    ctor public ScanInfo(long, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int);
-    method public int describeContents();
-    method public long getBssid();
-    method public byte[] getIconData();
-    method public java.lang.String getIconType();
-    method public java.lang.String getName();
-    method public int getOsuIdentity();
-    method public int getRssi();
-    method public android.net.wifi.ScanResult getScanResult();
-    method public java.lang.String getServiceDescription();
-    method public java.lang.String getSsid();
-    method public void writeToParcel(android.os.Parcel, int);
-  }
-
   public class ScanResult implements android.os.Parcelable {
     method public int describeContents();
     method public boolean is80211mcResponder();
@@ -26313,6 +26577,7 @@
     field public static final int SIM = 4; // 0x4
     field public static final int TLS = 1; // 0x1
     field public static final int TTLS = 2; // 0x2
+    field public static final int UNAUTH_TLS = 7; // 0x7
   }
 
   public static final class WifiEnterpriseConfig.Phase2 {
@@ -26358,7 +26623,6 @@
     method public android.net.wifi.WifiConnectionStatistics getConnectionStatistics();
     method public android.net.DhcpInfo getDhcpInfo();
     method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
-    method public java.util.List<android.net.wifi.ScanInfo> getScanInfos();
     method public java.util.List<android.net.wifi.ScanResult> getScanResults();
     method public android.net.wifi.WifiConfiguration getWifiApConfiguration();
     method public int getWifiApState();
@@ -26381,7 +26645,6 @@
     method public boolean reconnect();
     method public boolean removeNetwork(int);
     method public boolean saveConfiguration();
-    method public void setOsuSelection(int);
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
     method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
@@ -30553,6 +30816,7 @@
     field public static java.lang.String DIRECTORY_DCIM;
     field public static java.lang.String DIRECTORY_DOCUMENTS;
     field public static java.lang.String DIRECTORY_DOWNLOADS;
+    field public static java.lang.String DIRECTORY_HOME;
     field public static java.lang.String DIRECTORY_MOVIES;
     field public static java.lang.String DIRECTORY_MUSIC;
     field public static java.lang.String DIRECTORY_NOTIFICATIONS;
@@ -31307,6 +31571,7 @@
     field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
     field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
     field public static final java.lang.String DISALLOW_SET_USER_ICON = "no_set_user_icon";
+    field public static final java.lang.String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
     field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
     field public static final java.lang.String DISALLOW_SMS = "no_sms";
     field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
@@ -32171,6 +32436,7 @@
   }
 
   public class BlockedNumberContract {
+    method public static boolean canCurrentUserBlockNumbers(android.content.Context);
     method public static boolean isBlocked(android.content.Context, java.lang.String);
     field public static final java.lang.String AUTHORITY = "com.android.blockednumber";
     field public static final android.net.Uri AUTHORITY_URI;
@@ -32180,7 +32446,6 @@
     field public static final java.lang.String COLUMN_E164_NUMBER = "e164_number";
     field public static final java.lang.String COLUMN_ID = "_id";
     field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number";
-    field public static final java.lang.String COLUMN_STRIPPED_NUMBER = "stripped_number";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
     field public static final android.net.Uri CONTENT_URI;
@@ -33721,14 +33986,13 @@
     field public static final java.lang.String COLUMN_MIME_TYPE = "mime_type";
     field public static final java.lang.String COLUMN_SIZE = "_size";
     field public static final java.lang.String COLUMN_SUMMARY = "summary";
-    field public static final int FLAG_ARCHIVE = 1024; // 0x400
     field public static final int FLAG_DIR_PREFERS_GRID = 16; // 0x10
     field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
     field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
     field public static final int FLAG_SUPPORTS_COPY = 128; // 0x80
     field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
     field public static final int FLAG_SUPPORTS_MOVE = 256; // 0x100
-    field public static final int FLAG_SUPPORTS_REMOVE = 2048; // 0x800
+    field public static final int FLAG_SUPPORTS_REMOVE = 1024; // 0x400
     field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40
     field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
     field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
@@ -34256,6 +34520,7 @@
     field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
     field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
     field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
+    field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
     field public static final java.lang.String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS = "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
@@ -36513,6 +36778,9 @@
     ctor public MediaBrowserService.BrowserRoot(java.lang.String, android.os.Bundle);
     method public android.os.Bundle getExtras();
     method public java.lang.String getRootId();
+    field public static final java.lang.String EXTRA_OFFLINE = "android.service.media.extra.OFFLINE";
+    field public static final java.lang.String EXTRA_RECENT = "android.service.media.extra.RECENT";
+    field public static final java.lang.String EXTRA_SUGGESTED = "android.service.media.extra.SUGGESTED";
   }
 
   public class MediaBrowserService.Result {
@@ -36525,6 +36793,7 @@
 package android.service.notification {
 
   public class Condition implements android.os.Parcelable {
+    ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
     method public android.service.notification.Condition copy();
     method public int describeContents();
@@ -36556,7 +36825,7 @@
     method public final void notifyConditions(android.service.notification.Condition...);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract void onConnected();
-    method public abstract void onRequestConditions(int);
+    method public void onRequestConditions(int);
     method public abstract void onSubscribe(android.net.Uri);
     method public abstract void onUnsubscribe(android.net.Uri);
     field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
@@ -36569,13 +36838,11 @@
   public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
     ctor public NotificationAssistantService();
     method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
-    method public final void clearAnnotation(java.lang.String);
     method public void onNotificationActionClick(java.lang.String, long, int);
     method public void onNotificationClick(java.lang.String, long);
     method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
     method public void onNotificationRemoved(java.lang.String, long, int);
     method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
-    method public final void setAnnotation(java.lang.String, android.app.Notification);
     field public static final int REASON_APP_CANCEL = 8; // 0x8
     field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
     field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
@@ -36589,6 +36856,7 @@
     field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
     field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
     field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
+    field public static final int REASON_PROFILE_TURNED_OFF = 16; // 0x10
     field public static final int REASON_TOPIC_BANNED = 14; // 0xe
     field public static final int REASON_USER_STOPPED = 6; // 0x6
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
@@ -38663,6 +38931,7 @@
     method public boolean isRinging();
     method public boolean isTtySupported();
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
+    method public void launchManageBlockedNumbersActivity();
     method public void placeCall(android.net.Uri, android.os.Bundle);
     method public void registerPhoneAccount(android.telecom.PhoneAccount);
     method public void showInCallScreen(boolean);
@@ -38790,6 +39059,7 @@
     field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
     field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
+    field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int";
     field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
     field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
     field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
@@ -42449,7 +42719,6 @@
     method public static android.util.LocaleList getDefault();
     method public static android.util.LocaleList getEmptyLocaleList();
     method public java.util.Locale getFirstMatch(java.lang.String[]);
-    method public java.util.Locale getPrimary();
     method public int indexOf(java.util.Locale);
     method public boolean isEmpty();
     method public static void setDefault(android.util.LocaleList);
@@ -45659,7 +45928,7 @@
     method public abstract void setNavigationBarColor(int);
     method public void setReenterTransition(android.transition.Transition);
     method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
-    method public final void setRestrictedCaptionAreaListener(android.view.Window.RestrictedCaptionAreaListener);
+    method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
     method public void setReturnTransition(android.transition.Transition);
     method public void setSharedElementEnterTransition(android.transition.Transition);
     method public void setSharedElementExitTransition(android.transition.Transition);
@@ -45746,7 +46015,7 @@
     method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
   }
 
-  public static abstract interface Window.RestrictedCaptionAreaListener {
+  public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
     method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
   }
 
@@ -46096,6 +46365,7 @@
     method public boolean isEnabled();
     method public boolean isFocusable();
     method public boolean isFocused();
+    method public boolean isImportantForAccessibility();
     method public boolean isLongClickable();
     method public boolean isMultiLine();
     method public boolean isPassword();
@@ -46134,6 +46404,7 @@
     method public void setError(java.lang.CharSequence);
     method public void setFocusable(boolean);
     method public void setFocused(boolean);
+    method public void setImportantForAccessibility(boolean);
     method public void setInputType(int);
     method public void setLabelFor(android.view.View);
     method public void setLabelFor(android.view.View, int);
@@ -52921,13 +53192,16 @@
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method public T getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
@@ -53458,7 +53732,10 @@
   public class Package implements java.lang.reflect.AnnotatedElement {
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getImplementationTitle();
     method public java.lang.String getImplementationVendor();
     method public java.lang.String getImplementationVersion();
@@ -54152,7 +54429,10 @@
     ctor protected AccessibleObject();
     method public T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public boolean isAccessible();
     method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException;
@@ -54162,7 +54442,10 @@
   public abstract interface AnnotatedElement {
     method public abstract T getAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getAnnotations();
+    method public abstract T[] getAnnotationsByType(java.lang.Class<T>);
+    method public abstract java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public abstract T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public abstract boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
   }
 
@@ -55277,7 +55560,6 @@
     method public static void setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory);
     method public java.lang.String toExternalForm();
     method public java.net.URI toURI() throws java.net.URISyntaxException;
-    method public java.net.URI toURILenient() throws java.net.URISyntaxException;
   }
 
   public class URLClassLoader extends java.security.SecureClassLoader implements java.io.Closeable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 88ab3d8..7abc6d4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -28,7 +28,6 @@
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
-    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -68,7 +67,7 @@
     field public static final java.lang.String DUMP = "android.permission.DUMP";
     field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
     field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
-    field public static final deprecated java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
+    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 deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";
@@ -198,6 +197,7 @@
 
   public static final class R.attr {
     ctor public R.attr();
+    field public static final int abiOverride = 16844054; // 0x1010516
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -305,6 +305,7 @@
     field public static final int baselineAlignBottom = 16843042; // 0x1010122
     field public static final int baselineAligned = 16843046; // 0x1010126
     field public static final int baselineAlignedChildIndex = 16843047; // 0x1010127
+    field public static final int bitmap = 16844055; // 0x1010517
     field public static final int borderlessButtonStyle = 16843563; // 0x101032b
     field public static final int bottom = 16843184; // 0x10101b0
     field public static final int bottomBright = 16842957; // 0x10100cd
@@ -646,6 +647,8 @@
     field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
     field public static final int horizontalSpacing = 16843028; // 0x1010114
     field public static final int host = 16842792; // 0x1010028
+    field public static final int hotSpotX = 16844056; // 0x1010518
+    field public static final int hotSpotY = 16844057; // 0x1010519
     field public static final int hyphenationFrequency = 16843998; // 0x10104de
     field public static final int icon = 16842754; // 0x1010002
     field public static final int iconPreview = 16843337; // 0x1010249
@@ -3408,7 +3411,7 @@
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
-    method public void enterPictureInPictureMode();
+    method public void enterPictureInPicture();
     method public android.view.View findViewById(int);
     method public void finish();
     method public void finishActivity(int);
@@ -3448,8 +3451,8 @@
     method public android.view.Window getWindow();
     method public android.view.WindowManager getWindowManager();
     method public boolean hasWindowFocus();
-    method public boolean inMultiWindowMode();
-    method public boolean inPictureInPictureMode();
+    method public boolean inMultiWindow();
+    method public boolean inPictureInPicture();
     method public void invalidateOptionsMenu();
     method public boolean isChangingConfigurations();
     method public final boolean isChild();
@@ -3503,7 +3506,7 @@
     method public void onLowMemory();
     method public boolean onMenuItemSelected(int, android.view.MenuItem);
     method public boolean onMenuOpened(int, android.view.Menu);
-    method public void onMultiWindowModeChanged(boolean);
+    method public void onMultiWindowChanged(boolean);
     method public boolean onNavigateUp();
     method public boolean onNavigateUpFromChild(android.app.Activity);
     method protected void onNewIntent(android.content.Intent);
@@ -3511,7 +3514,7 @@
     method public void onOptionsMenuClosed(android.view.Menu);
     method public void onPanelClosed(int, android.view.Menu);
     method protected void onPause();
-    method public void onPictureInPictureModeChanged(boolean);
+    method public void onPictureInPictureChanged(boolean);
     method protected void onPostCreate(android.os.Bundle);
     method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
     method protected void onPostResume();
@@ -4422,9 +4425,11 @@
     method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
     method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
     method public void onLowMemory();
+    method public void onMultiWindowChanged(boolean);
     method public boolean onOptionsItemSelected(android.view.MenuItem);
     method public void onOptionsMenuClosed(android.view.Menu);
     method public void onPause();
+    method public void onPictureInPictureChanged(boolean);
     method public void onPrepareOptionsMenu(android.view.Menu);
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method public void onResume();
@@ -4505,9 +4510,11 @@
     method public void dispatchDestroy();
     method public void dispatchDestroyView();
     method public void dispatchLowMemory();
+    method public void dispatchMultiWindowChanged(boolean);
     method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
     method public void dispatchOptionsMenuClosed(android.view.Menu);
     method public void dispatchPause();
+    method public void dispatchPictureInPictureChanged(boolean);
     method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
     method public void dispatchResume();
     method public void dispatchStart();
@@ -5707,6 +5714,7 @@
     method public static android.app.WallpaperManager getInstance(android.content.Context);
     method public android.app.WallpaperInfo getWallpaperInfo();
     method public boolean hasResourceWallpaper(int);
+    method public boolean isWallpaperSettingAllowed();
     method public boolean isWallpaperSupported();
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
@@ -6316,6 +6324,22 @@
     field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
   }
 
+  public class DataUsagePolicy {
+    field public final int networkType;
+    field public final java.lang.String[] subscriberIds;
+    field public final long thresholdInBytes;
+    field public final int[] uids;
+  }
+
+  public static class DataUsagePolicy.Builder {
+    ctor public DataUsagePolicy.Builder();
+    method public android.app.usage.DataUsagePolicy.Builder addSubscriberId(java.lang.String);
+    method public android.app.usage.DataUsagePolicy.Builder addUid(int);
+    method public android.app.usage.DataUsagePolicy build();
+    method public android.app.usage.DataUsagePolicy.Builder setNetworkType(int);
+    method public android.app.usage.DataUsagePolicy.Builder setThreshold(long);
+  }
+
   public final class NetworkStats implements java.lang.AutoCloseable {
     method public void close();
     method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
@@ -6330,6 +6354,7 @@
     method public long getRxPackets();
     method public long getStartTimeStamp();
     method public int getState();
+    method public int getTag();
     method public long getTxBytes();
     method public long getTxPackets();
     method public int getUid();
@@ -6339,6 +6364,8 @@
     field public static final int STATE_ALL = -1; // 0xffffffff
     field public static final int STATE_DEFAULT = 1; // 0x1
     field public static final int STATE_FOREGROUND = 2; // 0x2
+    field public static final int TAG_ALL = 0; // 0x0
+    field public static final int TAG_ANY = -1; // 0xffffffff
     field public static final int UID_ALL = -1; // 0xffffffff
     field public static final int UID_REMOVED = -4; // 0xfffffffc
     field public static final int UID_TETHERING = -5; // 0xfffffffb
@@ -6347,9 +6374,20 @@
   public class NetworkStatsManager {
     method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
     method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
+    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback);
+    method public void registerDataUsageCallback(android.app.usage.DataUsagePolicy, android.app.usage.NetworkStatsManager.DataUsageCallback, android.os.Handler);
+    method public void unregisterDataUsageCallback(android.app.usage.NetworkStatsManager.DataUsageCallback);
+  }
+
+  public static class NetworkStatsManager.DataUsageCallback {
+    ctor public NetworkStatsManager.DataUsageCallback();
+    method public void onLimitReached();
   }
 
   public final class UsageEvents implements android.os.Parcelable {
@@ -7873,6 +7911,7 @@
     field public static final java.lang.String SYNC_EXTRAS_INITIALIZE = "initialize";
     field public static final java.lang.String SYNC_EXTRAS_MANUAL = "force";
     field public static final java.lang.String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
+    field public static final java.lang.String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging";
     field public static final java.lang.String SYNC_EXTRAS_UPLOAD = "upload";
     field public static final int SYNC_OBSERVER_TYPE_ACTIVE = 4; // 0x4
     field public static final int SYNC_OBSERVER_TYPE_PENDING = 2; // 0x2
@@ -8052,6 +8091,7 @@
     field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10
     field public static final int BIND_AUTO_CREATE = 1; // 0x1
     field public static final int BIND_DEBUG_UNBIND = 2; // 0x2
+    field public static final int BIND_EXTERNAL_SERVICE = -2147483648; // 0x80000000
     field public static final int BIND_IMPORTANT = 64; // 0x40
     field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
     field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20
@@ -9065,6 +9105,7 @@
     method public android.content.SyncRequest.Builder setIgnoreSettings(boolean);
     method public android.content.SyncRequest.Builder setManual(boolean);
     method public android.content.SyncRequest.Builder setNoRetry(boolean);
+    method public android.content.SyncRequest.Builder setRequiresCharging(boolean);
     method public android.content.SyncRequest.Builder setSyncAdapter(android.accounts.Account, java.lang.String);
     method public android.content.SyncRequest.Builder syncOnce();
     method public android.content.SyncRequest.Builder syncPeriodic(long, long);
@@ -9738,6 +9779,7 @@
     field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
     field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
     field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
+    field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
     field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
     field public static final java.lang.String FEATURE_WEBVIEW = "android.software.webview";
     field public static final java.lang.String FEATURE_WIFI = "android.hardware.wifi";
@@ -9909,6 +9951,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     field public static final android.os.Parcelable.Creator<android.content.pm.ServiceInfo> CREATOR;
+    field public static final int FLAG_EXTERNAL_SERVICE = 4; // 0x4
     field public static final int FLAG_ISOLATED_PROCESS = 2; // 0x2
     field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
     field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1
@@ -19109,38 +19152,7 @@
     method public static boolean isPresent();
   }
 
-  public abstract interface GnssNmeaListener {
-    method public abstract void onNmeaReceived(long, java.lang.String);
-  }
-
-  public final class GnssStatus {
-    method public float getAzimuth(int);
-    method public int getConstellationType(int);
-    method public float getElevation(int);
-    method public int getNumSatellites();
-    method public int getPrn(int);
-    method public float getSnr(int);
-    method public boolean hasAlmanac(int);
-    method public boolean hasEphemeris(int);
-    method public boolean usedInFix(int);
-    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
-    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
-    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
-    field public static final int CONSTELLATION_GPS = 1; // 0x1
-    field public static final int CONSTELLATION_QZSS = 4; // 0x4
-    field public static final int CONSTELLATION_SBAS = 2; // 0x2
-    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
-  }
-
-  public 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 final class GpsClock implements android.os.Parcelable {
+  public final class GnssClock implements android.os.Parcelable {
     method public int describeContents();
     method public double getBiasInNs();
     method public double getBiasUncertaintyInNs();
@@ -19167,7 +19179,7 @@
     method public void resetFullBiasInNs();
     method public void resetLeapSecond();
     method public void resetTimeUncertaintyInNs();
-    method public void set(android.location.GpsClock);
+    method public void set(android.location.GnssClock);
     method public void setBiasInNs(double);
     method public void setBiasUncertaintyInNs(double);
     method public void setDriftInNsPerSec(double);
@@ -19182,13 +19194,13 @@
     field public static final byte CLOCK_TYPE_GPS_TIME = 2; // 0x2
     field public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1; // 0x1
     field public static final byte CLOCK_TYPE_UNKNOWN = 0; // 0x0
-    field public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
 
-  public static abstract class GpsClock.GpsClockType implements java.lang.annotation.Annotation {
+  public static abstract class GnssClock.GnssClockType implements java.lang.annotation.Annotation {
   }
 
-  public final class GpsMeasurement implements android.os.Parcelable {
+  public final class GnssMeasurement implements android.os.Parcelable {
     method public int describeContents();
     method public double getAccumulatedDeltaRangeInMeters();
     method public short getAccumulatedDeltaRangeState();
@@ -19259,7 +19271,7 @@
     method public void resetPseudorangeUncertaintyInMeters();
     method public void resetSnrInDb();
     method public void resetTimeFromLastBitInMs();
-    method public void set(android.location.GpsMeasurement);
+    method public void set(android.location.GnssMeasurement);
     method public void setAccumulatedDeltaRangeInMeters(double);
     method public void setAccumulatedDeltaRangeState(short);
     method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
@@ -19298,7 +19310,7 @@
     field public static final short ADR_STATE_RESET = 2; // 0x2
     field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
     field public static final short ADR_STATE_VALID = 1; // 0x1
-    field public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
     field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
     field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
     field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
@@ -19313,34 +19325,34 @@
     field public static final short STATE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GpsMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+  public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
   }
 
-  public static abstract class GpsMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
+  public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
   }
 
-  public final class GpsMeasurementsEvent implements android.os.Parcelable {
-    ctor public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
+  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.GpsClock getClock();
-    method public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
+    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.GpsMeasurementsEvent> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
     field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract class GpsMeasurementsEvent.Callback {
-    ctor public GpsMeasurementsEvent.Callback();
-    method public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
+  public static abstract class GnssMeasurementsEvent.Callback {
+    ctor public GnssMeasurementsEvent.Callback();
+    method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GpsMeasurementsEvent.GpsMeasurementsStatus implements java.lang.annotation.Annotation {
+  public static abstract class GnssMeasurementsEvent.GnssMeasurementsStatus implements java.lang.annotation.Annotation {
   }
 
-  public final class GpsNavigationMessage implements android.os.Parcelable {
+  public final class GnssNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
@@ -19349,7 +19361,7 @@
     method public short getSubmessageId();
     method public byte getType();
     method public void reset();
-    method public void set(android.location.GpsNavigationMessage);
+    method public void set(android.location.GnssNavigationMessage);
     method public void setData(byte[]);
     method public void setMessageId(short);
     method public void setPrn(byte);
@@ -19357,7 +19369,7 @@
     method public void setSubmessageId(short);
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
     field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
     field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
     field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
@@ -19368,27 +19380,58 @@
     field public static final short STATUS_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GpsNavigationMessage.GpsNavigationMessageType implements java.lang.annotation.Annotation {
+  public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
   }
 
-  public final class GpsNavigationMessageEvent implements android.os.Parcelable {
-    ctor public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
+  public final class GnssNavigationMessageEvent implements android.os.Parcelable {
+    ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
     method public int describeContents();
-    method public android.location.GpsNavigationMessage getNavigationMessage();
+    method public android.location.GnssNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
+    field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
     field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract class GpsNavigationMessageEvent.Callback {
-    ctor public GpsNavigationMessageEvent.Callback();
-    method public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
+  public static abstract class GnssNavigationMessageEvent.Callback {
+    ctor public GnssNavigationMessageEvent.Callback();
+    method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GpsNavigationMessageEvent.GpsNavigationMessageStatus implements java.lang.annotation.Annotation {
+  public static abstract class GnssNavigationMessageEvent.GnssNavigationMessageStatus implements java.lang.annotation.Annotation {
+  }
+
+  public abstract interface GnssNmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public final class GnssStatus {
+    method public float getAzimuth(int);
+    method public int getConstellationType(int);
+    method public float getElevation(int);
+    method public int getNumSatellites();
+    method public int getPrn(int);
+    method public float getSnr(int);
+    method public boolean hasAlmanac(int);
+    method public boolean hasEphemeris(int);
+    method public boolean usedInFix(int);
+    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+    field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_QZSS = 4; // 0x4
+    field public static final int CONSTELLATION_SBAS = 2; // 0x2
+    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+  }
+
+  public 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 final class GpsSatellite {
@@ -19493,12 +19536,12 @@
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
     method public boolean isProviderEnabled(java.lang.String);
+    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean 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 registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
-    method public boolean registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback, android.os.Handler);
-    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback);
-    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.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);
@@ -19519,9 +19562,9 @@
     method public void setTestProviderEnabled(java.lang.String, boolean);
     method public void setTestProviderLocation(java.lang.String, android.location.Location);
     method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
+    method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
-    method public void unregisterGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
-    method public void unregisterGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.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";
@@ -23389,6 +23432,7 @@
     method public void unregisterNetworkCallback(android.app.PendingIntent);
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
     field public static final java.lang.String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
+    field public static final java.lang.String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED";
     field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
     field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
     field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
@@ -23438,6 +23482,12 @@
     method public int getUid();
   }
 
+  public class DataUsageRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.DataUsageRequest> CREATOR;
+  }
+
   public class DhcpInfo implements android.os.Parcelable {
     ctor public DhcpInfo();
     method public int describeContents();
@@ -24304,22 +24354,6 @@
 
 package android.net.wifi {
 
-  public class ScanInfo implements android.os.Parcelable {
-    ctor public ScanInfo(android.net.wifi.ScanResult);
-    ctor public ScanInfo(long, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int);
-    method public int describeContents();
-    method public long getBssid();
-    method public byte[] getIconData();
-    method public java.lang.String getIconType();
-    method public java.lang.String getName();
-    method public int getOsuIdentity();
-    method public int getRssi();
-    method public android.net.wifi.ScanResult getScanResult();
-    method public java.lang.String getServiceDescription();
-    method public java.lang.String getSsid();
-    method public void writeToParcel(android.os.Parcel, int);
-  }
-
   public class ScanResult implements android.os.Parcelable {
     method public int describeContents();
     method public boolean is80211mcResponder();
@@ -24480,6 +24514,7 @@
     field public static final int SIM = 4; // 0x4
     field public static final int TLS = 1; // 0x1
     field public static final int TTLS = 2; // 0x2
+    field public static final int UNAUTH_TLS = 7; // 0x7
   }
 
   public static final class WifiEnterpriseConfig.Phase2 {
@@ -24522,7 +24557,6 @@
     method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
     method public android.net.wifi.WifiInfo getConnectionInfo();
     method public android.net.DhcpInfo getDhcpInfo();
-    method public java.util.List<android.net.wifi.ScanInfo> getScanInfos();
     method public java.util.List<android.net.wifi.ScanResult> getScanResults();
     method public int getWifiState();
     method public boolean is5GHzBandSupported();
@@ -24538,7 +24572,6 @@
     method public boolean reconnect();
     method public boolean removeNetwork(int);
     method public boolean saveConfiguration();
-    method public void setOsuSelection(int);
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
     method public boolean setWifiEnabled(boolean);
@@ -28535,6 +28568,7 @@
     field public static java.lang.String DIRECTORY_DCIM;
     field public static java.lang.String DIRECTORY_DOCUMENTS;
     field public static java.lang.String DIRECTORY_DOWNLOADS;
+    field public static java.lang.String DIRECTORY_HOME;
     field public static java.lang.String DIRECTORY_MOVIES;
     field public static java.lang.String DIRECTORY_MUSIC;
     field public static java.lang.String DIRECTORY_NOTIFICATIONS;
@@ -29271,6 +29305,7 @@
     field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
     field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
     field public static final java.lang.String DISALLOW_SET_USER_ICON = "no_set_user_icon";
+    field public static final java.lang.String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
     field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
     field public static final java.lang.String DISALLOW_SMS = "no_sms";
     field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
@@ -30137,6 +30172,7 @@
   }
 
   public class BlockedNumberContract {
+    method public static boolean canCurrentUserBlockNumbers(android.content.Context);
     method public static boolean isBlocked(android.content.Context, java.lang.String);
     field public static final java.lang.String AUTHORITY = "com.android.blockednumber";
     field public static final android.net.Uri AUTHORITY_URI;
@@ -30146,7 +30182,6 @@
     field public static final java.lang.String COLUMN_E164_NUMBER = "e164_number";
     field public static final java.lang.String COLUMN_ID = "_id";
     field public static final java.lang.String COLUMN_ORIGINAL_NUMBER = "original_number";
-    field public static final java.lang.String COLUMN_STRIPPED_NUMBER = "stripped_number";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/blocked_number";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/blocked_numbers";
     field public static final android.net.Uri CONTENT_URI;
@@ -31657,14 +31692,13 @@
     field public static final java.lang.String COLUMN_MIME_TYPE = "mime_type";
     field public static final java.lang.String COLUMN_SIZE = "_size";
     field public static final java.lang.String COLUMN_SUMMARY = "summary";
-    field public static final int FLAG_ARCHIVE = 1024; // 0x400
     field public static final int FLAG_DIR_PREFERS_GRID = 16; // 0x10
     field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
     field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
     field public static final int FLAG_SUPPORTS_COPY = 128; // 0x80
     field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
     field public static final int FLAG_SUPPORTS_MOVE = 256; // 0x100
-    field public static final int FLAG_SUPPORTS_REMOVE = 2048; // 0x800
+    field public static final int FLAG_SUPPORTS_REMOVE = 1024; // 0x400
     field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40
     field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
     field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
@@ -32090,6 +32124,7 @@
     field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
     field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
     field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
+    field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
     field public static final java.lang.String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS = "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
@@ -34348,6 +34383,9 @@
     ctor public MediaBrowserService.BrowserRoot(java.lang.String, android.os.Bundle);
     method public android.os.Bundle getExtras();
     method public java.lang.String getRootId();
+    field public static final java.lang.String EXTRA_OFFLINE = "android.service.media.extra.OFFLINE";
+    field public static final java.lang.String EXTRA_RECENT = "android.service.media.extra.RECENT";
+    field public static final java.lang.String EXTRA_SUGGESTED = "android.service.media.extra.SUGGESTED";
   }
 
   public class MediaBrowserService.Result {
@@ -34360,6 +34398,7 @@
 package android.service.notification {
 
   public class Condition implements android.os.Parcelable {
+    ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
     method public android.service.notification.Condition copy();
     method public int describeContents();
@@ -34391,7 +34430,6 @@
     method public final void notifyConditions(android.service.notification.Condition...);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract void onConnected();
-    method public abstract void onRequestConditions(int);
     method public abstract void onSubscribe(android.net.Uri);
     method public abstract void onUnsubscribe(android.net.Uri);
     field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
@@ -34401,38 +34439,6 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
-  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
-    ctor public NotificationAssistantService();
-    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
-    method public final void clearAnnotation(java.lang.String);
-    method public void onNotificationActionClick(java.lang.String, long, int);
-    method public void onNotificationClick(java.lang.String, long);
-    method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
-    method public void onNotificationRemoved(java.lang.String, long, int);
-    method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
-    method public final void setAnnotation(java.lang.String, android.app.Notification);
-    field public static final int REASON_APP_CANCEL = 8; // 0x8
-    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
-    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
-    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
-    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
-    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
-    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
-    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
-    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
-    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
-    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
-    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
-    field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
-    field public static final int REASON_TOPIC_BANNED = 14; // 0xe
-    field public static final int REASON_USER_STOPPED = 6; // 0x6
-    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
-  }
-
-  public class NotificationAssistantService.Adjustment {
-    ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
-  }
-
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -36332,6 +36338,7 @@
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
+    method public void launchManageBlockedNumbersActivity();
     method public void placeCall(android.net.Uri, android.os.Bundle);
     method public void registerPhoneAccount(android.telecom.PhoneAccount);
     method public void showInCallScreen(boolean);
@@ -36452,6 +36459,7 @@
     field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
     field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
+    field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int";
     field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
     field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
     field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
@@ -40049,7 +40057,6 @@
     method public static android.util.LocaleList getDefault();
     method public static android.util.LocaleList getEmptyLocaleList();
     method public java.util.Locale getFirstMatch(java.lang.String[]);
-    method public java.util.Locale getPrimary();
     method public int indexOf(java.util.Locale);
     method public boolean isEmpty();
     method public static void setDefault(android.util.LocaleList);
@@ -43258,7 +43265,7 @@
     method public abstract void setNavigationBarColor(int);
     method public void setReenterTransition(android.transition.Transition);
     method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
-    method public final void setRestrictedCaptionAreaListener(android.view.Window.RestrictedCaptionAreaListener);
+    method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
     method public void setReturnTransition(android.transition.Transition);
     method public void setSharedElementEnterTransition(android.transition.Transition);
     method public void setSharedElementExitTransition(android.transition.Transition);
@@ -43345,7 +43352,7 @@
     method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
   }
 
-  public static abstract interface Window.RestrictedCaptionAreaListener {
+  public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
     method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
   }
 
@@ -43693,6 +43700,7 @@
     method public boolean isEnabled();
     method public boolean isFocusable();
     method public boolean isFocused();
+    method public boolean isImportantForAccessibility();
     method public boolean isLongClickable();
     method public boolean isMultiLine();
     method public boolean isPassword();
@@ -43731,6 +43739,7 @@
     method public void setError(java.lang.CharSequence);
     method public void setFocusable(boolean);
     method public void setFocused(boolean);
+    method public void setImportantForAccessibility(boolean);
     method public void setInputType(int);
     method public void setLabelFor(android.view.View);
     method public void setLabelFor(android.view.View, int);
@@ -50185,13 +50194,16 @@
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method public T getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
@@ -50722,7 +50734,10 @@
   public class Package implements java.lang.reflect.AnnotatedElement {
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public java.lang.String getImplementationTitle();
     method public java.lang.String getImplementationVendor();
     method public java.lang.String getImplementationVersion();
@@ -51416,7 +51431,10 @@
     ctor protected AccessibleObject();
     method public T getAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public T[] getAnnotationsByType(java.lang.Class<T>);
+    method public java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public boolean isAccessible();
     method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
     method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException;
@@ -51426,7 +51444,10 @@
   public abstract interface AnnotatedElement {
     method public abstract T getAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getAnnotations();
+    method public abstract T[] getAnnotationsByType(java.lang.Class<T>);
+    method public abstract java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
     method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method public abstract T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
     method public abstract boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
   }
 
@@ -52541,7 +52562,6 @@
     method public static void setURLStreamHandlerFactory(java.net.URLStreamHandlerFactory);
     method public java.lang.String toExternalForm();
     method public java.net.URI toURI() throws java.net.URISyntaxException;
-    method public java.net.URI toURILenient() throws java.net.URISyntaxException;
   }
 
   public class URLClassLoader extends java.security.SecureClassLoader implements java.io.Closeable {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 2c6729d..0bf6594 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -199,6 +199,14 @@
 
 }
 
+package android.service.notification {
+
+  public abstract class ConditionProviderService extends android.app.Service {
+    method public void onRequestConditions(int);
+  }
+
+}
+
 package android.test.mock {
 
   public deprecated class MockPackageManager extends android.content.pm.PackageManager {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 8187468..acc68cf 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -21,10 +21,12 @@
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
 import static android.app.ActivityManager.RESIZE_MODE_USER;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 
 import android.app.ActivityManager;
 import android.app.ActivityManager.StackInfo;
 import android.app.ActivityManagerNative;
+import android.app.ActivityOptions;
 import android.app.IActivityContainer;
 import android.app.IActivityController;
 import android.app.IActivityManager;
@@ -106,6 +108,7 @@
     private String mProfileFile;
     private int mSamplingInterval;
     private boolean mAutoStop;
+    private int mStackId;
 
     /**
      * Command-line entry point.
@@ -192,6 +195,7 @@
                 "    --track-allocation: enable tracking of object allocations\n" +
                 "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
                 "        specified then run as the current user.\n" +
+                "    --stack <STACK_ID>: Specify into which stack should the activity be put." +
                 "\n" +
                 "am startservice: start a Service.  Options are:\n" +
                 "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
@@ -468,6 +472,7 @@
         mSamplingInterval = 0;
         mAutoStop = false;
         mUserId = defUser;
+        mStackId = FULLSCREEN_WORKSPACE_STACK_ID;
 
         return Intent.parseCommandArgs(mArgs, new Intent.CommandOptionHandler() {
             @Override
@@ -496,6 +501,8 @@
                     mUserId = parseUserArg(nextArgRequired());
                 } else if (opt.equals("--receiver-permission")) {
                     mReceiverPermission = nextArgRequired();
+                } else if (opt.equals("--stack")) {
+                    mStackId = Integer.parseInt(nextArgRequired());
                 } else {
                     return false;
                 }
@@ -553,6 +560,7 @@
             mimeType = mAm.getProviderMimeType(intent.getData(), mUserId);
         }
 
+
         do {
             if (mStopOption) {
                 String packageName;
@@ -607,13 +615,20 @@
             IActivityManager.WaitResult result = null;
             int res;
             final long startTime = SystemClock.uptimeMillis();
+            ActivityOptions options = null;
+            if (mStackId != FULLSCREEN_WORKSPACE_STACK_ID) {
+                options = ActivityOptions.makeBasic();
+                options.setLaunchStackId(mStackId);
+            }
             if (mWaitOption) {
                 result = mAm.startActivityAndWait(null, null, intent, mimeType,
-                            null, null, 0, mStartFlags, profilerInfo, null, mUserId);
+                        null, null, 0, mStartFlags, profilerInfo,
+                        options != null ? options.toBundle() : null, mUserId);
                 res = result.result;
             } else {
                 res = mAm.startActivityAsUser(null, null, intent, mimeType,
-                        null, null, 0, mStartFlags, profilerInfo, null, mUserId);
+                        null, null, 0, mStartFlags, profilerInfo,
+                        options != null ? options.toBundle() : null, mUserId);
             }
             final long endTime = SystemClock.uptimeMillis();
             PrintStream out = mWaitOption ? System.out : System.err;
@@ -1762,18 +1777,33 @@
             System.err.println("Error: invalid input bounds");
             return;
         }
-        resizeStack(stackId, bounds, 0, false);
+        resizeStack(stackId, bounds, 0);
     }
 
     private void runStackResizeAnimated() throws Exception {
         String stackIdStr = nextArgRequired();
         int stackId = Integer.valueOf(stackIdStr);
-        final Rect bounds = getBounds();
-        if (bounds == null) {
-            System.err.println("Error: invalid input bounds");
-            return;
+        final Rect bounds;
+        if ("null".equals(mArgs.peekNextArg())) {
+            bounds = null;
+        } else {
+            bounds = getBounds();
+            if (bounds == null) {
+                System.err.println("Error: invalid input bounds");
+                return;
+            }
         }
-        resizeStack(stackId, bounds, 0, true);
+        resizeStackUnchecked(stackId, bounds, 0, true);
+    }
+
+    private void resizeStackUnchecked(int stackId, Rect bounds, int delayMs, boolean animate) {
+        try {
+            mAm.resizeStack(stackId, bounds, false, false, animate);
+            Thread.sleep(delayMs);
+        } catch (RemoteException e) {
+            showError("Error: resizing stack " + e);
+        } catch (InterruptedException e) {
+        }
     }
 
     private void runStackResizeDocked() throws Exception {
@@ -1790,20 +1820,13 @@
         }
     }
 
-    private void resizeStack(int stackId, Rect bounds, int delayMs, boolean animate)
+    private void resizeStack(int stackId, Rect bounds, int delayMs)
             throws Exception {
         if (bounds == null) {
             showError("Error: invalid input bounds");
             return;
         }
-
-        try {
-            mAm.resizeStack(stackId, bounds, false, false, animate);
-            Thread.sleep(delayMs);
-        } catch (RemoteException e) {
-            showError("Error: resizing stack " + e);
-        } catch (InterruptedException e) {
-        }
+        resizeStackUnchecked(stackId, bounds, delayMs, false);
     }
 
     private void runStackPositionTask() throws Exception {
@@ -1912,7 +1935,7 @@
             maxChange = Math.min(stepSize, currentPoint - minPoint);
             currentPoint -= maxChange;
             setBoundsSide(bounds, side, currentPoint);
-            resizeStack(DOCKED_STACK_ID, bounds, delayMs, false);
+            resizeStack(DOCKED_STACK_ID, bounds, delayMs);
         }
 
         System.out.println("Growing docked stack side=" + side);
@@ -1920,7 +1943,7 @@
             maxChange = Math.min(stepSize, maxPoint - currentPoint);
             currentPoint += maxChange;
             setBoundsSide(bounds, side, currentPoint);
-            resizeStack(DOCKED_STACK_ID, bounds, delayMs, false);
+            resizeStack(DOCKED_STACK_ID, bounds, delayMs);
         }
 
         System.out.println("Back to Original size side=" + side);
@@ -1928,7 +1951,7 @@
             maxChange = Math.min(stepSize, currentPoint - startPoint);
             currentPoint -= maxChange;
             setBoundsSide(bounds, side, currentPoint);
-            resizeStack(DOCKED_STACK_ID, bounds, delayMs, false);
+            resizeStack(DOCKED_STACK_ID, bounds, delayMs);
         }
     }
 
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 35695c4..1d9e3bb 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -430,46 +430,47 @@
     }
 
     /**
-     * List every {@link Account} registered on the device that are managed by
-     * applications whose signatures match the caller.
+     * Lists all accounts of any type registered on the device.
+     * Equivalent to getAccountsByType(null).
      *
-     * <p>This method can be called safely from the main thread. It is
-     * equivalent to calling <code>getAccountsByType(null)</code>.
+     * <p>It is safe to call this method from the main thread.
      *
-     * <p><b>NOTE:</b> Apps declaring a {@code targetSdkVersion<=23} in their
-     * manifests will continue to behave as they did on devices that support
-     * API level 23. In particular the GET_ACCOUNTS permission is required to
-     * see all the Accounts registered with the AccountManager. See docs for
-     * this function in API level 23 for more information.
+     * <p>Clients of this method that have not been granted the
+     * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
+     * will only see those accounts managed by AbstractAccountAuthenticators whose
+     * signature matches the client.
      *
-     * @return Array of Accounts. The array may be empty if no accounts are
-     *     available to the caller.
+     * @return An array of {@link Account}, one for each account.  Empty
+     *     (never null) if no accounts have been added.
      */
     @NonNull
+    @RequiresPermission(GET_ACCOUNTS)
     public Account[] getAccounts() {
-        return getAccountsByType(null);
+        try {
+            return mService.getAccounts(null, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            // won't ever happen
+            throw new RuntimeException(e);
+        }
     }
 
     /**
      * @hide
-     * List every {@link Account} registered on the device for a specific User
-     * that are managed by applications whose signatures match the caller.
+     * Lists all accounts of any type registered on the device for a given
+     * user id. Equivalent to getAccountsByType(null).
      *
-     * <p><b>NOTE:</b> Apps declaring a {@code targetSdkVersion<=23} in their
-     * manifests will continue to behave as they did on devices that support
-     * API level 23. In particular the GET_ACCOUNTS permission is required to
-     * see all the Accounts registered with the AccountManager for the
-     * specified userId. See docs for this function in API level 23 for more
-     * information.
+     * <p>It is safe to call this method from the main thread.
      *
-     * <p>This method can be called safely from the main thread.
+     * <p>Clients of this method that have not been granted the
+     * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
+     * will only see those accounts managed by AbstractAccountAuthenticators whose
+     * signature matches the client.
      *
-     * @param int userId associated with the User whose accounts should be
-     *     queried.
-     * @return Array of Accounts. The array may be empty if no accounts are
-     *     available to the caller.
+     * @return An array of {@link Account}, one for each account.  Empty
+     *     (never null) if no accounts have been added.
      */
     @NonNull
+    @RequiresPermission(GET_ACCOUNTS)
     public Account[] getAccountsAsUser(int userId) {
         try {
             return mService.getAccountsAsUser(null, userId, mContext.getOpPackageName());
@@ -500,11 +501,10 @@
     /**
      * Returns the accounts visible to the specified package, in an environment where some apps
      * are not authorized to view all accounts. This method can only be called by system apps.
-     *
      * @param type The type of accounts to return, null to retrieve all accounts
      * @param packageName The package name of the app for which the accounts are to be returned
-     * @return Array of Accounts. The array may be empty if no accounts of th
-     *     specified type are visible to the caller.
+     * @return An array of {@link Account}, one per matching account.  Empty
+     *     (never null) if no accounts of the specified type have been added.
      */
     @NonNull
     public Account[] getAccountsByTypeForPackage(String type, String packageName) {
@@ -518,22 +518,29 @@
     }
 
     /**
-     * List every {@link Account} of a specified type managed by applications
-     * whose signatures match the caller.
+     * Lists all accounts of a particular type.  The account type is a
+     * string token corresponding to the authenticator and useful domain
+     * of the account.  For example, there are types corresponding to Google
+     * and Facebook.  The exact string token to use will be published somewhere
+     * associated with the authenticator in question.
      *
-     * <p><b>NOTE:</b> Apps declaring a {@code targetSdkVersion<=23} in their
-     * manifests will continue to behave as they did on devices that support
-     * API level 23. See docs for this function in API level 23 for more
-     * information.
+     * <p>It is safe to call this method from the main thread.
      *
-     * <p>This method can be called safely from the main thread.
+     * <p>Clients of this method that have not been granted the
+     * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
+     * will only see those accounts managed by AbstractAccountAuthenticators whose
+     * signature matches the client.
      *
-     * @param type String denoting the type of the accounts to return,
-     *        {@code null} to retrieve all accounts visible to the caller.
-     * @return An array of Accounts.  Empty (never null) if no accounts
-     *         are available to the caller.
+     * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
+     * GET_ACCOUNTS permission is needed for those platforms, irrespective of uid
+     * or signature match. See docs for this function in API level 22.
+     *
+     * @param type The type of accounts to return, null to retrieve all accounts
+     * @return An array of {@link Account}, one per matching account.  Empty
+     *     (never null) if no accounts of the specified type have been added.
      */
     @NonNull
+    @RequiresPermission(GET_ACCOUNTS)
     public Account[] getAccountsByType(String type) {
         return getAccountsByTypeAsUser(type, Process.myUserHandle());
     }
@@ -579,7 +586,6 @@
      * @return a future containing the label string
      * @hide
      */
-    @NonNull
     public AccountManagerFuture<String> getAuthTokenLabel(
             final String accountType, final String authTokenType,
             AccountManagerCallback<String> callback, Handler handler) {
@@ -612,13 +618,9 @@
      * <p>This method may be called from any thread, but the returned
      * {@link AccountManagerFuture} must not be used on the main thread.
      *
-     * <p><b>Note:</b>The specified account must be managed by an application
-     * whose signature matches the caller.
-     *
-     * <p><b>Further note:</b>Apps targeting API level 23 or earlier will continue to
-     * behave as they did on devices that support API level 23. In particular
-     * they may still require the GET_ACCOUNTS permission. See docs for this
-     * function in API level 23.
+     * <p>This method requires the caller to hold the permission
+     * {@link android.Manifest.permission#GET_ACCOUNTS} or be a signature
+     * match with the AbstractAccountAuthenticator that manages the account.
      *
      * @param account The {@link Account} to test
      * @param features An array of the account features to check
@@ -627,11 +629,9 @@
      * @param handler {@link Handler} identifying the callback thread,
      *     null for the main thread
      * @return An {@link AccountManagerFuture} which resolves to a Boolean,
-     *     true if the account exists and has all of the specified features.
-     * @throws SecurityException if the specified account is managed by an
-     *     application whose signature doesn't match the caller's signature.
+     * true if the account exists and has all of the specified features.
      */
-    @NonNull
+    @RequiresPermission(GET_ACCOUNTS)
     public AccountManagerFuture<Boolean> hasFeatures(final Account account,
             final String[] features,
             AccountManagerCallback<Boolean> callback, Handler handler) {
@@ -654,10 +654,9 @@
 
     /**
      * Lists all accounts of a type which have certain features.  The account
-     * type identifies the authenticator (see {@link #getAccountsByType}). Said
-     * authenticator must be in a package whose signature matches the callers
-     * package signature. Account features are authenticator-specific string tokens
-     * identifying boolean account properties (see {@link #hasFeatures}).
+     * type identifies the authenticator (see {@link #getAccountsByType}).
+     * Account features are authenticator-specific string tokens identifying
+     * boolean account properties (see {@link #hasFeatures}).
      *
      * <p>Unlike {@link #getAccountsByType}, this method calls the authenticator,
      * which may contact the server or do other work to check account features,
@@ -666,14 +665,19 @@
      * <p>This method may be called from any thread, but the returned
      * {@link AccountManagerFuture} must not be used on the main thread.
      *
-     * <p><b>NOTE:</b> Apps targeting API level 23 or earlier will continue to
-     * behave as they did on devices that support API level 23. In particular
-     * they may still require the GET_ACCOUNTS permission. See docs for this
-     * function in API level 23.
+     * <p>Clients of this method that have not been granted the
+     * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
+     * will only see those accounts managed by AbstractAccountAuthenticators whose
+     * signature matches the client.
      *
      * @param type The type of accounts to return, must not be null
      * @param features An array of the account features to require,
      *     may be null or empty
+     *
+     * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
+     * GET_ACCOUNTS permission is needed for those platforms, irrespective of uid
+     * or signature match. See docs for this function in API level 22.
+     *
      * @param callback Callback to invoke when the request completes,
      *     null for no callback
      * @param handler {@link Handler} identifying the callback thread,
@@ -682,7 +686,7 @@
      *     {@link Account}, one per account of the specified type which
      *     matches the requested features.
      */
-    @NonNull
+    @RequiresPermission(GET_ACCOUNTS)
     public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures(
             final String type, final String[] features,
             AccountManagerCallback<Account[]> callback, Handler handler) {
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 1ab55dd..980329f 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1030,6 +1030,20 @@
         }
     }
 
+    /**
+     * @hide
+     * TODO: For animatorSet defined in XML, we can use a flag to indicate what the play order
+     * if defined (i.e. sequential or together), then we can use the flag instead of calculate
+     * dynamically.
+     * @return whether all the animators in the set are supposed to play together
+     */
+    public boolean shouldPlayTogether() {
+        updateAnimatorsDuration();
+        createDependencyGraph();
+        // All the child nodes are set out to play right after the delay animation
+        return mRootNode.mChildNodes.size() == mNodes.size() - 1;
+    }
+
     @Override
     public long getTotalDuration() {
         updateAnimatorsDuration();
diff --git a/core/java/android/animation/PathKeyframes.java b/core/java/android/animation/PathKeyframes.java
index 2a47b68..8230ac5 100644
--- a/core/java/android/animation/PathKeyframes.java
+++ b/core/java/android/animation/PathKeyframes.java
@@ -231,7 +231,7 @@
         }
     }
 
-    private abstract static class IntKeyframesBase extends SimpleKeyframes implements IntKeyframes {
+    abstract static class IntKeyframesBase extends SimpleKeyframes implements IntKeyframes {
         @Override
         public Class getType() {
             return Integer.class;
@@ -243,7 +243,7 @@
         }
     }
 
-    private abstract static class FloatKeyframesBase extends SimpleKeyframes
+    abstract static class FloatKeyframesBase extends SimpleKeyframes
             implements FloatKeyframes {
         @Override
         public Class getType() {
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index e993cca..6ba5b96 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -21,6 +21,7 @@
 import android.util.FloatProperty;
 import android.util.IntProperty;
 import android.util.Log;
+import android.util.PathParser;
 import android.util.Property;
 
 import java.lang.reflect.InvocationTargetException;
@@ -1046,6 +1047,43 @@
         return mAnimatedValue;
     }
 
+    /**
+     * PropertyValuesHolder is Animators use to hold internal animation related data.
+     * Therefore, in order to replicate the animation behavior, we need to get data out of
+     * PropertyValuesHolder.
+     * @hide
+     */
+    public void getPropertyValues(PropertyValues values) {
+        init();
+        values.propertyName = mPropertyName;
+        values.type = mValueType;
+        values.startValue = mKeyframes.getValue(0);
+        if (values.startValue instanceof PathParser.PathData) {
+            // PathData evaluator returns the same mutable PathData object when query fraction,
+            // so we have to make a copy here.
+            values.startValue = new PathParser.PathData((PathParser.PathData) values.startValue);
+        }
+        values.endValue = mKeyframes.getValue(1);
+        if (values.endValue instanceof PathParser.PathData) {
+            // PathData evaluator returns the same mutable PathData object when query fraction,
+            // so we have to make a copy here.
+            values.endValue = new PathParser.PathData((PathParser.PathData) values.endValue);
+        }
+        // TODO: We need a better way to get data out of keyframes.
+        if (mKeyframes instanceof PathKeyframes.FloatKeyframesBase
+                || mKeyframes instanceof PathKeyframes.IntKeyframesBase) {
+            // property values will animate based on external data source (e.g. Path)
+            values.dataSource = new PropertyValues.DataSource() {
+                @Override
+                public Object getValueAtFraction(float fraction) {
+                    return mKeyframes.getValue(fraction);
+                }
+            };
+        } else {
+            values.dataSource = null;
+        }
+    }
+
     @Override
     public String toString() {
         return mPropertyName + ": " + mKeyframes.toString();
@@ -1601,6 +1639,24 @@
         }
     };
 
+    /**
+     * @hide
+     */
+    public static class PropertyValues {
+        public String propertyName;
+        public Class type;
+        public Object startValue;
+        public Object endValue;
+        public DataSource dataSource = null;
+        public interface DataSource {
+            Object getValueAtFraction(float fraction);
+        }
+        public String toString() {
+            return ("property name: " + propertyName + ", type: " + type + ", startValue: "
+                    + startValue.toString() + ", endValue: " + endValue.toString());
+        }
+    }
+
     native static private long nGetIntMethod(Class targetClass, String methodName);
     native static private long nGetFloatMethod(Class targetClass, String methodName);
     native static private long nGetMultipleIntMethod(Class targetClass, String methodName,
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 75a19f4..e0eb389 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -62,7 +62,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
 import android.media.AudioManager;
 import android.media.session.MediaController;
 import android.net.Uri;
@@ -72,7 +71,6 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Parcelable;
-import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.StrictMode;
 import android.os.UserHandle;
@@ -80,16 +78,12 @@
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.method.TextKeyListener;
-import android.transition.Scene;
-import android.transition.TransitionManager;
-import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.SuperNotCalledException;
 import android.view.ActionMode;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -110,16 +104,11 @@
 import android.view.ViewManager;
 import android.view.ViewRootImpl;
 import android.view.Window;
-import android.view.Window.WindowControllerCallback;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
-import android.widget.Toolbar;
 
-import com.android.internal.app.IVoiceInteractor;
-import com.android.internal.app.ToolbarActionBar;
-import com.android.internal.app.WindowDecorActionBar;
 import com.android.internal.policy.PhoneWindow;
 
 import java.io.FileDescriptor;
@@ -1688,7 +1677,8 @@
             final char alphaShortcut = item.getAlphabeticShortcut();
             if (title != null && alphaShortcut != MIN_VALUE) {
                 if (group == null) {
-                    group = new KeyboardShortcutGroup(null /* no label */);
+                    final int resource = mApplication.getApplicationInfo().labelRes;
+                    group = new KeyboardShortcutGroup(resource != 0 ? getString(resource) : null);
                 }
                 group.addItem(new KeyboardShortcutInfo(
                     title, alphaShortcut, KeyEvent.META_CTRL_ON));
@@ -1842,14 +1832,15 @@
      * visa-versa.
      * @see android.R.attr#resizeableActivity
      *
-     * @param multiWindowMode True if the activity is in multi-window mode.
+     * @param inMultiWindow True if the activity is in multi-window mode.
      */
     @CallSuper
-    public void onMultiWindowModeChanged(boolean multiWindowMode) {
+    public void onMultiWindowChanged(boolean inMultiWindow) {
         if (DEBUG_LIFECYCLE) Slog.v(TAG,
-                "onMultiWindowModeChanged " + this + ": " + multiWindowMode);
+                "onMultiWindowChanged " + this + ": " + inMultiWindow);
+        mFragments.dispatchMultiWindowChanged(inMultiWindow);
         if (mWindow != null) {
-            mWindow.onMultiWindowModeChanged();
+            mWindow.onMultiWindowChanged();
         }
     }
 
@@ -1859,9 +1850,9 @@
      *
      * @return True if the activity is in multi-window mode.
      */
-    public boolean inMultiWindowMode() {
+    public boolean inMultiWindow() {
         try {
-            return ActivityManagerNative.getDefault().inMultiWindowMode(mToken);
+            return ActivityManagerNative.getDefault().inMultiWindow(mToken);
         } catch (RemoteException e) {
         }
         return false;
@@ -1871,11 +1862,13 @@
      * Called by the system when the activity changes to and from picture-in-picture mode.
      * @see android.R.attr#supportsPictureInPicture
      *
-     * @param pictureInPictureMode True if the activity is in picture-in-picture mode.
+     * @param inPictureInPicture True if the activity is in picture-in-picture mode.
      */
-    public void onPictureInPictureModeChanged(boolean pictureInPictureMode) {
+    @CallSuper
+    public void onPictureInPictureChanged(boolean inPictureInPicture) {
         if (DEBUG_LIFECYCLE) Slog.v(TAG,
-                "onPictureInPictureModeChanged " + this + ": " + pictureInPictureMode);
+                "onPictureInPictureChanged " + this + ": " + inPictureInPicture);
+        mFragments.dispatchPictureInPictureChanged(inPictureInPicture);
     }
 
     /**
@@ -1884,9 +1877,9 @@
      *
      * @return True if the activity is in picture-in-picture mode.
      */
-    public boolean inPictureInPictureMode() {
+    public boolean inPictureInPicture() {
         try {
-            return ActivityManagerNative.getDefault().inPictureInPictureMode(mToken);
+            return ActivityManagerNative.getDefault().inPictureInPicture(mToken);
         } catch (RemoteException e) {
         }
         return false;
@@ -1896,9 +1889,9 @@
      * Puts the activity in picture-in-picture mode.
      * @see android.R.attr#supportsPictureInPicture
      */
-    public void enterPictureInPictureMode() {
+    public void enterPictureInPicture() {
         try {
-            ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken);
+            ActivityManagerNative.getDefault().enterPictureInPicture(mToken);
         } catch (RemoteException e) {
         }
     }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index dc37a57..1eb2fe2 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -567,11 +567,13 @@
         }
 
         /**
-         * Returns true if the windows of tasks being moved to this stack should be preserved so
-         * there isn't a display gap.
+         * Returns true if the windows of tasks being moved to the target stack from the source
+         * stack should be replaced, meaning that window manager will keep the old window around
+         * until the new is ready.
          */
-        public static boolean preserveWindowOnTaskMove(int stackId) {
-            return stackId == FULLSCREEN_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID;
+        public static boolean replaceWindowsOnTaskMove(int sourceStackId, int targetStackId) {
+            return sourceStackId == FREEFORM_WORKSPACE_STACK_ID
+                    || targetStackId == FREEFORM_WORKSPACE_STACK_ID;
         }
 
         /**
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 138ff6d..a3160f4 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2842,26 +2842,26 @@
             reply.writeInt(res);
             return true;
         }
-        case IN_MULTI_WINDOW_MODE_TRANSACTION: {
+        case IN_MULTI_WINDOW_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             final IBinder token = data.readStrongBinder();
-            final boolean multiWindowMode = inMultiWindowMode(token);
+            final boolean inMultiWindow = inMultiWindow(token);
             reply.writeNoException();
-            reply.writeInt(multiWindowMode ? 1 : 0);
+            reply.writeInt(inMultiWindow ? 1 : 0);
             return true;
         }
-        case IN_PICTURE_IN_PICTURE_MODE_TRANSACTION: {
+        case IN_PICTURE_IN_PICTURE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             final IBinder token = data.readStrongBinder();
-            final boolean pipMode = inPictureInPictureMode(token);
+            final boolean inPip = inPictureInPicture(token);
             reply.writeNoException();
-            reply.writeInt(pipMode ? 1 : 0);
+            reply.writeInt(inPip ? 1 : 0);
             return true;
         }
-        case ENTER_PICTURE_IN_PICTURE_MODE_TRANSACTION: {
+        case ENTER_PICTURE_IN_PICTURE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             final IBinder token = data.readStrongBinder();
-            enterPictureInPictureMode(token);
+            enterPictureInPicture(token);
             reply.writeNoException();
             return true;
         }
@@ -6678,12 +6678,12 @@
     }
 
     @Override
-    public boolean inMultiWindowMode(IBinder token) throws RemoteException {
+    public boolean inMultiWindow(IBinder token) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        mRemote.transact(IN_MULTI_WINDOW_MODE_TRANSACTION, data, reply, 0);
+        mRemote.transact(IN_MULTI_WINDOW_TRANSACTION, data, reply, 0);
         reply.readException();
         final boolean multiWindowMode = reply.readInt() == 1 ? true : false;
         data.recycle();
@@ -6692,12 +6692,12 @@
     }
 
     @Override
-    public boolean inPictureInPictureMode(IBinder token) throws RemoteException {
+    public boolean inPictureInPicture(IBinder token) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        mRemote.transact(IN_PICTURE_IN_PICTURE_MODE_TRANSACTION, data, reply, 0);
+        mRemote.transact(IN_PICTURE_IN_PICTURE_TRANSACTION, data, reply, 0);
         reply.readException();
         final boolean pipMode = reply.readInt() == 1 ? true : false;
         data.recycle();
@@ -6706,12 +6706,12 @@
     }
 
     @Override
-    public void enterPictureInPictureMode(IBinder token) throws RemoteException {
+    public void enterPictureInPicture(IBinder token) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
-        mRemote.transact(ENTER_PICTURE_IN_PICTURE_MODE_TRANSACTION, data, reply, 0);
+        mRemote.transact(ENTER_PICTURE_IN_PICTURE_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 99c275c..6424520 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -53,7 +53,6 @@
 import android.net.Proxy;
 import android.net.ProxyInfo;
 import android.net.Uri;
-import android.opengl.GLUtils;
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Build;
@@ -84,7 +83,6 @@
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
-import android.util.LocaleList;
 import android.util.Log;
 import android.util.LogPrinter;
 import android.util.Pair;
@@ -1245,15 +1243,15 @@
         }
 
         @Override
-        public void scheduleMultiWindowModeChanged(IBinder token, boolean multiWindowMode)
+        public void scheduleMultiWindowChanged(IBinder token, boolean inMultiWindow)
                 throws RemoteException {
-            sendMessage(H.MULTI_WINDOW_MODE_CHANGED, token, multiWindowMode ? 1 : 0);
+            sendMessage(H.MULTI_WINDOW_CHANGED, token, inMultiWindow ? 1 : 0);
         }
 
         @Override
-        public void schedulePictureInPictureModeChanged(IBinder token, boolean pipMode)
+        public void schedulePictureInPictureChanged(IBinder token, boolean inPip)
                 throws RemoteException {
-            sendMessage(H.PICTURE_IN_PICTURE_MODE_CHANGED, token, pipMode ? 1 : 0);
+            sendMessage(H.PICTURE_IN_PICTURE_CHANGED, token, inPip ? 1 : 0);
         }
 
         @Override
@@ -1325,8 +1323,8 @@
         public static final int ENTER_ANIMATION_COMPLETE = 149;
         public static final int START_BINDER_TRACKING = 150;
         public static final int STOP_BINDER_TRACKING_AND_DUMP = 151;
-        public static final int MULTI_WINDOW_MODE_CHANGED = 152;
-        public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153;
+        public static final int MULTI_WINDOW_CHANGED = 152;
+        public static final int PICTURE_IN_PICTURE_CHANGED = 153;
         public static final int LOCAL_VOICE_INTERACTION_STARTED = 154;
 
         String codeToString(int code) {
@@ -1381,8 +1379,8 @@
                     case CANCEL_VISIBLE_BEHIND: return "CANCEL_VISIBLE_BEHIND";
                     case BACKGROUND_VISIBLE_BEHIND_CHANGED: return "BACKGROUND_VISIBLE_BEHIND_CHANGED";
                     case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE";
-                    case MULTI_WINDOW_MODE_CHANGED: return "MULTI_WINDOW_MODE_CHANGED";
-                    case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED";
+                    case MULTI_WINDOW_CHANGED: return "MULTI_WINDOW_CHANGED";
+                    case PICTURE_IN_PICTURE_CHANGED: return "PICTURE_IN_PICTURE_CHANGED";
                     case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED";
                 }
             }
@@ -1627,11 +1625,11 @@
                 case STOP_BINDER_TRACKING_AND_DUMP:
                     handleStopBinderTrackingAndDump((ParcelFileDescriptor) msg.obj);
                     break;
-                case MULTI_WINDOW_MODE_CHANGED:
-                    handleMultiWindowModeChanged((IBinder) msg.obj, msg.arg1 == 1);
+                case MULTI_WINDOW_CHANGED:
+                    handleMultiWindowChanged((IBinder) msg.obj, msg.arg1 == 1);
                     break;
-                case PICTURE_IN_PICTURE_MODE_CHANGED:
-                    handlePictureInPictureModeChanged((IBinder) msg.obj, msg.arg1 == 1);
+                case PICTURE_IN_PICTURE_CHANGED:
+                    handlePictureInPictureChanged((IBinder) msg.obj, msg.arg1 == 1);
                     break;
                 case LOCAL_VOICE_INTERACTION_STARTED:
                     handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
@@ -2880,17 +2878,17 @@
         }
     }
 
-    private void handleMultiWindowModeChanged(IBinder token, boolean multiWindowMode) {
+    private void handleMultiWindowChanged(IBinder token, boolean inMultiWindow) {
         final ActivityClientRecord r = mActivities.get(token);
         if (r != null) {
-            r.activity.onMultiWindowModeChanged(multiWindowMode);
+            r.activity.onMultiWindowChanged(inMultiWindow);
         }
     }
 
-    private void handlePictureInPictureModeChanged(IBinder token, boolean pipMode) {
+    private void handlePictureInPictureChanged(IBinder token, boolean inPip) {
         final ActivityClientRecord r = mActivities.get(token);
         if (r != null) {
-            r.activity.onPictureInPictureModeChanged(pipMode);
+            r.activity.onPictureInPictureChanged(inPip);
         }
     }
 
@@ -4781,12 +4779,6 @@
             return;
         }
         final ApplicationInfo appInfo = loadedApk.getApplicationInfo();
-        if (isSharingRuntime(appInfo)) {
-            // If sharing is enabled we do not have a unique application
-            // in a process and therefore cannot rely on the package
-            // name inside the runtime.
-            return;
-        }
         final List<String> codePaths = new ArrayList<>();
         if ((appInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
             codePaths.add(appInfo.sourceDir);
@@ -4829,46 +4821,13 @@
                 codePaths.toArray(new String[codePaths.size()]));
     }
 
-    /*
-     * Two possible indications that this package could be
-     * sharing its runtime with other packages:
-     *
-     * 1) the sharedUserId attribute is set in the manifest,
-     *    indicating a request to share a VM with other
-     *    packages with the same sharedUserId.
-     *
-     * 2) the application element of the manifest has an
-     *    attribute specifying a non-default process name,
-     *    indicating the desire to run in another packages VM.
-     */
-    private static boolean isSharingRuntime(ApplicationInfo appInfo) {
-        IPackageManager pm = getPackageManager();
-        android.content.pm.PackageInfo pi = null;
-        try {
-            pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId());
-        } catch (RemoteException e) {
-        }
-        if (pi != null) {
-            boolean sharedUserIdSet = (pi.sharedUserId != null);
-            boolean processNameNotDefault = (pi.applicationInfo != null) &&
-                    !appInfo.packageName.equals(pi.applicationInfo.processName);
-            boolean sharable = sharedUserIdSet || processNameNotDefault;
-            return sharable;
-        }
-        // We couldn't get information for the package. Be pessimistic and assume
-        // it's sharing the runtime.
-        return true;
-    }
-
     private void updateDefaultDensity() {
-        if (mCurDefaultDisplayDpi != Configuration.DENSITY_DPI_UNDEFINED
-                && mCurDefaultDisplayDpi != DisplayMetrics.DENSITY_DEVICE
-                && !mDensityCompatMode) {
-            Slog.i(TAG, "Switching default density from "
-                    + DisplayMetrics.DENSITY_DEVICE + " to "
-                    + mCurDefaultDisplayDpi);
-            DisplayMetrics.DENSITY_DEVICE = mCurDefaultDisplayDpi;
-            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
+        final int densityDpi = mCurDefaultDisplayDpi;
+        if (!mDensityCompatMode
+                && densityDpi != Configuration.DENSITY_DPI_UNDEFINED
+                && densityDpi != DisplayMetrics.DENSITY_DEVICE) {
+            DisplayMetrics.DENSITY_DEVICE = densityDpi;
+            Bitmap.setDefaultDensity(densityDpi);
         }
     }
 
@@ -5061,7 +5020,7 @@
         }
 
         final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
-        if (!Process.isIsolated()) {
+        if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {
             final File cacheDir = appContext.getCacheDir();
             if (cacheDir != null) {
                 // Provide a usable directory for temporary files
@@ -5080,6 +5039,10 @@
                 Log.e(TAG, "Unable to setupGraphicsSupport and setupJitProfileSupport " +
                         "due to missing code-cache directory");
             }
+
+            // Add the lib dir path to hardware renderer so that vulkan layers
+            // can be searched for within that directory.
+            ThreadedRenderer.setLibDir(data.info.getLibDir());
         }
 
         // Install the Network Security Config Provider. This must happen before the application
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 220fb607..c071162 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -326,8 +326,7 @@
                 // This is a temporary hack. Callers must use
                 // createPackageContext(packageName).getApplicationInfo() to
                 // get the right paths.
-                maybeAdjustApplicationInfo(ai);
-                return ai;
+                return maybeAdjustApplicationInfo(ai);
             }
         } catch (RemoteException e) {
             throw new RuntimeException("Package manager has died", e);
@@ -336,7 +335,7 @@
         throw new NameNotFoundException(packageName);
     }
 
-    private static void maybeAdjustApplicationInfo(ApplicationInfo info) {
+    private static ApplicationInfo maybeAdjustApplicationInfo(ApplicationInfo info) {
         // If we're dealing with a multi-arch application that has both
         // 32 and 64 bit shared libraries, we might need to choose the secondary
         // depending on what the current runtime's instruction set is.
@@ -353,9 +352,12 @@
             // Everything will be set up correctly because info.nativeLibraryDir will
             // correspond to the right ISA.
             if (runtimeIsa.equals(secondaryIsa)) {
-                info.nativeLibraryDir = info.secondaryNativeLibraryDir;
+                ApplicationInfo modified = new ApplicationInfo(info);
+                modified.nativeLibraryDir = info.secondaryNativeLibraryDir;
+                return modified;
             }
         }
+        return info;
     }
 
     @Override
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 9be7f23..59ecc03 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -730,21 +730,21 @@
             return true;
         }
 
-        case SCHEDULE_MULTI_WINDOW_MODE_CHANGED_TRANSACTION:
+        case SCHEDULE_MULTI_WINDOW_CHANGED_TRANSACTION:
         {
             data.enforceInterface(IApplicationThread.descriptor);
             final IBinder b = data.readStrongBinder();
-            final boolean multiWindowMode = data.readInt() != 0;
-            scheduleMultiWindowModeChanged(b, multiWindowMode);
+            final boolean inMultiWindow = data.readInt() != 0;
+            scheduleMultiWindowChanged(b, inMultiWindow);
             return true;
         }
 
-        case SCHEDULE_PICTURE_IN_PICTURE_MODE_CHANGED_TRANSACTION:
+        case SCHEDULE_PICTURE_IN_PICTURE_CHANGED_TRANSACTION:
         {
             data.enforceInterface(IApplicationThread.descriptor);
             final IBinder b = data.readStrongBinder();
-            final boolean pipMode = data.readInt() != 0;
-            schedulePictureInPictureModeChanged(b, pipMode);
+            final boolean inPip = data.readInt() != 0;
+            schedulePictureInPictureChanged(b, inPip);
             return true;
         }
 
@@ -1495,25 +1495,25 @@
     }
 
     @Override
-    public final void scheduleMultiWindowModeChanged(
-            IBinder token, boolean multiWindowMode) throws RemoteException {
+    public final void scheduleMultiWindowChanged(
+            IBinder token, boolean inMultiWindow) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
-        data.writeInt(multiWindowMode ? 1 : 0);
-        mRemote.transact(SCHEDULE_MULTI_WINDOW_MODE_CHANGED_TRANSACTION, data, null,
+        data.writeInt(inMultiWindow ? 1 : 0);
+        mRemote.transact(SCHEDULE_MULTI_WINDOW_CHANGED_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
     }
 
     @Override
-    public final void schedulePictureInPictureModeChanged(IBinder token, boolean pipMode)
+    public final void schedulePictureInPictureChanged(IBinder token, boolean inPip)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
-        data.writeInt(pipMode ? 1 : 0);
-        mRemote.transact(SCHEDULE_PICTURE_IN_PICTURE_MODE_CHANGED_TRANSACTION, data, null,
+        data.writeInt(inPip ? 1 : 0);
+        mRemote.transact(SCHEDULE_PICTURE_IN_PICTURE_CHANGED_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
     }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index c5b5b08..89d4931 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -182,8 +182,6 @@
     @GuardedBy("mSync")
     private File[] mExternalMediaDirs;
 
-    private static final String[] EMPTY_STRING_ARRAY = {};
-
     // The system service cache for the system services that are cached per-ContextImpl.
     final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
 
@@ -627,8 +625,7 @@
 
     @Override
     public String[] fileList() {
-        final String[] list = getFilesDir().list();
-        return (list != null) ? list : EMPTY_STRING_ARRAY;
+        return FileUtils.listOrEmpty(getFilesDir());
     }
 
     @Override
@@ -682,24 +679,23 @@
             dir = new File(dirPath);
             name = name.substring(name.lastIndexOf(File.separatorChar));
             f = new File(dir, name);
+
+            if (!dir.isDirectory() && dir.mkdir()) {
+                FileUtils.setPermissions(dir.getPath(),
+                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+                    -1, -1);
+            }
         } else {
             dir = getDatabasesDir();
             f = makeFilename(dir, name);
         }
 
-        if (!dir.isDirectory() && dir.mkdir()) {
-            FileUtils.setPermissions(dir.getPath(),
-                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-                -1, -1);
-        }
-
         return f;
     }
 
     @Override
     public String[] databaseList() {
-        final String[] list = getDatabasesDir().list();
-        return (list != null) ? list : EMPTY_STRING_ARRAY;
+        return FileUtils.listOrEmpty(getDatabasesDir());
     }
 
     private File getDatabasesDir() {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 20eaf0b..688c9f8 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1576,6 +1576,25 @@
     public void onSaveInstanceState(Bundle outState) {
     }
 
+    /**
+     * Called when the Fragment's activity changes from fullscreen mode to multi-window mode and
+     * visa-versa. This is generally tied to {@link Activity#onMultiWindowChanged} of the containing
+     * Activity.
+     *
+     * @param inMultiWindow True if the activity is in multi-window mode.
+     */
+    public void onMultiWindowChanged(boolean inMultiWindow) {
+    }
+
+    /**
+     * Called by the system when the activity changes to and from picture-in-picture mode. This is
+     * generally tied to {@link Activity#onPictureInPictureChanged} of the containing Activity.
+     *
+     * @param inPictureInPicture True if the activity is in picture-in-picture mode.
+     */
+    public void onPictureInPictureChanged(boolean inPictureInPicture) {
+    }
+
     public void onConfigurationChanged(Configuration newConfig) {
         mCalled = true;
     }
@@ -2308,6 +2327,20 @@
         }
     }
 
+    void performMultiWindowChanged(boolean inMultiWindow) {
+        onMultiWindowChanged(inMultiWindow);
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchMultiWindowChanged(inMultiWindow);
+        }
+    }
+
+    void performPictureInPictureChanged(boolean inPictureInPicture) {
+        onPictureInPictureChanged(inPictureInPicture);
+        if (mChildFragmentManager != null) {
+            mChildFragmentManager.dispatchPictureInPictureChanged(inPictureInPicture);
+        }
+    }
+
     void performConfigurationChanged(Configuration newConfig) {
         onConfigurationChanged(newConfig);
         if (mChildFragmentManager != null) {
diff --git a/core/java/android/app/FragmentController.java b/core/java/android/app/FragmentController.java
index 28dadfa..a9270bc 100644
--- a/core/java/android/app/FragmentController.java
+++ b/core/java/android/app/FragmentController.java
@@ -219,6 +219,28 @@
     }
 
     /**
+     * Lets all Fragments managed by the controller's FragmentManager know the multi-window mode of
+     * the activity changed.
+     * <p>Call when the multi-window mode of the activity changed.
+     *
+     * @see Fragment#onMultiWindowChanged
+     */
+    public void dispatchMultiWindowChanged(boolean inMultiWindow) {
+        mHost.mFragmentManager.dispatchMultiWindowChanged(inMultiWindow);
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager know the picture-in-picture
+     * mode of the activity changed.
+     * <p>Call when the picture-in-picture mode of the activity changed.
+     *
+     * @see Fragment#onPictureInPictureChanged
+     */
+    public void dispatchPictureInPictureChanged(boolean inPictureInPicture) {
+        mHost.mFragmentManager.dispatchPictureInPictureChanged(inPictureInPicture);
+    }
+
+    /**
      * Lets all Fragments managed by the controller's FragmentManager
      * know a configuration change occurred.
      * <p>Call when there is a configuration change.
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 84ae09d..32fec84 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1987,7 +1987,31 @@
         mContainer = null;
         mParent = null;
     }
-    
+
+    public void dispatchMultiWindowChanged(boolean inMultiWindow) {
+        if (mAdded == null) {
+            return;
+        }
+        for (int i = mAdded.size() - 1; i >= 0; --i) {
+            final Fragment f = mAdded.get(i);
+            if (f != null) {
+                f.performMultiWindowChanged(inMultiWindow);
+            }
+        }
+    }
+
+    public void dispatchPictureInPictureChanged(boolean inPictureInPicture) {
+        if (mAdded == null) {
+            return;
+        }
+        for (int i = mAdded.size() - 1; i >= 0; --i) {
+            final Fragment f = mAdded.get(i);
+            if (f != null) {
+                f.performPictureInPictureChanged(inPictureInPicture);
+            }
+        }
+    }
+
     public void dispatchConfigurationChanged(Configuration newConfig) {
         if (mAdded != null) {
             for (int i=0; i<mAdded.size(); i++) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index cefbb80..f5e7d78 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -581,11 +581,11 @@
 
     public int getAppStartMode(int uid, String packageName) throws RemoteException;
 
-    public boolean inMultiWindowMode(IBinder token) throws RemoteException;
+    public boolean inMultiWindow(IBinder token) throws RemoteException;
 
-    public boolean inPictureInPictureMode(IBinder token) throws RemoteException;
+    public boolean inPictureInPicture(IBinder token) throws RemoteException;
 
-    public void enterPictureInPictureMode(IBinder token) throws RemoteException;
+    public void enterPictureInPicture(IBinder token) throws RemoteException;
 
     public void setVrMode(IBinder token, boolean enabled) throws RemoteException;
 
@@ -958,10 +958,10 @@
     int MOVE_TOP_ACTIVITY_TO_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 349;
     int GET_APP_START_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 350;
     int UNLOCK_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 351;
-    int IN_MULTI_WINDOW_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 352;
-    int IN_PICTURE_IN_PICTURE_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 353;
+    int IN_MULTI_WINDOW_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 352;
+    int IN_PICTURE_IN_PICTURE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 353;
     int KILL_PACKAGE_DEPENDENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 354;
-    int ENTER_PICTURE_IN_PICTURE_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 355;
+    int ENTER_PICTURE_IN_PICTURE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 355;
     int ACTIVITY_RELAUNCHED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 356;
     int GET_URI_PERMISSION_OWNER_FOR_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 357;
     int RESIZE_DOCKED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 358;
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 6d64bd0..b55da88 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -152,8 +152,8 @@
     void notifyCleartextNetwork(byte[] firstPacket) throws RemoteException;
     void startBinderTracking() throws RemoteException;
     void stopBinderTrackingAndDump(FileDescriptor fd) throws RemoteException;
-    void scheduleMultiWindowModeChanged(IBinder token, boolean multiWindowMode) throws RemoteException;
-    void schedulePictureInPictureModeChanged(IBinder token, boolean multiWindowMode) throws RemoteException;
+    void scheduleMultiWindowChanged(IBinder token, boolean multiWindowMode) throws RemoteException;
+    void schedulePictureInPictureChanged(IBinder token, boolean multiWindowMode) throws RemoteException;
     void scheduleLocalVoiceInteractionStarted(IBinder token, IVoiceInteractor voiceInteractor) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
@@ -215,7 +215,7 @@
     int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+55;
     int START_BINDER_TRACKING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+56;
     int STOP_BINDER_TRACKING_AND_DUMP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+57;
-    int SCHEDULE_MULTI_WINDOW_MODE_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58;
-    int SCHEDULE_PICTURE_IN_PICTURE_MODE_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59;
+    int SCHEDULE_MULTI_WINDOW_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58;
+    int SCHEDULE_PICTURE_IN_PICTURE_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59;
     int SCHEDULE_LOCAL_VOICE_INTERACTION_STARTED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+60;
 }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 3288cd9..40e58af 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -55,6 +55,7 @@
     void setImportance(String pkg, int uid, in Notification.Topic topic, int importance);
     int getImportance(String pkg, int uid, in Notification.Topic topic);
     boolean doesAppUseTopics(String pkg, int uid);
+    boolean hasBannedTopics(String pkg, int uid);
 
     // TODO: Remove this when callers have been migrated to the equivalent
     // INotificationListener method.
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index fa0fbd1..04493cb 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -113,4 +113,9 @@
      * Check whether wallpapers are supported for the calling user.
      */
     boolean isWallpaperSupported(in String callingPackage);
+    
+    /**
+     * Check whether setting of wallpapers are allowed for the calling user.
+     */
+    boolean isWallpaperSettingAllowed(in String callingPackage);
 }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 1e22bef..da52c1e 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -382,6 +382,13 @@
                     libraryPermittedPath += File.pathSeparator +
                                             System.getProperty("java.library.path");
                 }
+                // DO NOT SHIP: this is a workaround for apps loading native libraries
+                // provided by 3rd party apps using absolute path instead of corresponding
+                // classloader; see http://b/26954419 for example.
+                if (mApplicationInfo.targetSdkVersion <= 23) {
+                    libraryPermittedPath += File.pathSeparator + "/data/app";
+                }
+                // -----------------------------------------------------------------------------
 
                 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
 
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7f037f2..a78076b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2623,9 +2623,6 @@
             if (onMs != 0 || offMs != 0) {
                 mN.flags |= FLAG_SHOW_LIGHTS;
             }
-            if ((mN.defaults & DEFAULT_LIGHTS) != 0) {
-                mN.flags |= FLAG_SHOW_LIGHTS;
-            }
             return this;
         }
 
@@ -3239,6 +3236,7 @@
                 return;
             }
             contentView.setTextViewText(R.id.app_name_text, appName);
+            contentView.setTextColor(R.id.app_name_text, resolveColor());
         }
 
         private void bindSmallIcon(RemoteViews contentView) {
@@ -3603,6 +3601,10 @@
                 mStyle.buildStyled(mN);
             }
 
+            if ((mN.defaults & DEFAULT_LIGHTS) != 0) {
+                mN.flags |= FLAG_SHOW_LIGHTS;
+            }
+
             return mN;
         }
 
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index b0ffd21..eda82c0 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -74,7 +74,8 @@
  * {@link #getInstance(android.content.Context) getInstance()}.
  *
  * <p> An app can check whether wallpapers are supported for the current user, by calling
- * {@link #isWallpaperSupported()}.
+ * {@link #isWallpaperSupported()}, and whether setting of wallpapers is allowed, by calling
+ * {@link #isWallpaperSettingAllowed()}.
  */
 public class WallpaperManager {
     private static String TAG = "WallpaperManager";
@@ -134,7 +135,7 @@
      * screen coordinates.
      */
     public static final String COMMAND_TAP = "android.wallpaper.tap";
-    
+
     /**
      * Command for {@link #sendWallpaperCommand}: reported by the wallpaper
      * host when the user releases a secondary pointer on an empty area
@@ -177,7 +178,7 @@
     public static final int FLAG_SET_LOCK = 1 << 1;
 
     private final Context mContext;
-    
+
     /**
      * Special drawable that draws a wallpaper as fast as possible.  Assumes
      * no scaling or placement off (0,0) of the wallpaper (this should be done
@@ -258,19 +259,19 @@
             return mHeight;
         }
     }
-    
+
     static class Globals extends IWallpaperManagerCallback.Stub {
         private IWallpaperManager mService;
         private Bitmap mWallpaper;
         private Bitmap mDefaultWallpaper;
-        
+
         private static final int MSG_CLEAR_WALLPAPER = 1;
-        
+
         Globals(Looper looper) {
             IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
             mService = IWallpaperManager.Stub.asInterface(b);
         }
-        
+
         public void onWallpaperChanged() {
             /* The wallpaper has changed but we shouldn't eagerly load the
              * wallpaper as that would be inefficient. Reset the cached wallpaper
@@ -366,7 +367,7 @@
             return null;
         }
     }
-    
+
     private static final Object sSync = new Object[0];
     private static Globals sGlobals;
 
@@ -377,7 +378,7 @@
             }
         }
     }
-    
+
     /*package*/ WallpaperManager(Context context, Handler handler) {
         mContext = context;
         initGlobals(context.getMainLooper());
@@ -390,18 +391,18 @@
         return (WallpaperManager)context.getSystemService(
                 Context.WALLPAPER_SERVICE);
     }
-    
+
     /** @hide */
     public IWallpaperManager getIWallpaperManager() {
         return sGlobals.mService;
     }
-    
+
     /**
      * Retrieve the current system wallpaper; if
      * no wallpaper is set, the system built-in static wallpaper is returned.
      * This is returned as an
      * abstract Drawable that you can install in a View to display whatever
-     * wallpaper the user has currently set. 
+     * wallpaper the user has currently set.
      *
      * @return Returns a Drawable object that will draw the wallpaper.
      */
@@ -588,7 +589,7 @@
      * Retrieve the current system wallpaper; if there is no wallpaper set,
      * a null pointer is returned. This is returned as an
      * abstract Drawable that you can install in a View to display whatever
-     * wallpaper the user has currently set.  
+     * wallpaper the user has currently set.
      *
      * @return Returns a Drawable object that will draw the wallpaper or a
      * null pointer if these is none.
@@ -641,7 +642,7 @@
 
     /**
      * Like {@link #getDrawable()} but returns a Bitmap.
-     * 
+     *
      * @hide
      */
     public Bitmap getBitmap() {
@@ -1248,7 +1249,7 @@
      * are floating point numbers ranging from 0 to 1, representing where the
      * wallpaper should be positioned within the screen space.  These only
      * make sense when the wallpaper is larger than the display.
-     * 
+     *
      * @param windowToken The window who these offsets should be associated
      * with, as returned by {@link android.view.View#getWindowToken()
      * View.getWindowToken()}.
@@ -1271,17 +1272,17 @@
      * specify the step size between virtual screens. For example, if the
      * launcher has 3 virtual screens, it would specify an xStep of 0.5,
      * since the X offset for those screens are 0.0, 0.5 and 1.0
-     * @param xStep The X offset delta from one screen to the next one 
+     * @param xStep The X offset delta from one screen to the next one
      * @param yStep The Y offset delta from one screen to the next one
      */
     public void setWallpaperOffsetSteps(float xStep, float yStep) {
         mWallpaperXStep = xStep;
         mWallpaperYStep = yStep;
     }
-    
+
     /**
      * Send an arbitrary command to the current active wallpaper.
-     * 
+     *
      * @param windowToken The window who these offsets should be associated
      * with, as returned by {@link android.view.View#getWindowToken()
      * View.getWindowToken()}.
@@ -1306,7 +1307,8 @@
 
     /**
      * Returns whether wallpapers are supported for the calling user. If this function returns
-     * false, any attempts to changing the wallpaper will have no effect.
+     * {@code false}, any attempts to changing the wallpaper will have no effect,
+     * and any attempt to obtain of the wallpaper will return {@code null}.
      */
     public boolean isWallpaperSupported() {
         if (sGlobals.mService == null) {
@@ -1322,11 +1324,31 @@
     }
 
     /**
+     * Returns whether the calling package is allowed to set the wallpaper for the calling user.
+     * If this function returns {@code false}, any attempts to change the wallpaper will have
+     * no effect. Always returns {@code true} for device owner and profile owner.
+     *
+     * @see android.os.UserManager#DISALLOW_SET_WALLPAPER
+     */
+    public boolean isWallpaperSettingAllowed() {
+        if (sGlobals.mService == null) {
+            Log.w(TAG, "WallpaperService not running");
+        } else {
+            try {
+                return sGlobals.mService.isWallpaperSettingAllowed(mContext.getOpPackageName());
+            } catch (RemoteException e) {
+                // Ignore
+            }
+        }
+        return false;
+    }
+
+    /**
      * Clear the offsets previously associated with this window through
      * {@link #setWallpaperOffsets(IBinder, float, float)}.  This reverts
      * the window to its default state, where it does not cause the wallpaper
      * to scroll from whatever its last offsets were.
-     * 
+     *
      * @param windowToken The window who these offsets should be associated
      * with, as returned by {@link android.view.View#getWindowToken()
      * View.getWindowToken()}.
@@ -1339,7 +1361,7 @@
             // Ignore.
         }
     }
-    
+
     /**
      * Remove any currently set wallpaper, reverting to the system's built-in
      * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index f04e76e..02eb115 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -241,6 +241,48 @@
 
     /**
      * Activity action: Starts the provisioning flow which sets up a managed device.
+     *
+     * <p>During device owner provisioning, a device admin app is downloaded and set as the owner of
+     * the device. A device owner has full control over the device. The device owner can not be
+     * modified by the user and the only way of resetting the device is via factory reset.
+     *
+     * <p>A typical use case would be a device that is owned by a company, but used by either an
+     * employee or client.
+     *
+     * <p>The provisioning message should be sent to an unprovisioned device.
+     *
+     * <p>Unlike {@link #ACTION_PROVISION_MANAGED_DEVICE}, the provisioning message can only be sent
+     * by a privileged app with the permission
+     * {@link android.Manifest.permission#DISPATCH_PROVISIONING_MESSAGE}.
+     *
+     * <p>The provisioning intent contains the following properties:
+     * <ul>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_LOCAL_TIME} (convert to String), optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_TIME_ZONE}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_LOCALE}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_SSID}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_HIDDEN} (convert to String), optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_SECURITY_TYPE}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_PASSWORD}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_HOST}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_PORT} (convert to String), optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_BYPASS}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li></ul>
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @SystemApi
+    public static final String ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE =
+            "android.app.action.PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE";
+
+    /**
+     * Activity action: Starts the provisioning flow which sets up a managed device.
      * Must be started with {@link android.app.Activity#startActivityForResult(Intent, int)}.
      *
      * <p>NOTE: This is only supported on split system user devices, and puts the device into a
@@ -3474,8 +3516,7 @@
     public boolean isProfileOwnerApp(String packageName) {
         if (mService != null) {
             try {
-                ComponentName profileOwner = mService.getProfileOwner(
-                        Process.myUserHandle().getIdentifier());
+                ComponentName profileOwner = mService.getProfileOwner(myUserId());
                 return profileOwner != null
                         && profileOwner.getPackageName().equals(packageName);
             } catch (RemoteException re) {
@@ -4068,6 +4109,29 @@
     }
 
     /**
+     * Called by the system to check if a specific accessibility service is disabled by admin.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName Accessibility service package name that needs to be checked.
+     * @param userHandle user id the admin is running as.
+     * @return true if the accessibility service is permitted, otherwise false.
+     *
+     * @hide
+     */
+    public boolean isAccessibilityServicePermittedByAdmin(@NonNull ComponentName admin,
+            @NonNull String packageName, int userHandle) {
+        if (mService != null) {
+            try {
+                return mService.isAccessibilityServicePermittedByAdmin(admin, packageName,
+                        userHandle);
+            } catch (RemoteException e) {
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Returns the list of accessibility services permitted by the device or profiles
      * owners of this user.
      *
@@ -4147,6 +4211,28 @@
     }
 
     /**
+     * Called by the system to check if a specific input method is disabled by admin.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName Input method package name that needs to be checked.
+     * @param userHandle user id the admin is running as.
+     * @return true if the input method is permitted, otherwise false.
+     *
+     * @hide
+     */
+    public boolean isInputMethodPermittedByAdmin(@NonNull ComponentName admin,
+            @NonNull String packageName, int userHandle) {
+        if (mService != null) {
+            try {
+                return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle);
+            } catch (RemoteException e) {
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Returns the list of input methods permitted by the device or profiles
      * owners of the current user.  (*Not* calling user, due to a limitation in InputMethodManager.)
      *
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index b57e1b7..c6a5344 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -174,10 +174,12 @@
     boolean setPermittedAccessibilityServices(in ComponentName admin,in List packageList);
     List getPermittedAccessibilityServices(in ComponentName admin);
     List getPermittedAccessibilityServicesForUser(int userId);
+    boolean isAccessibilityServicePermittedByAdmin(in ComponentName admin, String packageName, int userId);
 
     boolean setPermittedInputMethods(in ComponentName admin,in List packageList);
     List getPermittedInputMethods(in ComponentName admin);
     List getPermittedInputMethodsForCurrentUser();
+    boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId);
 
     boolean setApplicationHidden(in ComponentName admin, in String packageName, boolean hidden);
     boolean isApplicationHidden(in ComponentName admin, in String packageName);
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 0143797..5398e7f 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -23,6 +23,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
+import android.util.Log;
+import static android.util.TimeUtils.formatForLogging;
 
 import java.util.ArrayList;
 
@@ -35,6 +37,7 @@
  * accomplish. Doing otherwise with throw an exception in your app.
  */
 public class JobInfo implements Parcelable {
+    private static String TAG = "JobInfo";
     /** Default. */
     public static final int NETWORK_TYPE_NONE = 0;
     /** This job requires network connectivity. */
@@ -526,7 +529,8 @@
         /**
          * Specify that this job should recur with the provided interval and flex. The job can
          * execute at any time in a window of flex length at the end of the period.
-         * @param intervalMillis Millisecond interval for which this job will repeat.
+         * @param intervalMillis Millisecond interval for which this job will repeat. A minimum
+         *                       value of {@link #MIN_PERIOD_MILLIS} is enforced.
          * @param flexMillis Millisecond flex for this job. Flex is clamped to be at least
          *                   {@link #MIN_FLEX_MILLIS} or 5 percent of the period, whichever is
          *                   higher.
@@ -635,7 +639,18 @@
                         " back-off policy, so calling setBackoffCriteria with" +
                         " setRequiresDeviceIdle is an error.");
             }
-            return new JobInfo(this);
+            JobInfo job = new JobInfo(this);
+            if (job.intervalMillis != job.getIntervalMillis()) {
+                Log.w(TAG, "Specified interval for " + mJobService.getPackageName() + " is "
+                        + formatForLogging(mIntervalMillis) + ". Clamped to " +
+                        formatForLogging(job.getIntervalMillis()));
+            }
+            if (job.flexMillis != job.getFlexMillis()) {
+                Log.w(TAG, "Specified interval for " + mJobService.getPackageName() + " is "
+                        + formatForLogging(mFlexMillis) + ". Clamped to " +
+                        formatForLogging(job.getFlexMillis()));
+            }
+            return job;
         }
     }
 
diff --git a/core/java/android/app/usage/DataUsagePolicy.java b/core/java/android/app/usage/DataUsagePolicy.java
new file mode 100644
index 0000000..5a5dcbc
--- /dev/null
+++ b/core/java/android/app/usage/DataUsagePolicy.java
@@ -0,0 +1,174 @@
+/**
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package android.app.usage;
+
+import android.net.ConnectivityManager;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.IntArray;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Defines a policy for data usage callbacks, made through {@link DataUsagePolicy.Builder} and used
+ * to be notified on data usage via {@link NetworkStatsManager#registerDataUsageCallback}.
+ */
+public class DataUsagePolicy {
+
+    /**
+     * Network type to be monitored, as defined in {@link ConnectivityManager}, e.g.
+     * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} etc.
+     */
+    public final int networkType;
+
+    /**
+     * Set of subscriber ids to be monitored for the given network type. May be empty if not
+     * applicable.
+     * <p>Should not be modified once created.
+     */
+    public final String[] subscriberIds;
+
+    /**
+     * Set of UIDs of which to monitor data usage.
+     *
+     * <p>If not {@code null}, the caller will be notified when any of the uids exceed
+     * the given threshold. If empty all uids for which the calling process has access
+     * to stats will be monitored.
+     * <p>Should not be modified once created.
+     */
+    public final int[] uids;
+
+    /**
+     * Threshold in bytes to be notified on.
+     */
+    public final long thresholdInBytes;
+
+    /**
+     * @hide
+     */
+    DataUsagePolicy(int networkType, String[] subscriberIds, int[] uids,
+                long thresholdInBytes) {
+        this.networkType = networkType;
+        this.subscriberIds = subscriberIds;
+        this.uids = uids;
+        this.thresholdInBytes = thresholdInBytes;
+    }
+
+    /**
+     * Builder used to create {@link DataUsagePolicy} objects.
+     */
+    public static class Builder {
+        private static final int INVALID_NETWORK_TYPE = -1;
+        private int mNetworkType = INVALID_NETWORK_TYPE;
+        private List<String> mSubscriberList = new ArrayList<>();
+        private IntArray mUids = new IntArray();
+        private long mThresholdInBytes;
+
+        /**
+         * Default constructor for Builder.
+         */
+        public Builder() {}
+
+        /**
+         * Build {@link DataUsagePolicy} given the current policies.
+         */
+        public DataUsagePolicy build() {
+            if (mNetworkType == INVALID_NETWORK_TYPE) {
+                throw new IllegalArgumentException(
+                        "DataUsagePolicy requires a valid network type to be set");
+            }
+            return new DataUsagePolicy(mNetworkType,
+                    mSubscriberList.toArray(new String[mSubscriberList.size()]),
+                    mUids.toArray(), mThresholdInBytes);
+        }
+
+        /**
+         * Specifies that the given {@code subscriberId} should be monitored.
+         *
+         * @param subscriberId the subscriber id of the network interface.
+         */
+        public Builder addSubscriberId(String subscriberId) {
+            mSubscriberList.add(subscriberId);
+            return this;
+        }
+
+        /**
+         * Specifies that the given {@code uid} should be monitored.
+         */
+        public Builder addUid(int uid) {
+            mUids.add(uid);
+            return this;
+        }
+
+        /**
+         * Specifies that the callback should monitor the given network. It is mandatory
+         * to set one.
+         *
+         * @param networkType As defined in {@link ConnectivityManager}, e.g.
+         *            {@link ConnectivityManager#TYPE_MOBILE},
+         *            {@link ConnectivityManager#TYPE_WIFI}, etc.
+         */
+        public Builder setNetworkType(int networkType) {
+            mNetworkType = networkType;
+            return this;
+        }
+
+        /**
+         * Sets the threshold in bytes on which the listener should be called. The framework may
+         * impose a minimum threshold to avoid too many notifications to be triggered.
+         */
+        public Builder setThreshold(long thresholdInBytes) {
+            mThresholdInBytes = thresholdInBytes;
+            return this;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "DataUsagePolicy [ networkType=" + networkType
+                + ", subscriberIds=" + Arrays.toString(subscriberIds)
+                + ", uids=" + Arrays.toString(uids)
+                + ", thresholdInBytes=" + thresholdInBytes + " ]";
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof DataUsagePolicy == false) return false;
+        DataUsagePolicy that = (DataUsagePolicy) obj;
+        return that.networkType == this.networkType
+                && Arrays.deepEquals(that.subscriberIds, this.subscriberIds)
+                && Arrays.equals(that.uids, this.uids)
+                && that.thresholdInBytes == this.thresholdInBytes;
+    }
+
+    @Override
+    public int hashCode() {
+        // Start with a non-zero constant.
+        int result = 17;
+
+        // Include a hash for each field.
+        result = 31 * result + networkType;
+        result = 31 * result + Arrays.deepHashCode(subscriberIds);
+        result = 31 * result + Arrays.hashCode(uids);
+        result = 31 * result + (int) (thresholdInBytes ^ (thresholdInBytes >>> 32));
+
+        return result;
+   }
+}
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index 5622207..9f1a9cf0 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -48,7 +48,6 @@
      */
     private final long mEndTimeStamp;
 
-
     /**
      * Non-null array indicates the query enumerates over uids.
      */
@@ -165,7 +164,18 @@
          */
         public static final int ROAMING_ROAMING = 0x2;
 
+        /**
+         * Special TAG value matching any tag.
+         */
+        public static final int TAG_ANY = android.net.NetworkStats.TAG_ALL;
+
+        /**
+         * Special TAG value for total data across all tags
+         */
+        public static final int TAG_ALL = android.net.NetworkStats.TAG_NONE;
+
         private int mUid;
+        private int mTag;
         private int mState;
         private int mRoaming;
         private long mBeginTimeStamp;
@@ -192,6 +202,14 @@
             return uid;
         }
 
+        private static int convertTag(int tag) {
+            switch (tag) {
+                case android.net.NetworkStats.TAG_ALL: return TAG_ANY;
+                case android.net.NetworkStats.TAG_NONE: return TAG_ALL;
+            }
+            return tag;
+        }
+
         private static int convertRoaming(int roaming) {
             switch (roaming) {
                 case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL;
@@ -218,6 +236,14 @@
         }
 
         /**
+         * Tag of the bucket.<p />
+         * @return Bucket tag.
+         */
+        public int getTag() {
+            return mTag;
+        }
+
+        /**
          * Usage state. One of the following values:<p/>
          * <ul>
          * <li>{@link #STATE_ALL}</li>
@@ -363,9 +389,9 @@
      * Collects summary results and sets summary enumeration mode.
      * @throws RemoteException
      */
-    void startSummaryEnumeration() throws RemoteException {
-        mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp, false);
-
+    void startSummaryEnumeration(boolean includeTags) throws RemoteException {
+        mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp,
+                includeTags);
         mEnumerationIndex = 0;
     }
 
@@ -373,10 +399,17 @@
      * Collects history results for uid and resets history enumeration index.
      */
     void startHistoryEnumeration(int uid) {
+        startHistoryEnumeration(uid, android.net.NetworkStats.TAG_NONE);
+    }
+
+    /**
+     * Collects history results for uid and resets history enumeration index.
+     */
+    void startHistoryEnumeration(int uid, int tag) {
         mHistory = null;
         try {
             mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
-                    android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
+                    android.net.NetworkStats.SET_ALL, tag,
                     NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
             setSingleUid(uid);
         } catch (RemoteException e) {
@@ -434,6 +467,7 @@
 
     private void fillBucketFromSummaryEntry(Bucket bucketOut) {
         bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
+        bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag);
         bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
         bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
         bucketOut.mBeginTimeStamp = mStartTimeStamp;
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 1a9bf4e..13aeef0 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -16,12 +16,17 @@
 
 package android.app.usage;
 
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.Nullable;
 import android.app.usage.NetworkStats.Bucket;
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.DataUsageRequest;
 import android.net.NetworkIdentity;
 import android.net.NetworkTemplate;
 import android.os.Build;
+import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -82,10 +87,11 @@
     }
     /**
      * Query network usage statistics summaries. Result is summarised data usage for the whole
-     * device. Result is a single Bucket aggregated over time, state and uid. This means the
-     * bucket's start and end timestamp are going to be the same as the 'startTime' and 'endTime'
-     * parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
-     * {@link NetworkStats.Bucket#UID_ALL}, and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
+     * device. Result is a single Bucket aggregated over time, state, uid, tag and roaming. This
+     * means the bucket's start and end timestamp are going to be the same as the 'startTime' and
+     * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
+     * {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_ALL}
+     * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
      *
      * @param networkType As defined in {@link ConnectivityManager}, e.g.
      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -114,11 +120,22 @@
     }
 
     /**
+     * Query network usage statistics summaries aggregated across tags.
+     *
+     * #see querySummaryForUser(int, String, long, long, boolean)
+     */
+    public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
+            long endTime) throws SecurityException, RemoteException {
+        return querySummaryForUser(networkType, subscriberId, startTime, endTime,
+            false /* includeTags */);
+    }
+
+    /**
      * Query network usage statistics summaries. Result is summarised data usage for all uids
      * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
      * This means the bucket's start and end timestamp are going to be the same as the 'startTime'
-     * and 'endTime' parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
-     * {@link NetworkStats.Bucket#UID_ALL}, and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
+     * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid
+     * {@link NetworkStats.Bucket#UID_ALL}.
      *
      * @param networkType As defined in {@link ConnectivityManager}, e.g.
      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -128,11 +145,13 @@
      *            {@link java.lang.System#currentTimeMillis}.
      * @param endTime End of period. Defined in terms of "Unix time", see
      *            {@link java.lang.System#currentTimeMillis}.
+     * @param includeTags whether to include network tags. If {@code true}, tags will be returned
+     *            and history retention may be shorter.
      * @return Bucket object or null if permissions are insufficient or error happened during
      *         statistics collection.
      */
     public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
-            long endTime) throws SecurityException, RemoteException {
+            long endTime, boolean includeTags) throws SecurityException, RemoteException {
         NetworkTemplate template = createTemplate(networkType, subscriberId);
         if (template == null) {
             return null;
@@ -140,18 +159,28 @@
 
         NetworkStats stats;
         stats = new NetworkStats(mContext, template, startTime, endTime);
-        stats.startSummaryEnumeration();
+        stats.startSummaryEnumeration(includeTags);
 
         stats.close();
         return stats.getSummaryAggregate();
     }
 
     /**
+     * Query network usage statistics summaries aggregated across tags.
+     *
+     * #see querySummary(int, String, long, long, boolean)
+     */
+    public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
+            long endTime) throws SecurityException, RemoteException {
+        return querySummary(networkType, subscriberId, startTime, endTime, false /* includeTags */);
+    }
+
+    /**
      * Query network usage statistics summaries. Result filtered to include only uids belonging to
      * calling user. Result is aggregated over time, hence all buckets will have the same start and
-     * end timestamps. Not aggregated over state, uid, or roaming. This means buckets' start and end
-     * timestamps are going to be the same as the 'startTime' and 'endTime' parameters, state and
-     * uid are going to vary.
+     * end timestamps. Not aggregated over state or uid or tag. This means buckets' start and end
+     * timestamps are going to be the same as the 'startTime' and 'endTime' parameters. State,
+     * uid and tag are going to vary.
      *
      * @param networkType As defined in {@link ConnectivityManager}, e.g.
      *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -161,11 +190,13 @@
      *            {@link java.lang.System#currentTimeMillis}.
      * @param endTime End of period. Defined in terms of "Unix time", see
      *            {@link java.lang.System#currentTimeMillis}.
+     * @param includeTags whether to include network tags. If {@code true}, tags will be returned
+     *            and history retention may be shorter.
      * @return Statistics object or null if permissions are insufficient or error happened during
      *         statistics collection.
      */
     public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
-            long endTime) throws SecurityException, RemoteException {
+            long endTime, boolean includeTags) throws SecurityException, RemoteException {
         NetworkTemplate template = createTemplate(networkType, subscriberId);
         if (template == null) {
             return null;
@@ -173,17 +204,28 @@
 
         NetworkStats result;
         result = new NetworkStats(mContext, template, startTime, endTime);
-        result.startSummaryEnumeration();
+        result.startSummaryEnumeration(includeTags);
 
         return result;
     }
 
     /**
-     * Query network usage statistics details. Only usable for uids belonging to calling user.
-     * Result is aggregated over state but not aggregated over time. This means buckets' start and
-     * end timestamps are going to be between 'startTime' and 'endTime' parameters, state is going
-     * to be {@link NetworkStats.Bucket#STATE_ALL} and uid the same as the 'uid' parameter. roaming
-     * is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
+     * Query network usage statistics details for a given uid.
+     *
+     * #see queryDetailsForUidTag(int, String, long, long, int, int)
+     */
+    public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
+            long startTime, long endTime, int uid) throws SecurityException, RemoteException {
+        return queryDetailsForUidTag(networkType, subscriberId, startTime, endTime, uid,
+            NetworkStats.Bucket.TAG_ALL);
+    }
+
+    /**
+     * Query network usage statistics details for a given uid and tag. Only usable for uids
+     * belonging to calling user. Result is aggregated over state but not aggregated over time.
+     * This means buckets' start and end timestamps are going to be between 'startTime' and
+     * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the
+     * same as the 'uid' parameter and tag the same as 'tag' parameter.
      * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
      * interpolate across partial buckets. Since bucket length is in the order of hours, this
      * method cannot be used to measure data usage on a fine grained time scale.
@@ -197,11 +239,14 @@
      * @param endTime End of period. Defined in terms of "Unix time", see
      *            {@link java.lang.System#currentTimeMillis}.
      * @param uid UID of app
+     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_ANY} for any tags, use
+     *            {@link NetworkStats.Bucket#TAG_ALL} to aggregate over tags.
      * @return Statistics object or null if permissions are insufficient or error happened during
      *         statistics collection.
      */
-    public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
-            long startTime, long endTime, int uid) throws SecurityException, RemoteException {
+    public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
+            long startTime, long endTime, int uid, int tag) throws SecurityException,
+            RemoteException {
         NetworkTemplate template = createTemplate(networkType, subscriberId);
         if (template == null) {
             return null;
@@ -209,7 +254,7 @@
 
         NetworkStats result;
         result = new NetworkStats(mContext, template, startTime, endTime);
-        result.startHistoryEnumeration(uid);
+        result.startHistoryEnumeration(uid, tag);
 
         return result;
     }
@@ -218,8 +263,9 @@
      * Query network usage statistics details. Result filtered to include only uids belonging to
      * calling user. Result is aggregated over state but not aggregated over time or uid. This means
      * buckets' start and end timestamps are going to be between 'startTime' and 'endTime'
-     * parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid will vary.
-     * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
+     * parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
+     * tag {@link NetworkStats.Bucket#TAG_ALL} and roaming is going to be
+     * {@link NetworkStats.Bucket#ROAMING_ALL}.
      * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
      * interpolate across partial buckets. Since bucket length is in the order of hours, this
      * method cannot be used to measure data usage on a fine grained time scale.
@@ -247,6 +293,62 @@
         return result;
     }
 
+    /**
+     * Registers to receive notifications about data usage on specified networks and uids.
+     * The callbacks will continue to be called as long as the process is live or
+     * {@link #unregisterDataUsageCallback} is called.
+     *
+     * @param policy {@link DataUsagePolicy} describing this request.
+     * @param callback The {@link DataUsageCallback} that the system will call when data usage
+     *            has exceeded the specified threshold.
+     */
+    public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback) {
+        registerDataUsageCallback(policy, callback, null /* handler */);
+    }
+
+    /**
+     * Registers to receive notifications about data usage on specified networks and uids.
+     * The callbacks will continue to be called as long as the process is live or
+     * {@link #unregisterDataUsageCallback} is called.
+     *
+     * @param policy {@link DataUsagePolicy} describing this request.
+     * @param callback The {@link DataUsageCallback} that the system will call when data usage
+     *            has exceeded the specified threshold.
+     * @param handler to dispatch callback events through, otherwise if {@code null} it uses
+     *            the calling thread.
+     */
+    public void registerDataUsageCallback(DataUsagePolicy policy, DataUsageCallback callback,
+                @Nullable Handler handler) {
+        checkNotNull(policy, "DataUsagePolicy cannot be null");
+        checkNotNull(callback, "DataUsageCallback cannot be null");
+
+        // TODO: Implement stub.
+    }
+
+    /**
+     * Unregisters callbacks on data usage.
+     *
+     * @param callback The {@link DataUsageCallback} used when registering.
+     */
+    public void unregisterDataUsageCallback(DataUsageCallback callback) {
+        checkNotNull(callback, "DataUsageCallback cannot be null");
+
+        // TODO: Implement stub.
+    }
+
+    /**
+     * Base class for data usage callbacks. Should be extended by applications wanting
+     * notifications.
+     */
+    public static class DataUsageCallback {
+        /**
+         * Called when data usage has reached the given policy threshold.
+         */
+        public void onLimitReached() {}
+
+        private DataUsageRequest request;
+    }
+
     private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
         NetworkTemplate template = null;
         switch (networkType) {
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index a88aa3125..2937ccc 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -47,20 +47,6 @@
     public long mLastTimeUsed;
 
     /**
-     * The last time the package was used via implicit, non-user initiated actions (service
-     * was bound, etc).
-     * {@hide}
-     */
-    public long mLastTimeSystemUsed;
-
-    /**
-     * Last time the package was used and the beginning of the idle countdown.
-     * This uses a different timebase that is about how much the device has been in use in general.
-     * {@hide}
-     */
-    public long mBeginIdleTime;
-
-    /**
      * {@hide}
      */
     public long mTotalTimeInForeground;
@@ -89,8 +75,6 @@
         mTotalTimeInForeground = stats.mTotalTimeInForeground;
         mLaunchCount = stats.mLaunchCount;
         mLastEvent = stats.mLastEvent;
-        mBeginIdleTime = stats.mBeginIdleTime;
-        mLastTimeSystemUsed = stats.mLastTimeSystemUsed;
     }
 
     public String getPackageName() {
@@ -127,25 +111,6 @@
     }
 
     /**
-     * @hide
-     * Get the last time this package was used by the system (not the user). This can be different
-     * from {@link #getLastTimeUsed()} when the system binds to one of this package's services.
-     * See {@link System#currentTimeMillis()}.
-     */
-    public long getLastTimeSystemUsed() {
-        return mLastTimeSystemUsed;
-    }
-
-    /**
-     * @hide
-     * Get the last time this package was active, measured in milliseconds. This timestamp
-     * uses a timebase that represents how much the device was used and not wallclock time.
-     */
-    public long getBeginIdleTime() {
-        return mBeginIdleTime;
-    }
-
-    /**
      * Get the total time this package spent in the foreground, measured in milliseconds.
      */
     public long getTotalTimeInForeground() {
@@ -172,8 +137,6 @@
             // regards to their mEndTimeStamp.
             mLastEvent = right.mLastEvent;
             mLastTimeUsed = right.mLastTimeUsed;
-            mBeginIdleTime = right.mBeginIdleTime;
-            mLastTimeSystemUsed = right.mLastTimeSystemUsed;
         }
         mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
         mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
@@ -195,8 +158,6 @@
         dest.writeLong(mTotalTimeInForeground);
         dest.writeInt(mLaunchCount);
         dest.writeInt(mLastEvent);
-        dest.writeLong(mBeginIdleTime);
-        dest.writeLong(mLastTimeSystemUsed);
     }
 
     public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -210,8 +171,6 @@
             stats.mTotalTimeInForeground = in.readLong();
             stats.mLaunchCount = in.readInt();
             stats.mLastEvent = in.readInt();
-            stats.mBeginIdleTime = in.readLong();
-            stats.mLastTimeSystemUsed = in.readLong();
             return stats;
         }
 
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 3219fe7..bed91ec 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -29,6 +29,7 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -38,6 +39,7 @@
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Adapter;
 import android.widget.AdapterView;
@@ -48,6 +50,8 @@
 import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
 import android.widget.TextView;
 
+import java.util.concurrent.Executor;
+
 /**
  * Provides the glue to show AppWidget views. This class offers automatic animation
  * between updates, and will try recycling old views for each incoming
@@ -86,6 +90,9 @@
     Paint mOldPaint = new Paint();
     private OnClickHandler mOnClickHandler;
 
+    private Executor mAsyncExecutor;
+    private CancellationSignal mLastExecutionSignal;
+
     /**
      * Create a host view.  Uses default fade animations.
      */
@@ -234,6 +241,25 @@
         }
     }
 
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        try {
+            super.onLayout(changed, left, top, right, bottom);
+        } catch (final RuntimeException e) {
+            Log.e(TAG, "Remote provider threw runtime exception, using error view instead.", e);
+            removeViewInLayout(mView);
+            View child = getErrorView();
+            prepareView(child);
+            addViewInLayout(child, 0, child.getLayoutParams());
+            measureChild(child, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
+            child.layout(0, 0, child.getMeasuredWidth() + mPaddingLeft + mPaddingRight,
+                    child.getMeasuredHeight() + mPaddingTop + mPaddingBottom);
+            mView = child;
+            mViewMode = VIEW_MODE_ERROR;
+        }
+    }
+
     /**
      * Provide guidance about the size of this widget to the AppWidgetManager. The widths and
      * heights should correspond to the full area the AppWidgetHostView is given. Padding added by
@@ -320,6 +346,22 @@
     }
 
     /**
+     * Sets an executor which can be used for asynchronously inflating and applying the remoteviews.
+     * @see {@link RemoteViews#applyAsync(Context, ViewGroup, RemoteViews.OnViewAppliedListener, Executor)}
+     *
+     * @param executor the executor to use or null.
+     * @hide
+     */
+    public void setAsyncExecutor(Executor executor) {
+        if (mLastExecutionSignal != null) {
+            mLastExecutionSignal.cancel();
+            mLastExecutionSignal = null;
+        }
+
+        mAsyncExecutor = executor;
+    }
+
+    /**
      * Update the AppWidgetProviderInfo for this view, and reset it to the
      * initial layout.
      */
@@ -360,6 +402,11 @@
             }
         }
 
+        if (mLastExecutionSignal != null) {
+            mLastExecutionSignal.cancel();
+            mLastExecutionSignal = null;
+        }
+
         if (remoteViews == null) {
             if (mViewMode == VIEW_MODE_DEFAULT) {
                 // We've already done this -- nothing to do.
@@ -369,6 +416,10 @@
             mLayoutId = -1;
             mViewMode = VIEW_MODE_DEFAULT;
         } else {
+            if (mAsyncExecutor != null) {
+                inflateAsync(remoteViews);
+                return;
+            }
             // Prepare a local reference to the remote Context so we're ready to
             // inflate any requested LayoutParams.
             mRemoteContext = getRemoteContext();
@@ -381,7 +432,7 @@
                     remoteViews.reapply(mContext, mView, mOnClickHandler);
                     content = mView;
                     recycled = true;
-                    if (LOGD) Log.d(TAG, "was able to recycled existing layout");
+                    if (LOGD) Log.d(TAG, "was able to recycle existing layout");
                 } catch (RuntimeException e) {
                     exception = e;
                 }
@@ -401,6 +452,10 @@
             mViewMode = VIEW_MODE_CONTENT;
         }
 
+        applyContent(content, recycled, exception);
+    }
+
+    private void applyContent(View content, boolean recycled, Exception exception) {
         if (content == null) {
             if (mViewMode == VIEW_MODE_ERROR) {
                 // We've already done this -- nothing to do.
@@ -432,6 +487,68 @@
         }
     }
 
+    private void inflateAsync(RemoteViews remoteViews) {
+        // Prepare a local reference to the remote Context so we're ready to
+        // inflate any requested LayoutParams.
+        mRemoteContext = getRemoteContext();
+        int layoutId = remoteViews.getLayoutId();
+
+        // If our stale view has been prepared to match active, and the new
+        // layout matches, try recycling it
+        if (layoutId == mLayoutId && mView != null) {
+            try {
+                mLastExecutionSignal = remoteViews.reapplyAsync(mContext,
+                        mView,
+                        mAsyncExecutor,
+                        new ViewApplyListener(remoteViews, layoutId, true),
+                        mOnClickHandler);
+            } catch (Exception e) {
+                // Reapply failed. Try apply
+            }
+        }
+        if (mLastExecutionSignal == null) {
+            mLastExecutionSignal = remoteViews.applyAsync(mContext,
+                    this,
+                    mAsyncExecutor,
+                    new ViewApplyListener(remoteViews, layoutId, false),
+                    mOnClickHandler);
+        }
+    }
+
+    private class ViewApplyListener implements RemoteViews.OnViewAppliedListener {
+        private final RemoteViews mViews;
+        private final boolean mIsReapply;
+        private final int mLayoutId;
+
+        public ViewApplyListener(RemoteViews views, int layoutId, boolean isReapply) {
+            mViews = views;
+            mLayoutId = layoutId;
+            mIsReapply = isReapply;
+        }
+
+        @Override
+        public void onViewApplied(View v) {
+            AppWidgetHostView.this.mLayoutId = mLayoutId;
+            mViewMode = VIEW_MODE_CONTENT;
+
+            applyContent(v, mIsReapply, null);
+        }
+
+        @Override
+        public void onError(Exception e) {
+            if (mIsReapply) {
+                // Try a fresh replay
+                mLastExecutionSignal = mViews.applyAsync(mContext,
+                        AppWidgetHostView.this,
+                        mAsyncExecutor,
+                        new ViewApplyListener(mViews, mLayoutId, false),
+                        mOnClickHandler);
+            } else {
+                applyContent(null, false, e);
+            }
+        }
+    }
+
     /**
      * Process data-changed notifications for the specified view in the specified
      * set of {@link RemoteViews} views.
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 4135487..9221fbb 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -148,8 +148,7 @@
                 return null;
             }
 
-            if ("com.google.android.gms".equals(mPackageName)
-                    || "com.google.android.syncadapters.contacts".equals(mPackageName)) {
+            if ("com.google.android.gms".equals(mPackageName)) {
                 // They're casting to a concrete subclass, sigh
                 return cursor;
             } else {
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 3461c11..4e1b6e0 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -89,6 +89,13 @@
     public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
 
     /**
+     * If this extra is set to true, the sync request will be scheduled
+     * only when the device is plugged in. This is equivalent to calling
+     * setRequiresCharging(true) on {@link SyncRequest}.
+     */
+    public static final String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging";
+
+    /**
      * @deprecated instead use
      * {@link #SYNC_EXTRAS_MANUAL}
      */
@@ -2053,7 +2060,8 @@
      * @param account the account to specify in the sync
      * @param authority the provider to specify in the sync request
      * @param extras extra parameters to go along with the sync request
-     * @param pollFrequency how frequently the sync should be performed, in seconds.
+     * @param pollFrequency how frequently the sync should be performed, in seconds. A minimum value
+     *                      of 1 hour is enforced.
      * @throws IllegalArgumentException if an illegal extra was set or if any of the parameters
      * are null.
      */
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 622aad9..4918914 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -342,9 +342,7 @@
      * {@link android.R.attr#isolatedProcess isolated},
      * {@link android.R.attr#externalService external} service.  This binds the service into the
      * calling application's package, rather than the package in which the service is declared.
-     * @hide
      */
-    @SystemApi
     public static final int BIND_EXTERNAL_SERVICE = 0x80000000;
 
     /**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 83943ad..7dc7401 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -8939,6 +8939,8 @@
                 case ACTION_MEDIA_SCANNER_STARTED:
                 case ACTION_MEDIA_SCANNER_FINISHED:
                 case ACTION_MEDIA_SCANNER_SCAN_FILE:
+                case ACTION_PACKAGE_NEEDS_VERIFICATION:
+                case ACTION_PACKAGE_VERIFIED:
                     // Ignore legacy actions
                     break;
                 default:
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 7619c6d..f793d76 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -246,6 +246,10 @@
          * this sync is bound to a provider), otherwise null.
          */
         private String mAuthority;
+        /**
+         * Whether the sync requires the phone to be plugged in.
+         */
+        private boolean mRequiresCharging;
 
         public Builder() {
         }
@@ -303,10 +307,11 @@
          * be thrown.
          *
          * @param pollFrequency the amount of time in seconds that you wish
-         *            to elapse between periodic syncs.
+         *            to elapse between periodic syncs. A minimum period of 1 hour is enforced.
          * @param beforeSeconds the amount of flex time in seconds before
          *            {@code pollFrequency} that you permit for the sync to take
-         *            place. Must be less than {@code pollFrequency}.
+         *            place. Must be less than {@code pollFrequency} and greater than
+         *            MAX(5% of {@code pollFrequency}, 5 minutes)
          */
         public Builder syncPeriodic(long pollFrequency, long beforeSeconds) {
             if (mSyncType != SYNC_TYPE_UNKNOWN) {
@@ -335,13 +340,22 @@
         public Builder setDisallowMetered(boolean disallow) {
             if (mIgnoreSettings && disallow) {
                 throw new IllegalArgumentException("setDisallowMetered(true) after having"
-                        + "specified that settings are ignored.");
+                        + " specified that settings are ignored.");
             }
             mDisallowMetered = disallow;
             return this;
         }
 
         /**
+         * Specify whether the sync requires the phone to be plugged in.
+         * @param requiresCharging true if sync requires the phone to be plugged in. Default false.
+         */
+        public Builder setRequiresCharging(boolean requiresCharging) {
+            mRequiresCharging = true;
+            return this;
+        }
+
+        /**
          * Specify an authority and account for this transfer.
          *
          * @param authority A String identifying the content provider to be synced.
@@ -499,6 +513,9 @@
             if (mDisallowMetered) {
                 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, true);
             }
+            if (mRequiresCharging) {
+                mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING, true);
+            }
             if (mIgnoreSettings) {
                 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
             }
diff --git a/core/java/android/content/pm/IOtaDexopt.aidl b/core/java/android/content/pm/IOtaDexopt.aidl
new file mode 100644
index 0000000..8f38d6f
--- /dev/null
+++ b/core/java/android/content/pm/IOtaDexopt.aidl
@@ -0,0 +1,49 @@
+/*
+**
+** 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.
+*/
+
+package android.content.pm;
+
+/**
+ * A/B OTA dexopting service.
+ *
+ * {@hide}
+ */
+interface IOtaDexopt {
+    /**
+     * Prepare for A/B OTA dexopt. Initialize internal structures.
+     *
+     * Calls to the other methods are only valid after a call to prepare. You may not call
+     * prepare twice without a cleanup call.
+     */
+    void prepare();
+
+    /**
+     * Clean up all internal state.
+     */
+    void cleanup();
+
+    /**
+     * Check whether all updates have been performed.
+     */
+    boolean isDone();
+
+    /**
+     * Optimize the next package. Note: this command is synchronous, that is, only returns after
+     * the package has been dexopted (or dexopting failed).
+     */
+    void dexoptNextPackage();
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 2c6b604..593fe2a 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -452,6 +452,9 @@
      */
     boolean performDexOptIfNeeded(String packageName, String instructionSet);
 
+    boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles,
+            boolean extractOnly, boolean force);
+
     void forceDexOpt(String packageName);
 
     /**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3a94bf7..6fb3c7c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2064,13 +2064,26 @@
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
      * The device implements a an optimized mode for virtual reality (VR) applications that handles
      * stereoscopic rendering of notifications, and may potentially also include optimizations to
-     * reduce latency in the graphics, display, and sensor stacks.  Presence of this feature
-     * also indicates that the VrCore library is included on this device.
+     * reduce latency in the graphics, display, and sensor stacks.
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_VR_MODE = "android.software.vr.mode";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device implements {@link #FEATURE_VR_MODE} but additionally meets all CTS requirements
+     * to be certified as a "VR Ready" device, which guarantees that the device is capable of
+     * delivering consistent performance at a high framerate over an extended period of time for
+     * typical VR application CPU/GPU workloads with a minimal number of frame drops, implements
+     * {@link #FEATURE_HIFI_SENSORS} with a low sensor latency, implements an optimized render path
+     * to minimize latency to draw to the device's main display, and includes optimizations to
+     * lower display persistence to an acceptable level.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_VR_MODE_HIGH_PERFORMANCE
+            = "android.hardware.vr.high_performance";
+
+    /**
      * Action to external storage service to clean out removed apps.
      * @hide
      */
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 09b85c9..3802db8 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -291,6 +291,7 @@
 
         public final boolean coreApp;
         public final boolean multiArch;
+        public final String abiOverride;
         public final boolean extractNativeLibs;
 
         public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
@@ -307,6 +308,7 @@
             this.splitRevisionCodes = splitRevisionCodes;
             this.coreApp = baseApk.coreApp;
             this.multiArch = baseApk.multiArch;
+            this.abiOverride = baseApk.abiOverride;
             this.extractNativeLibs = baseApk.extractNativeLibs;
         }
 
@@ -334,11 +336,12 @@
         public final Signature[] signatures;
         public final boolean coreApp;
         public final boolean multiArch;
+        public final String abiOverride;
         public final boolean extractNativeLibs;
 
         public ApkLite(String codePath, String packageName, String splitName, int versionCode,
                 int revisionCode, int installLocation, List<VerifierInfo> verifiers,
-                Signature[] signatures, boolean coreApp, boolean multiArch,
+                Signature[] signatures, boolean coreApp, boolean multiArch, String abiOverride,
                 boolean extractNativeLibs) {
             this.codePath = codePath;
             this.packageName = packageName;
@@ -350,6 +353,7 @@
             this.signatures = signatures;
             this.coreApp = coreApp;
             this.multiArch = multiArch;
+            this.abiOverride = abiOverride;
             this.extractNativeLibs = extractNativeLibs;
         }
     }
@@ -793,6 +797,7 @@
             }
 
             pkg.codePath = packageDir.getAbsolutePath();
+            pkg.cpuAbiOverride = lite.abiOverride;
             return pkg;
         } finally {
             IoUtils.closeQuietly(assets);
@@ -811,8 +816,8 @@
      */
     @Deprecated
     public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
+        final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
         if (mOnlyCoreApps) {
-            final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
             if (!lite.coreApp) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                         "Not a coreApp: " + apkFile);
@@ -823,6 +828,7 @@
         try {
             final Package pkg = parseBaseApk(apkFile, assets, flags);
             pkg.codePath = apkFile.getAbsolutePath();
+            pkg.cpuAbiOverride = lite.abiOverride;
             return pkg;
         } finally {
             IoUtils.closeQuietly(assets);
@@ -1316,6 +1322,7 @@
         int revisionCode = 0;
         boolean coreApp = false;
         boolean multiArch = false;
+        String abiOverride = null;
         boolean extractNativeLibs = true;
 
         for (int i = 0; i < attrs.getAttributeCount(); i++) {
@@ -1356,6 +1363,9 @@
                     if ("multiArch".equals(attr)) {
                         multiArch = attrs.getAttributeBooleanValue(i, false);
                     }
+                    if ("abiOverride".equals(attr)) {
+                        abiOverride = attrs.getAttributeValue(i);
+                    }
                     if ("extractNativeLibs".equals(attr)) {
                         extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
                     }
@@ -1365,7 +1375,7 @@
 
         return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
                 revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
-                extractNativeLibs);
+                abiOverride, extractNativeLibs);
     }
 
     /**
@@ -3237,18 +3247,20 @@
                     SCREEN_ORIENTATION_UNSPECIFIED);
 
             a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
-            if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
-                final boolean appDefault = (owner.applicationInfo.privateFlags
-                        & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES) != 0;
-                if (sa.getBoolean(
-                        R.styleable.AndroidManifestActivity_resizeableActivity, appDefault)) {
-                    if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
-                            false)) {
-                        a.info.resizeMode = RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
-                    } else {
-                        a.info.resizeMode = RESIZE_MODE_RESIZEABLE;
-                    }
+            final boolean appDefault = (owner.applicationInfo.privateFlags
+                    & PRIVATE_FLAG_RESIZEABLE_ACTIVITIES) != 0;
+            final boolean resizeable = sa.getBoolean(
+                    R.styleable.AndroidManifestActivity_resizeableActivity, appDefault);
+
+            if (resizeable) {
+                if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
+                        false)) {
+                    a.info.resizeMode = RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
+                } else {
+                    a.info.resizeMode = RESIZE_MODE_RESIZEABLE;
                 }
+            } else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
+                a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
             } else if (a.info.screenOrientation == SCREEN_ORIENTATION_UNSPECIFIED
                     && (a.info.flags & FLAG_IMMERSIVE) == 0) {
                 a.info.resizeMode = RESIZE_MODE_CROP_WINDOWS;
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index eecf0de..6bd285a 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -52,7 +52,6 @@
      * Bit in {@link #flags}: If set, the service can be bound and run in the
      * calling application's package, rather than the package in which it is
      * declared.  Set from {@link android.R.attr#externalService} attribute.
-     * @hide
      */
     public static final int FLAG_EXTERNAL_SERVICE = 0x0004;
 
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 7db5a08..be4f895 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -715,7 +715,7 @@
      * about setLocales() has changed locale directly. */
     private void fixUpLocaleList() {
         if ((locale == null && !mLocaleList.isEmpty()) ||
-                (locale != null && !locale.equals(mLocaleList.getPrimary()))) {
+                (locale != null && !locale.equals(mLocaleList.get(0)))) {
             mLocaleList = new LocaleList(locale);
         }
     }
@@ -1269,7 +1269,7 @@
             localeArray[i] = Locale.forLanguageTag(source.readString());
         }
         mLocaleList = new LocaleList(localeArray);
-        locale = mLocaleList.getPrimary();
+        locale = mLocaleList.get(0);
 
         userSetLocale = (source.readInt()==1);
         touchscreen = source.readInt();
@@ -1435,7 +1435,7 @@
      */
     public void setLocales(@Nullable LocaleList locales) {
         mLocaleList = locales == null ? LocaleList.getEmptyLocaleList() : locales;
-        locale = mLocaleList.getPrimary();
+        locale = mLocaleList.get(0);
         setLayoutDirection(locale);
     }
 
@@ -1900,7 +1900,7 @@
 
         final String localesStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALES);
         configOut.mLocaleList = LocaleList.forLanguageTags(localesStr);
-        configOut.locale = configOut.mLocaleList.getPrimary();
+        configOut.locale = configOut.mLocaleList.get(0);
 
         configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
                 TOUCHSCREEN_UNDEFINED);
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 4967d05..915fae0 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -381,7 +381,7 @@
     private PluralRules getPluralRule() {
         synchronized (sSync) {
             if (mPluralRule == null) {
-                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().getPrimary());
+                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
             }
             return mPluralRule;
         }
@@ -444,7 +444,7 @@
     @NonNull
     public String getString(@StringRes int id, Object... formatArgs) throws NotFoundException {
         final String raw = getString(id);
-        return String.format(mConfiguration.getLocales().getPrimary(), raw, formatArgs);
+        return String.format(mConfiguration.getLocales().get(0), raw, formatArgs);
     }
 
     /**
@@ -475,7 +475,7 @@
     public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
             throws NotFoundException {
         String raw = getQuantityText(id, quantity).toString();
-        return String.format(mConfiguration.getLocales().getPrimary(), raw, formatArgs);
+        return String.format(mConfiguration.getLocales().get(0), raw, formatArgs);
     }
 
     /**
@@ -1971,7 +1971,7 @@
             }
 
             mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
-                    adjustLanguageTag(locales.getPrimary().toLanguageTag()),
+                    adjustLanguageTag(locales.get(0).toLanguageTag()),
                     mConfiguration.orientation,
                     mConfiguration.touchscreen,
                     mConfiguration.densityDpi, mConfiguration.keyboard,
@@ -1996,7 +1996,7 @@
         }
         synchronized (sSync) {
             if (mPluralRule != null) {
-                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().getPrimary());
+                mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
             }
         }
     }
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 8bdd42a..bb0a042 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -175,7 +175,8 @@
          * colorCorrection.*
          */
         m.set(COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
-                new int[] { COLOR_CORRECTION_ABERRATION_MODE_FAST });
+                new int[] { COLOR_CORRECTION_ABERRATION_MODE_FAST,
+                            COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY });
         /*
          * control.ae*
          */
@@ -210,7 +211,8 @@
          * noiseReduction.*
          */
         m.set(NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
-                new int[] { NOISE_REDUCTION_MODE_FAST });
+                new int[] { NOISE_REDUCTION_MODE_FAST,
+                            NOISE_REDUCTION_MODE_HIGH_QUALITY});
 
         /*
          * scaler.*
@@ -1389,7 +1391,22 @@
         /*
          * noiseReduction.*
          */
-        m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST);
+        if (templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
+            m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_HIGH_QUALITY);
+        } else {
+            m.set(CaptureRequest.NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST);
+        }
+
+        /*
+        * colorCorrection.*
+        */
+        if (templateId == CameraDevice.TEMPLATE_STILL_CAPTURE) {
+            m.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
+                    COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);
+        } else {
+            m.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
+                    COLOR_CORRECTION_ABERRATION_MODE_FAST);
+        }
 
         /*
          * lens.*
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index 6a44ac5..2e06d5f 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -89,7 +89,8 @@
                     COLOR_CORRECTION_ABERRATION_MODE,
                     /*defaultValue*/COLOR_CORRECTION_ABERRATION_MODE_FAST);
 
-            if (aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_FAST) {
+            if (aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_FAST &&
+                    aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY) {
                 Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " +
                         "colorCorrection.aberrationMode = " + aberrationMode);
             }
@@ -446,7 +447,8 @@
                     NOISE_REDUCTION_MODE,
                     /*defaultValue*/NOISE_REDUCTION_MODE_FAST);
 
-            if (mode != NOISE_REDUCTION_MODE_FAST) {
+            if (mode != NOISE_REDUCTION_MODE_FAST &&
+                    mode != NOISE_REDUCTION_MODE_HIGH_QUALITY) {
                 Log.w(TAG, "convertRequestToMetadata - Ignoring unsupported " +
                         "noiseReduction.mode = " + mode);
             }
diff --git a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
index ce85005..dc5823d 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
@@ -67,7 +67,9 @@
         /*
          * Attempt to look up the result from the cache if the parameters haven't changed
          */
-        if (mCachedRequest != null && legacyRequest.parameters.same(mCachedRequest.parameters)) {
+        if (mCachedRequest != null &&
+                legacyRequest.parameters.same(mCachedRequest.parameters) &&
+                legacyRequest.captureRequest.equals(mCachedRequest.captureRequest)) {
             result = new CameraMetadataNative(mCachedResult);
             cached = true;
         } else {
@@ -124,8 +126,8 @@
          */
         // colorCorrection.aberrationMode
         {
-            // Always hardcoded to FAST
-            result.set(COLOR_CORRECTION_ABERRATION_MODE, COLOR_CORRECTION_ABERRATION_MODE_FAST);
+            result.set(COLOR_CORRECTION_ABERRATION_MODE,
+                    request.get(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE));
         }
 
         /*
@@ -282,7 +284,7 @@
          * noiseReduction.*
          */
         // noiseReduction.mode
-        result.set(NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST);
+        result.set(NOISE_REDUCTION_MODE, request.get(CaptureRequest.NOISE_REDUCTION_MODE));
 
         return result;
     }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 25b38c0..7004e97 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3215,11 +3215,24 @@
 
     /**
      * Device is restricting metered network activity while application is running on background.
+     * <p>
      * In this state, application should not try to use the network while running on background,
      * because it would be denied.
      */
     public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3;
 
+    /**
+     * A change in the background metered network activity restriction has occurred.
+     * <p>
+     * Applications should call {@link #getRestrictBackgroundStatus()} to check if the restriction
+     * applies to them.
+     * <p>
+     * This is only sent to registered receivers, not manifest receivers.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_RESTRICT_BACKGROUND_CHANGED =
+            "android.net.conn.RESTRICT_BACKGROUND_CHANGED";
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = false, value = {
diff --git a/wifi/java/android/net/wifi/ScanInfo.aidl b/core/java/android/net/DataUsageRequest.aidl
similarity index 83%
copy from wifi/java/android/net/wifi/ScanInfo.aidl
copy to core/java/android/net/DataUsageRequest.aidl
index 18ae508..d1937c7 100644
--- a/wifi/java/android/net/wifi/ScanInfo.aidl
+++ b/core/java/android/net/DataUsageRequest.aidl
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2015, The Android Open Source Project
+ * Copyright (c) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.net.wifi;
+package android.net;
 
-parcelable ScanInfo;
+parcelable DataUsageRequest;
diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java
new file mode 100644
index 0000000..0e46f4c
--- /dev/null
+++ b/core/java/android/net/DataUsageRequest.java
@@ -0,0 +1,143 @@
+/**
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package android.net;
+
+import android.net.NetworkTemplate;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Defines a request to register a callbacks. Used to be notified on data usage via
+ * {@link android.app.usage.NetworkStatsManager#registerDataUsageCallback}.
+ * If no {@code uid}s are set, callbacks are restricted to device-owners,
+ * carrier-privileged apps, or system apps.
+ */
+public class DataUsageRequest implements Parcelable {
+
+    /**
+     * @hide
+     */
+    public static final int REQUEST_ID_UNSET = 0;
+
+    /**
+     * Identifies the request.  {@link DataUsageRequest}s should only be constructed by
+     * the Framework and it is used internally to identify the request.
+     * @hide
+     */
+    public final int requestId;
+
+    /**
+     * Set of {@link NetworkTemplate}s describing the networks to monitor.
+     * @hide
+     */
+    public final NetworkTemplate[] templates;
+
+    /**
+     * Set of UIDs of which to monitor data usage.
+     *
+     * <p>If not {@code null}, the caller will be notified when any of the uids exceed
+     * the given threshold. If {@code null} all uids for which the calling process has access
+     * to stats will be monitored.
+     * @hide
+     */
+    public final int[] uids;
+
+    /**
+     * Threshold in bytes to be notified on.
+     * @hide
+     */
+    public final long thresholdInBytes;
+
+    /**
+     * @hide
+     */
+    public DataUsageRequest(int requestId, NetworkTemplate[] templates, int[] uids,
+                long thresholdInBytes) {
+        this.requestId = requestId;
+        this.templates = templates;
+        this.uids = uids;
+        this.thresholdInBytes = thresholdInBytes;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(requestId);
+        dest.writeTypedArray(templates, flags);
+        dest.writeIntArray(uids);
+        dest.writeLong(thresholdInBytes);
+    }
+
+    public static final Creator<DataUsageRequest> CREATOR =
+            new Creator<DataUsageRequest>() {
+                @Override
+                public DataUsageRequest createFromParcel(Parcel in) {
+                    int requestId = in.readInt();
+                    NetworkTemplate[] templates = in.createTypedArray(NetworkTemplate.CREATOR);
+                    int[] uids = in.createIntArray();
+                    long thresholdInBytes = in.readLong();
+                    DataUsageRequest result = new DataUsageRequest(requestId,
+                            templates, uids, thresholdInBytes);
+                    return result;
+                }
+
+                @Override
+                public DataUsageRequest[] newArray(int size) {
+                    return new DataUsageRequest[size];
+                }
+            };
+
+    @Override
+    public String toString() {
+        return "DataUsageRequest [ requestId=" + requestId
+                + ", networkTemplates=" + Arrays.toString(templates)
+                + ", uids=" + Arrays.toString(uids)
+                + ", thresholdInBytes=" + thresholdInBytes + " ]";
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof DataUsageRequest == false) return false;
+        DataUsageRequest that = (DataUsageRequest) obj;
+        return that.requestId == this.requestId
+                && Arrays.deepEquals(that.templates, this.templates)
+                && Arrays.equals(that.uids, this.uids)
+                && that.thresholdInBytes == this.thresholdInBytes;
+    }
+
+    @Override
+    public int hashCode() {
+        // Start with a non-zero constant.
+        int result = 17;
+
+        // Include a hash for each field.
+        result = 31 * result + requestId;
+        result = 31 * result + Arrays.deepHashCode(templates);
+        result = 31 * result + Arrays.hashCode(uids);
+        result = 31 * result + (int) (thresholdInBytes ^ (thresholdInBytes >>> 32));
+
+        return result;
+   }
+
+}
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 8919d51..3d8b091 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -49,6 +49,7 @@
     /** {@link #uid} value when UID details unavailable. */
     public static final int UID_ALL = -1;
     /** {@link #tag} value matching any tag. */
+    // TODO: Rename TAG_ALL to TAG_ANY.
     public static final int TAG_ALL = -1;
     /** {@link #set} value for all sets combined, not including debug sets. */
     public static final int SET_ALL = -1;
@@ -64,6 +65,7 @@
     public static final int SET_DBG_VPN_OUT = 1002;
 
     /** {@link #tag} value for total data across all tags. */
+    // TODO: Rename TAG_NONE to TAG_ALL.
     public static final int TAG_NONE = 0;
 
     /** {@link #set} value for all roaming values. */
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 53b027b..67378bd 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -2342,7 +2342,7 @@
      * @hide
      */
     public void checkFileUriExposed(String location) {
-        if ("file".equals(getScheme())) {
+        if ("file".equals(getScheme()) && !getPath().startsWith("/system/")) {
             StrictMode.onFileUriExposed(this, location);
         }
     }
diff --git a/core/java/android/nfc/tech/NfcF.java b/core/java/android/nfc/tech/NfcF.java
index b3e3ab6..4487121 100644
--- a/core/java/android/nfc/tech/NfcF.java
+++ b/core/java/android/nfc/tech/NfcF.java
@@ -98,8 +98,13 @@
     /**
      * Send raw NFC-F commands to the tag and receive the response.
      *
-     * <p>Applications must not append the SoD (length) or EoD (CRC) to the payload,
-     * it will be automatically calculated.
+     * <p>Applications must not prefix the SoD (preamble and sync code)
+     * and/or append the EoD (CRC) to the payload, it will be automatically calculated.
+     *
+     * <p>A typical NFC-F frame for this method looks like:
+     * <pre>
+     * LENGTH (1 byte) --- CMD (1 byte) -- IDm (8 bytes) -- PARAMS (LENGTH - 10 bytes)
+     * </pre>
      *
      * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum amount of bytes
      * that can be sent with {@link #transceive}.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 52fa2ed..b33e807 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -147,6 +147,11 @@
     public static final int WAKE_TYPE_DRAW = 18;
 
     /**
+     * A constant indicating a bluetooth scan timer.
+     */
+    public static final int BLUETOOTH_SCAN_ON = 19;
+
+    /**
      * Include all of the data in the stats, including previously saved data.
      */
     public static final int STATS_SINCE_CHARGED = 0;
@@ -438,6 +443,7 @@
         public abstract Timer getFlashlightTurnedOnTimer();
         public abstract Timer getCameraTurnedOnTimer();
         public abstract Timer getForegroundActivityTimer();
+        public abstract Timer getBluetoothScanTimer();
 
         // Time this uid has any processes in the top state.
         public static final int PROCESS_STATE_TOP = 0;
@@ -1179,6 +1185,7 @@
         public static final int STATE2_PHONE_IN_CALL_FLAG = 1<<23;
         public static final int STATE2_BLUETOOTH_ON_FLAG = 1<<22;
         public static final int STATE2_CAMERA_FLAG = 1<<21;
+        public static final int STATE2_BLUETOOTH_SCAN_FLAG = 1 << 20;
 
         public static final int MOST_INTERESTING_STATES2 =
             STATE2_POWER_SAVE_FLAG | STATE2_WIFI_ON_FLAG | STATE2_DEVICE_IDLE_MASK
@@ -1922,6 +1929,7 @@
                 HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT, "wifi_suppl", "Wsp",
                 WIFI_SUPPL_STATE_NAMES, WIFI_SUPPL_STATE_SHORT_NAMES),
         new BitDescription(HistoryItem.STATE2_CAMERA_FLAG, "camera", "ca"),
+        new BitDescription(HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG, "ble_scan", "bles"),
     };
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
@@ -2041,6 +2049,13 @@
      */
     public abstract long getCameraOnTime(long elapsedRealtimeUs, int which);
 
+    /**
+     * Returns the time in microseconds that bluetooth scans were running while the device was
+     * on battery.
+     *
+     * {@hide}
+     */
+    public abstract long getBluetoothScanTime(long elapsedRealtimeUs, int which);
 
     public static final int NETWORK_MOBILE_RX_DATA = 0;
     public static final int NETWORK_MOBILE_TX_DATA = 1;
@@ -2797,9 +2812,12 @@
         final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
         final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
         final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
+        final long btRxTotalBytes = getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
+        final long btTxTotalBytes = getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
         dumpLine(pw, 0 /* uid */, category, GLOBAL_NETWORK_DATA,
                 mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
-                mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets);
+                mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets,
+                btRxTotalBytes, btTxTotalBytes);
 
         // Dump Modem controller stats
         dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_MODEM_CONTROLLER_DATA,
@@ -3017,14 +3035,18 @@
             final int mobileActiveCount = u.getMobileRadioActiveCount(which);
             final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
             final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
+            final long btBytesRx = u.getNetworkActivityBytes(NETWORK_BT_RX_DATA, which);
+            final long btBytesTx = u.getNetworkActivityBytes(NETWORK_BT_TX_DATA, which);
             if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
                     || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
-                    || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) {
+                    || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0
+                    || btBytesRx > 0 || btBytesTx > 0) {
                 dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
                         wifiBytesRx, wifiBytesTx,
                         mobilePacketsRx, mobilePacketsTx,
                         wifiPacketsRx, wifiPacketsTx,
-                        mobileActiveTime, mobileActiveCount);
+                        mobileActiveTime, mobileActiveCount,
+                        btBytesRx, btBytesTx);
             }
 
             // Dump modem controller data, per UID.
@@ -3046,6 +3068,9 @@
             dumpControllerActivityLine(pw, uid, category, WIFI_CONTROLLER_DATA,
                     u.getWifiControllerActivity(), which);
 
+            dumpControllerActivityLine(pw, uid, category, BLUETOOTH_CONTROLLER_DATA,
+                    u.getBluetoothControllerActivity(), which);
+
             if (u.hasUserActivity()) {
                 args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
                 boolean hasData = false;
@@ -3668,6 +3693,12 @@
         pw.print("  Bluetooth total received: "); pw.print(formatBytesLocked(btRxTotalBytes));
         pw.print(", sent: "); pw.println(formatBytesLocked(btTxTotalBytes));
 
+        final long bluetoothScanTimeMs = getBluetoothScanTime(rawRealtime, which) / 1000;
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("  Bluetooth scan time: "); formatTimeMs(sb, bluetoothScanTimeMs);
+        pw.println(sb.toString());
+
         printControllerActivity(pw, sb, prefix, "Bluetooth", getBluetoothControllerActivity(),
                 which);
 
@@ -3793,6 +3824,10 @@
                         pw.print(" wifi=");
                         printmAh(pw, bs.wifiPowerMah);
                     }
+                    if (bs.bluetoothPowerMah != 0) {
+                        pw.print(" bt=");
+                        printmAh(pw, bs.bluetoothPowerMah);
+                    }
                     if (bs.gpsPowerMah != 0) {
                         pw.print(" gps=");
                         printmAh(pw, bs.gpsPowerMah);
@@ -4035,6 +4070,9 @@
                 pw.println(" sent");
             }
 
+            uidActivity |= printTimer(pw, sb, u.getBluetoothScanTimer(), rawRealtime, which, prefix,
+                    "Bluetooth Scan");
+
             if (u.hasUserActivity()) {
                 boolean hasData = false;
                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index c776ef8..e841dfe 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -479,6 +479,11 @@
     public static String DIRECTORY_DOCUMENTS = "Documents";
 
     /**
+     * Standard directory in which user managed files are stored.
+     */
+    public static String DIRECTORY_HOME = "Home";
+
+    /**
      * List of standard storage directories.
      * <p>
      * Each of its values have its own constant:
@@ -493,6 +498,7 @@
      *   <li>{@link #DIRECTORY_DOWNLOADS}
      *   <li>{@link #DIRECTORY_DCIM}
      *   <li>{@link #DIRECTORY_DOCUMENTS}
+     *   <li>{@link #DIRECTORY_HOME}
      * </ul>
      * @hide
      */
@@ -506,7 +512,8 @@
             DIRECTORY_MOVIES,
             DIRECTORY_DOWNLOADS,
             DIRECTORY_DCIM,
-            DIRECTORY_DOCUMENTS
+            DIRECTORY_DOCUMENTS,
+            DIRECTORY_HOME
     };
 
     /**
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 290f7b3..c2aca41 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -29,6 +29,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import libcore.util.EmptyArray;
+
 import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -658,8 +660,19 @@
         }
     }
 
-    public static @NonNull File[] listFilesOrEmpty(File dir) {
-        File[] res = dir.listFiles();
+    public static @NonNull String[] listOrEmpty(@Nullable File dir) {
+        if (dir == null) return EmptyArray.STRING;
+        final String[] res = dir.list();
+        if (res != null) {
+            return res;
+        } else {
+            return EmptyArray.STRING;
+        }
+    }
+
+    public static @NonNull File[] listFilesOrEmpty(@Nullable File dir) {
+        if (dir == null) return EMPTY;
+        final File[] res = dir.listFiles();
         if (res != null) {
             return res;
         } else {
@@ -667,8 +680,9 @@
         }
     }
 
-    public static @NonNull File[] listFilesOrEmpty(File dir, FilenameFilter filter) {
-        File[] res = dir.listFiles(filter);
+    public static @NonNull File[] listFilesOrEmpty(@Nullable File dir, FilenameFilter filter) {
+        if (dir == null) return EMPTY;
+        final File[] res = dir.listFiles(filter);
         if (res != null) {
             return res;
         } else {
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index fe2dfdf..b51d2dfb 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -373,6 +373,12 @@
      **/
     public static final int THREAD_GROUP_AUDIO_SYS = 4;
 
+    /**
+     * Thread group for top foreground app.
+     * @hide
+     **/
+    public static final int THREAD_GROUP_TOP_APP = 5;
+
     public static final int SIGNAL_QUIT = 3;
     public static final int SIGNAL_KILL = 9;
     public static final int SIGNAL_USR1 = 10;
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 407ff08..154c9bb 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -67,6 +67,7 @@
 
     /** Used to communicate with recovery.  See bootable/recovery/recovery.cpp. */
     private static File RECOVERY_DIR = new File("/cache/recovery");
+    private static File BLOCK_MAP_FILE = new File(RECOVERY_DIR, "block.map");
     private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");
     private static File UNCRYPT_FILE = new File(RECOVERY_DIR, "uncrypt_file");
     private static File LOG_FILE = new File(RECOVERY_DIR, "log");
@@ -473,7 +474,9 @@
             Log.e(TAG, "Error reading recovery log", e);
         }
 
-        if (UNCRYPT_FILE.exists()) {
+        // Only remove the OTA package if it's partially processed (uncrypt'd).
+        boolean reservePackage = BLOCK_MAP_FILE.exists();
+        if (!reservePackage && UNCRYPT_FILE.exists()) {
             String filename = null;
             try {
                 filename = FileUtils.readTextFile(UNCRYPT_FILE, 0, null);
@@ -492,11 +495,18 @@
             }
         }
 
-        // Delete everything in RECOVERY_DIR except those beginning
-        // with LAST_PREFIX
+        // We keep the update logs (beginning with LAST_PREFIX), and optionally
+        // the block map file (BLOCK_MAP_FILE) for a package. BLOCK_MAP_FILE
+        // will be created at the end of a successful uncrypt. If seeing this
+        // file, we keep the block map file and the file that contains the
+        // package name (UNCRYPT_FILE). This is to reduce the work for GmsCore
+        // to avoid re-downloading everything again.
         String[] names = RECOVERY_DIR.list();
         for (int i = 0; names != null && i < names.length; i++) {
             if (names[i].startsWith(LAST_PREFIX)) continue;
+            if (reservePackage && names[i].equals(BLOCK_MAP_FILE.getName())) continue;
+            if (reservePackage && names[i].equals(UNCRYPT_FILE.getName())) continue;
+
             recursiveDelete(new File(RECOVERY_DIR, names[i]));
         }
 
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index 54d1090..fc804e5 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -234,6 +234,16 @@
         }
     }
 
+    public String peekNextArg() {
+        if (mCurArgData != null) {
+            return mCurArgData;
+        } else if (mArgPos < mArgs.length) {
+            return mArgs[mArgPos];
+        } else {
+            return null;
+        }
+    }
+
     /**
      * Return the next argument on the command line, whatever it is; if there are
      * no arguments left, throws an IllegalArgumentException to report this to the user.
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 344d06e..24666fe 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -74,6 +74,9 @@
     /** @hide A user id constant to indicate the "system" user of the device */
     public static final @UserIdInt int USER_SYSTEM = 0;
 
+    /** @hide A user serial constant to indicate the "system" user of the device */
+    public static final int USER_SERIAL_SYSTEM = 0;
+
     /** @hide A user handle to indicate the "system" user of the device */
     public static final UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
 
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 1ac798b..dc0e249 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -64,8 +64,8 @@
      * use {@link android.accounts.AccountManager} APIs to add or remove accounts when account
      * management is disallowed.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -75,10 +75,10 @@
     /**
      * Specifies if a user is disallowed from changing Wi-Fi
      * access points. The default value is <code>false</code>.
-     * <p/>This restriction has no effect in a managed profile.
+     * <p>This restriction has no effect in a managed profile.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -89,8 +89,8 @@
      * Specifies if a user is disallowed from installing applications.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -101,8 +101,8 @@
      * Specifies if a user is disallowed from uninstalling applications.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -112,11 +112,11 @@
     /**
      * Specifies if a user is disallowed from turning on location sharing.
      * The default value is <code>false</code>.
-     * <p/>In a managed profile, location sharing always reflects the primary user's setting, but
+     * <p>In a managed profile, location sharing always reflects the primary user's setting, but
      * can be overridden and forced off by setting this restriction to true in the managed profile.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -128,8 +128,8 @@
      * "Unknown Sources" setting, that allows installation of apps from unknown sources.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -140,10 +140,10 @@
      * Specifies if a user is disallowed from configuring bluetooth.
      * This does <em>not</em> restrict the user from turning bluetooth on or off.
      * The default value is <code>false</code>.
-     * <p/>This restriction has no effect in a managed profile.
+     * <p>This restriction has no effect in a managed profile.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -155,8 +155,8 @@
      * USB. This can only be set by device owners and profile owners on the primary user.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -167,8 +167,8 @@
      * Specifies if a user is disallowed from configuring user
      * credentials. The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -181,8 +181,8 @@
      * This restriction has no effect on managed profiles.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -193,8 +193,8 @@
      * Specifies if a user is disallowed from enabling or
      * accessing debugging features. The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -207,8 +207,8 @@
      * This restriction has an effect in a managed profile only from
      * {@link android.os.Build.VERSION_CODES#M}
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -220,8 +220,8 @@
      * & portable hotspots. This can only be set by device owners and profile owners on the
      * primary user. The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -232,11 +232,11 @@
      * Specifies if a user is disallowed from resetting network settings
      * from Settings. This can only be set by device owners and profile owners on the primary user.
      * The default value is <code>false</code>.
-     * <p/>This restriction has no effect on secondary users and managed profiles since only the
+     * <p>This restriction has no effect on secondary users and managed profiles since only the
      * primary user can reset the network settings of the device.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -247,11 +247,11 @@
      * Specifies if a user is disallowed from factory resetting
      * from Settings. This can only be set by device owners and profile owners on the primary user.
      * The default value is <code>false</code>.
-     * <p/>This restriction has no effect on secondary users and managed profiles since only the
+     * <p>This restriction has no effect on secondary users and managed profiles since only the
      * primary user can factory reset the device.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -262,11 +262,11 @@
      * Specifies if a user is disallowed from adding new users and
      * profiles. This can only be set by device owners and profile owners on the primary user.
      * The default value is <code>false</code>.
-     * <p/>This restriction has no effect on secondary users and managed profiles since only the
+     * <p>This restriction has no effect on secondary users and managed profiles since only the
      * primary user can add other users.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -277,8 +277,8 @@
      * Specifies if a user is disallowed from disabling application
      * verification. The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -289,11 +289,11 @@
      * Specifies if a user is disallowed from configuring cell
      * broadcasts. This can only be set by device owners and profile owners on the primary user.
      * The default value is <code>false</code>.
-     * <p/>This restriction has no effect on secondary users and managed profiles since only the
+     * <p>This restriction has no effect on secondary users and managed profiles since only the
      * primary user can configure cell broadcasts.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -304,11 +304,11 @@
      * Specifies if a user is disallowed from configuring mobile
      * networks. This can only be set by device owners and profile owners on the primary user.
      * The default value is <code>false</code>.
-     * <p/>This restriction has no effect on secondary users and managed profiles since only the
+     * <p>This restriction has no effect on secondary users and managed profiles since only the
      * primary user can configure mobile networks.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -328,8 +328,8 @@
      * <p>
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -341,8 +341,8 @@
      * physical external media. This can only be set by device owners and profile owners on the
      * primary user. The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -354,8 +354,8 @@
      * volume. If set, the microphone will be muted. This can only be set by device owners
      * and profile owners on the primary user. The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -367,8 +367,8 @@
      * volume. If set, the master volume will be muted. This can only be set by device owners
      * and profile owners on the primary user. The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -379,11 +379,11 @@
      * Specifies that the user is not allowed to make outgoing
      * phone calls. Emergency calls are still permitted.
      * The default value is <code>false</code>.
-     * <p/>This restriction has no effect on managed profiles since call intents are normally
+     * <p>This restriction has no effect on managed profiles since call intents are normally
      * forwarded to the primary user.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -394,8 +394,8 @@
      * Specifies that the user is not allowed to send or receive
      * SMS messages. The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -407,8 +407,8 @@
      * device owner may wish to prevent the user from experiencing amusement or
      * joy while using the device. The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -428,8 +428,8 @@
      * <p>This can only be set by device owners and profile owners on the primary user.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -442,8 +442,8 @@
      * pasted in this profile.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -454,8 +454,8 @@
      * Specifies if the user is not allowed to use NFC to beam out data from apps.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -463,9 +463,11 @@
     public static final String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
 
     /**
-     * Hidden user restriction to disallow access to wallpaper manager APIs. This user restriction
-     * is always set for managed profiles.
+     * Hidden user restriction to disallow access to wallpaper manager APIs. This restriction
+     * generally means that wallpapers are not supported for the particular user. This user
+     * restriction is always set for managed profiles, because such profiles don't have wallpapers.
      * @hide
+     * @see #DISALLOW_SET_WALLPAPER
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -473,12 +475,25 @@
     public static final String DISALLOW_WALLPAPER = "no_wallpaper";
 
     /**
+     * User restriction to disallow setting a wallpaper. Profile owner and device owner
+     * are able to set wallpaper regardless of this restriction.
+     * The default value is <code>false</code>.
+     *
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
+
+    /**
      * Specifies if the user is not allowed to reboot the device into safe boot mode.
      * This can only be set by device owners and profile owners on the primary user.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -535,9 +550,7 @@
      * affected. The default value is <code>false</code>.
      *
      * <p>Key for user restrictions.
-     *
      * <p>Type: Boolean
-     *
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -555,8 +568,8 @@
      * define a host can handle intents from the managed profile.
      * The default value is <code>false</code>.
      *
-     * <p/>Key for user restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
@@ -575,8 +588,8 @@
      * management application that sets this flag to update it when the final
      * restrictions are enforced.
      *
-     * <p/>Key for application restrictions.
-     * <p/>Type: Boolean
+     * <p>Key for application restrictions.
+     * <p>Type: Boolean
      * @see android.app.admin.DevicePolicyManager#setApplicationRestrictions(
      *      android.content.ComponentName, String, Bundle)
      * @see android.app.admin.DevicePolicyManager#getApplicationRestrictions(
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 9b3f02d..dd8eb5f 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -1284,7 +1284,7 @@
 
             @Override
             public void prepareUserStorage(
-                    String volumeUuid, int userId, int serialNumber, boolean ephemeral)
+                    String volumeUuid, int userId, int serialNumber, int flags)
                     throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
@@ -1293,7 +1293,7 @@
                     _data.writeString(volumeUuid);
                     _data.writeInt(userId);
                     _data.writeInt(serialNumber);
-                    _data.writeInt(ephemeral ? 1 : 0);
+                    _data.writeInt(flags);
                     mRemote.transact(Stub.TRANSACTION_prepareUserStorage, _data, _reply, 0);
                     _reply.readException();
                 } finally {
@@ -2055,8 +2055,8 @@
                     String volumeUuid = data.readString();
                     int userId = data.readInt();
                     int serialNumber = data.readInt();
-                    boolean ephemeral = data.readInt() != 0;
-                    prepareUserStorage(volumeUuid, userId, serialNumber, ephemeral);
+                    int _flags = data.readInt();
+                    prepareUserStorage(volumeUuid, userId, serialNumber, _flags);
                     reply.writeNoException();
                     return true;
                 }
@@ -2389,7 +2389,7 @@
     public boolean isUserKeyUnlocked(int userId) throws RemoteException;
 
     public void prepareUserStorage(String volumeUuid, int userId, int serialNumber,
-            boolean ephemeral) throws RemoteException;
+            int flags) throws RemoteException;
 
     public ParcelFileDescriptor mountAppFuse(String name) throws RemoteException;
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index c8b942b..b82638a 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -92,8 +92,14 @@
     /** {@hide} */
     public static final int DEBUG_EMULATE_FBE = 1 << 1;
 
+    // NOTE: keep in sync with installd
     /** {@hide} */
-    public static final int FLAG_FOR_WRITE = 1 << 0;
+    public static final int FLAG_STORAGE_DE = 1 << 0;
+    /** {@hide} */
+    public static final int FLAG_STORAGE_CE = 1 << 1;
+
+    /** {@hide} */
+    public static final int FLAG_FOR_WRITE = 1 << 8;
 
     private final Context mContext;
     private final ContentResolver mResolver;
@@ -1003,10 +1009,9 @@
     }
 
     /** {@hide} */
-    public void prepareUserStorage(
-            String volumeUuid, int userId, int serialNumber, boolean ephemeral) {
+    public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
         try {
-            mMountService.prepareUserStorage(volumeUuid, userId, serialNumber, ephemeral);
+            mMountService.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 5997515..4b70649 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -438,8 +438,11 @@
         final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.setData(uri);
+
+        // note that docsui treats this as *force* show advanced. So sending
+        // false permits advanced to be shown based on user preferences.
+        intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, isPrimary());
         intent.putExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, true);
-        intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, true);
         return intent;
     }
 
diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java
index 8892e34..e9c196d 100644
--- a/core/java/android/print/PrintAttributes.java
+++ b/core/java/android/print/PrintAttributes.java
@@ -27,6 +27,7 @@
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.internal.R;
@@ -872,6 +873,23 @@
             mPackageName = null;
         }
 
+        /**
+         * Get the Id of all predefined media sizes beside the {@link #UNKNOWN_PORTRAIT} and
+         * {@link #UNKNOWN_LANDSCAPE}.
+         *
+         * @return List of all predefined media sizes
+         *
+         * @hide
+         */
+        public static @NonNull ArraySet<MediaSize> getAllPredefinedSizes() {
+            ArraySet<MediaSize> definedMediaSizes = new ArraySet<>(sIdToMediaSizeMap.values());
+
+            definedMediaSizes.remove(UNKNOWN_PORTRAIT);
+            definedMediaSizes.remove(UNKNOWN_LANDSCAPE);
+
+            return definedMediaSizes;
+        }
+
         /** @hide */
         public MediaSize(String id, String label, String packageName,
                 int widthMils, int heightMils, int labelResId) {
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index 2a9d4ae..ea54f92 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -20,35 +20,126 @@
 import android.os.Bundle;
 
 /**
- * Constants and methods to access blocked phone numbers for incoming calls and texts.
+ * <p>
+ * The contract between the blockednumber provider and applications. Contains definitions for
+ * the supported URIs and columns.
+ * </p>
  *
- * TODO javadoc
- * - Proper javadoc tagging.
- * - Code sample?
- * - Describe who can access it.
+ * <h3> Overview </h3>
+ * <p>
+ * The content provider exposes a table containing blocked numbers. The columns and URIs for
+ * accessing this table are defined by the {@link BlockedNumbers} class. Messages, and calls from
+ * blocked numbers are discarded by the platform. Notifications upon provider changes can be
+ * received using a {@link android.database.ContentObserver}.
+ * </p>
+ *
+ * <h3> Permissions </h3>
+ * <p>
+ * Only the system, the default SMS application, and the default phone app
+ * (See {@link android.telecom.TelecomManager#getDefaultDialerPackage()}), and carrier apps
+ * (See {@link android.service.carrier.CarrierService}) can read, and write to the blockednumber
+ * provider.
+ * </p>
+ *
+ * <h3> Data </h3>
+ * <p>
+ * Other than regular phone numbers, the blocked number provider can also store addresses (such
+ * as email) from which a user can receive messages, and calls. The blocked numbers are stored
+ * in the {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} column. A normalized version of phone
+ * numbers (if normalization is possible) is stored in {@link BlockedNumbers#COLUMN_E164_NUMBER}
+ * column. The platform blocks calls, and messages from an address if it is present in in the
+ * {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} column or if the E164 version of the address
+ * matches the {@link BlockedNumbers#COLUMN_E164_NUMBER} column.
+ * </p>
+ *
+ * <h3> Operations </h3>
+ * <dl>
+ * <dt><b>Insert</b></dt>
+ * <dd>
+ * <p>
+ * {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} is a required column that needs to be populated.
+ * Apps can optionally provide the {@link BlockedNumbers#COLUMN_E164_NUMBER} which is the phone
+ * number's E164 representation. The provider automatically populates this column if the app does
+ * not provide it. Note that this column is not populated if normalization fails or if the address
+ * is not a phone number (eg: email). The provider enforces uniqueness constraint on this column.
+ * Examples:
+ * <pre>
+ * ContentValues values = new ContentValues();
+ * values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890");
+ * Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
+ * </pre>
+ * <pre>
+ * ContentValues values = new ContentValues();
+ * values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890");
+ * values.put(BlockedNumbers.COLUMN_E164_NUMBER, "+11234567890");
+ * Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
+ * </pre>
+ * <pre>
+ * ContentValues values = new ContentValues();
+ * values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "12345@abdcde.com");
+ * Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
+ * </pre>
+ * </p>
+ * </dd>
+ * <dt><b>Update</b></dt>
+ * <dd>
+ * <p>
+ * Updates are not supported. Use Delete, and Insert instead.
+ * </p>
+ * </dd>
+ * <dt><b>Delete</b></dt>
+ * <dd>
+ * <p>
+ * Deletions can be performed as follows:
+ * <pre>
+ * ContentValues values = new ContentValues();
+ * values.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890");
+ * Uri uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values);
+ * getContentResolver().delete(uri, null, null);
+ * </pre>
+ * </p>
+ * </dd>
+ * <dt><b>Query</b></dt>
+ * <dd>
+ * <p>
+ * All blocked numbers can be enumerated as follows:
+ * <pre>
+ * Cursor c = getContentResolver().query(BlockedNumbers.CONTENT_URI,
+ *          new String[]{BlockedNumbers.COLUMN_ID, BlockedNumbers.COLUMN_ORIGINAL_NUMBER,
+ *          BlockedNumbers.COLUMN_E164_NUMBER}, null, null, null);
+ * </pre>
+ * To check if a particular number is blocked, use the method
+ * {@link #isBlocked(Context, String)}.
+ * </p>
+ * </dd>
+ *
+ * <h3> Multi-user </h3>
+ * <p>
+ * Apps must use the method {@link #canCurrentUserBlockNumbers(Context)} before performing any
+ * operation on the blocked number provider. If {@link #canCurrentUserBlockNumbers(Context)} returns
+ * {@code false}, all operations on the provider will fail with an
+ * {@link UnsupportedOperationException}. The platform will block calls, and messages from numbers
+ * in the provider independent of the current user.
+ * </p>
  */
 public class BlockedNumberContract {
     private BlockedNumberContract() {
     }
 
-    /** The authority for the contacts provider */
+    /** The authority for the blocked number provider */
     public static final String AUTHORITY = "com.android.blockednumber";
 
-    /** A content:// style uri to the authority for the contacts provider */
+    /** A content:// style uri to the authority for the blocked number provider */
     public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
 
     /**
-     * TODO javadoc
-     *
-     * Constants to interact with the blocked phone number list.
+     * Constants to interact with the blocked numbers list.
      */
     public static class BlockedNumbers {
         private BlockedNumbers() {
         }
 
         /**
-         * TODO javadoc
-         *
          * Content URI for the blocked numbers.
          *
          * Supported operations
@@ -91,14 +182,6 @@
         /**
          * Phone number to block.  The system generates it from {@link #COLUMN_ORIGINAL_NUMBER}
          * by removing all formatting characters.
-         * <p>Must NOT be specified in {@code insert}.
-         * <p>TYPE: String</p>
-         */
-        public static final String COLUMN_STRIPPED_NUMBER = "stripped_number";
-
-        /**
-         * Phone number to block.  The system generates it from {@link #COLUMN_ORIGINAL_NUMBER}
-         * by removing all formatting characters.
          * <p>Optional in {@code insert}.  When not specified, the system tries to generate it
          * assuming the current country. (Which will still be null if the number is not valid.)
          * <p>TYPE: String</p>
@@ -112,17 +195,32 @@
     /** @hide */
     public static final String RES_NUMBER_IS_BLOCKED = "blocked";
 
+    /** @hide */
+    public static final String METHOD_CAN_CURRENT_USER_BLOCK_NUMBERS =
+            "can_current_user_block_numbers";
+
+    /** @hide */
+    public static final String RES_CAN_BLOCK_NUMBERS = "can_block";
+
     /**
      * Returns whether a given number is in the blocked list.
-     *
-     * TODO This should probably catch IllegalArgumentException to guard against the case where
-     * the provider is encrypted or the user is not running.
-     * (See addEntryAndRemoveExpiredEntries() in
-     * http://ag/#/c/844426/3/core/java/android/provider/CallLog.java)
+     * <p> Note that if the {@link #canCurrentUserBlockNumbers} is {@code false} for the user
+     * context {@code context}, this method will throw an {@link UnsupportedOperationException}.
      */
     public static boolean isBlocked(Context context, String phoneNumber) {
-        final Bundle res = context.getContentResolver().call(AUTHORITY_URI,
-                METHOD_IS_BLOCKED, phoneNumber, null);
+        final Bundle res = context.getContentResolver().call(
+                AUTHORITY_URI, METHOD_IS_BLOCKED, phoneNumber, null);
         return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
     }
+
+    /**
+     * Returns {@code true} if blocking numbers is supported for the current user.
+     * <p> Typically, blocking numbers is only supported for the primary user.
+     */
+    public static boolean canCurrentUserBlockNumbers(Context context) {
+        final Bundle res = context.getContentResolver().call(
+                AUTHORITY_URI, METHOD_CAN_CURRENT_USER_BLOCK_NUMBERS, null, null);
+        return res != null && res.getBoolean(RES_CAN_BLOCK_NUMBERS, false);
+    }
+
 }
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 330fcf6..dfdd36d 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -2079,10 +2079,11 @@
             if (preferHighres) {
                 final Uri displayPhotoUri = Uri.withAppendedPath(contactUri,
                         Contacts.Photo.DISPLAY_PHOTO);
-                InputStream inputStream;
                 try {
                     AssetFileDescriptor fd = cr.openAssetFileDescriptor(displayPhotoUri, "r");
-                    return fd.createInputStream();
+                    if (fd != null) {
+                        return fd.createInputStream();
+                    }
                 } catch (IOException e) {
                     // fallback to the thumbnail code
                 }
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 032d83d..8468040 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -362,6 +362,15 @@
         public static final int FLAG_VIRTUAL_DOCUMENT = 1 << 9;
 
         /**
+         * Flag indicating that a document can be removed from a parent.
+         *
+         * @see #COLUMN_FLAGS
+         * @see DocumentsContract#removeDocument(ContentProviderClient, Uri, Uri)
+         * @see DocumentsProvider#removeDocument(String, String)
+         */
+        public static final int FLAG_SUPPORTS_REMOVE = 1 << 10;
+
+        /**
          * Flag indicating that a document is an archive, and it's contents can be
          * obtained via {@link DocumentsProvider#queryChildDocuments}.
          * <p>
@@ -370,18 +379,10 @@
          *
          * @see #COLUMN_FLAGS
          * @see DocumentsProvider#queryChildDocuments(String, String[], String)
+         * @hide
          */
-        public static final int FLAG_ARCHIVE = 1 << 10;
 
-        /**
-         * Flag indicating that a document can be removed from a parent.
-         *
-         * @see #COLUMN_FLAGS
-         * @see DocumentsContract#removeDocument(ContentProviderClient, Uri, Uri)
-         * @see DocumentsProvider#removeDocument(String, String)
-         */
-        public static final int FLAG_SUPPORTS_REMOVE = 1 << 11;
-
+        public static final int FLAG_ARCHIVE = 1 << 15;
         /**
          * Flag indicating that document titles should be hidden when viewing
          * this directory in a larger format grid. For example, a directory
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1561d46..7830142 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -670,14 +670,14 @@
             "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
 
     /**
-     * Activity Action: Ask the user to allow an to ignore battery optimizations (that is,
+     * Activity Action: Ask the user to allow an app to ignore battery optimizations (that is,
      * put them on the whitelist of apps shown by
      * {@link #ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS}).  For an app to use this, it also
      * must hold the {@link android.Manifest.permission#REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}
      * permission.
      * <p><b>Note:</b> most applications should <em>not</em> use this; there are many facilities
      * provided by the platform for applications to operate correctly in the various power
-     * saving mode.  This is only for unusual applications that need to deeply control their own
+     * saving modes.  This is only for unusual applications that need to deeply control their own
      * execution, at the potential expense of the user's battery life.  Note that these applications
      * greatly run the risk of showing to the user as high power consumers on their device.</p>
      * <p>
@@ -695,6 +695,24 @@
             "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
 
     /**
+     * Activity Action: Show screen for controlling which apps can ignore background data
+     * restrictions.
+     * <p>
+     * Input: if the Intent's data URI is set with an application name (using the "package" schema,
+     * like "package:com.my.app"), then when the screen is displayed it will focus on such app. If
+     * the data is not set, it will just open the screen.
+     * <p>
+     * Output: Nothing.
+     * <p>
+     * Applications can also use {@link android.net.ConnectivityManager#getRestrictBackgroundStatus
+     * ConnectivityManager#getRestrictBackgroundStatus()} to determine the status of the background
+     * data restrictions for them.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS =
+            "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
+
+    /**
      * @hide
      * Activity Action: Show the "app ops" settings screen.
      * <p>
@@ -3851,7 +3869,6 @@
             MOVED_TO_GLOBAL.add(Settings.Global.DATA_ROAMING);
             MOVED_TO_GLOBAL.add(Settings.Global.DEVELOPMENT_SETTINGS_ENABLED);
             MOVED_TO_GLOBAL.add(Settings.Global.DEVICE_PROVISIONED);
-            MOVED_TO_GLOBAL.add(Settings.Global.DISPLAY_DENSITY_FORCED);
             MOVED_TO_GLOBAL.add(Settings.Global.DISPLAY_SIZE_FORCED);
             MOVED_TO_GLOBAL.add(Settings.Global.DOWNLOAD_MAX_BYTES_OVER_MOBILE);
             MOVED_TO_GLOBAL.add(Settings.Global.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE);
@@ -5086,6 +5103,15 @@
             "disabled_print_services";
 
         /**
+         * The saved value for WindowManagerService.setForcedDisplayDensity()
+         * formatted as a single integer representing DPI. If unset, then use
+         * the real display density.
+         *
+         * @hide
+         */
+        public static final String DISPLAY_DENSITY_FORCED = "display_density_forced";
+
+        /**
          * Setting to always use the default text-to-speech settings regardless
          * of the application settings.
          * 1 = override application settings,
@@ -6517,13 +6543,6 @@
        public static final String DEVICE_PROVISIONED = "device_provisioned";
 
        /**
-        * The saved value for WindowManagerService.setForcedDisplayDensity().
-        * One integer in dpi.  If unset, then use the real display density.
-        * @hide
-        */
-       public static final String DISPLAY_DENSITY_FORCED = "display_density_forced";
-
-       /**
         * The saved value for WindowManagerService.setForcedDisplaySize().
         * Two integers separated by a comma.  If unset, then use the real display size.
         * @hide
@@ -6895,6 +6914,15 @@
        public static final String TETHER_DUN_APN = "tether_dun_apn";
 
        /**
+        * List of carrier apps which are whitelisted to prompt the user for install when
+        * a sim card with matching uicc carrier privilege rules is inserted.
+        *
+        * The value is "package1;package2;..."
+        * @hide
+        */
+       public static final String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
+
+       /**
         * USB Mass Storage Enabled
         */
        public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
diff --git a/core/java/android/service/chooser/ChooserTargetService.java b/core/java/android/service/chooser/ChooserTargetService.java
index e054185..a1afa60 100644
--- a/core/java/android/service/chooser/ChooserTargetService.java
+++ b/core/java/android/service/chooser/ChooserTargetService.java
@@ -139,6 +139,7 @@
         public void getChooserTargets(ComponentName targetComponentName,
                 IntentFilter matchedFilter, IChooserTargetResult result) throws RemoteException {
             List<ChooserTarget> targets = null;
+            final long id = clearCallingIdentity();
             try {
                 if (DEBUG) {
                     Log.d(TAG, "getChooserTargets calling onGetChooserTargets; "
@@ -146,6 +147,7 @@
                 }
                 targets = onGetChooserTargets(targetComponentName, matchedFilter);
             } finally {
+                restoreCallingIdentity(id);
                 result.sendResult(targets);
                 if (DEBUG) Log.d(TAG, "Sent results");
             }
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 2c7bf65..11737c6 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -16,6 +16,7 @@
 
 package android.service.notification;
 
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Parcel;
@@ -24,7 +25,8 @@
 import java.util.Objects;
 
 /**
- * Condition information from condition providers.
+ * Condition information from condition providers. Used to tell the system to enter Do Not Disturb
+ * mode and request that the system exit Do Not Disturb mode.
  */
 public class Condition implements Parcelable {
 
@@ -38,14 +40,47 @@
     public static final int FLAG_RELEVANT_NOW = 1 << 0;
     public static final int FLAG_RELEVANT_ALWAYS = 1 << 1;
 
+    /**
+     * The URI representing the condition being updated.
+     * See {@link android.app.AutomaticZenRule#getConditionId()}.
+     */
     public final Uri id;
-    public final String summary;
-    public final String line1;
-    public final String line2;
-    public final int icon;
-    public final int state;
-    public final int flags;
 
+    /**
+     * A summary of what the rule encoded in {@link #id} means when it is enabled. User visible
+     * if the state of the condition is {@link #STATE_TRUE}.
+     */
+    public final String summary;
+
+    /**
+     * Additional information about what the rule encoded in {@link #id} means when it is enabled.
+     * User visible if the state of the condition is {@link #STATE_TRUE}.
+     */
+    public final String line1;
+
+    /**
+     * Additional information about what the rule encoded in {@link #id} means when it is enabled.
+     * User visible if the state of the condition is {@link #STATE_TRUE}.
+     */
+    public final String line2;
+
+    /**
+     * The state of this condition. {@link #STATE_TRUE} will enable Do Not Disturb mode. Any other
+     * state will turn Do Not Disturb off for this rule. Note that Do Not Disturb might still be
+     * enabled globally if other conditions are in a {@link #STATE_TRUE} state.
+     */
+    public final int state;
+
+    @SystemApi
+    public final int flags;
+    @SystemApi
+    public final int icon;
+
+    public Condition(Uri id, String summary, String line1, String line2, int state) {
+        this(id, summary, line1, line2, -1, state, FLAG_RELEVANT_ALWAYS);
+    }
+
+    @SystemApi
     public Condition(Uri id, String summary, String line1, String line2, int icon,
             int state, int flags) {
         if (id == null) throw new IllegalArgumentException("id is required");
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index eff09d6..adcc9d6 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -17,6 +17,7 @@
 package android.service.notification;
 
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.app.INotificationManager;
 import android.app.Service;
 import android.content.ComponentName;
@@ -102,13 +103,10 @@
     abstract public void onConnected();
 
     /**
-     * Called when the system wants to know the state of Conditions managed by this provider.
-     *
-     * Implementations should evaluate the state of all subscribed conditions, and provide updates
-     * by calling {@link #notifyCondition(Condition)} or {@link #notifyConditions(Condition...)}.
-     * @param relevance
+     * @removed
      */
-    abstract public void onRequestConditions(int relevance);
+    @SystemApi
+    public void onRequestConditions(int relevance) {}
 
     /**
      * Called by the system when there is a new {@link Condition} to be managed by this provider.
@@ -131,7 +129,11 @@
     }
 
     /**
-     * Informs the notification manager that the state of a Condition has changed.
+     * Informs the notification manager that the state of a Condition has changed. Use this method
+     * to put the system into Do Not Disturb mode or request that it exits Do Not Disturb mode. This
+     * call will be ignored unless there is an enabled {@link android.app.AutomaticZenRule} owned by
+     * service that has an {@link android.app.AutomaticZenRule#getConditionId()} equal to this
+     * {@link Condition#id}.
      * @param condition the condition that has changed.
      */
     public final void notifyCondition(Condition condition) {
@@ -140,7 +142,8 @@
     }
 
     /**
-     * Informs the notification manager that the state of one or more Conditions has changed.
+     * Informs the notification manager that the state of one or more Conditions has changed. See
+     * {@link #notifyCondition(Condition)} for restrictions.
      * @param conditions the changed conditions.
      */
     public final void notifyConditions(Condition... conditions) {
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index bd41fb5..fb58f4e 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -45,7 +45,9 @@
  *         &lt;action android:name="android.service.notification.NotificationAssistantService" />
  *     &lt;/intent-filter>
  * &lt;/service></pre>
+ * @hide
  */
+@SystemApi
 public abstract class NotificationAssistantService extends NotificationListenerService {
     private static final String TAG = "NotificationAssistant";
 
@@ -101,6 +103,9 @@
     /** Notification was canceled by the device administrator suspending the package. */
     public static final int REASON_PACKAGE_SUSPENDED = 15;
 
+    /** Notification was canceled by the owning managed profile being turned off. */
+    public static final int REASON_PROFILE_TURNED_OFF = 16;
+
     public class Adjustment {
         int mImportance;
         CharSequence mExplanation;
@@ -207,29 +212,6 @@
         }
     }
 
-    /**
-     * Add an annotation to a an existing notification. The delete intent will
-     * be fired when the host notification is deleted, or when this annotation
-     * is removed or replaced.
-     *
-     * @param key the key of the notification to be annotated
-     * @param annotation the new annotation object
-     */
-    public final void setAnnotation(String key, Notification annotation)
-    {
-        // TODO: pack up the annotation and send it to the NotificationManager.
-    }
-
-    /**
-     * Remove the annotation from a notification.
-     *
-     * @param key the key of the notification to be cleansed of annotatons
-     */
-    public final void clearAnnotation(String key)
-    {
-        // TODO: ask the NotificationManager to clear the annotation.
-    }
-
     private class NotificationAssistantWrapper extends NotificationListenerWrapper {
         @Override
         public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder,
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index ed90e79..7ff883e 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -695,7 +695,7 @@
     /**
      * Request that the listener be rebound, after a previous call to (@link requestUnbind).
      *
-     * <P>This method will fail for assistants 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
@@ -1022,8 +1022,7 @@
         }
 
         /**
-         * If the importance has been overriden by user preference, or by a
-         * {@link NotificationAssistantService}, then this will be non-null,
+         * If the importance has been overriden by user preference, then this will be non-null,
          * and should be displayed to the user.
          *
          * @return the explanation for the importance, or null if it is the natural importance
diff --git a/core/java/android/service/quicksettings/IQSService.aidl b/core/java/android/service/quicksettings/IQSService.aidl
index 4bfc948..1d90505 100644
--- a/core/java/android/service/quicksettings/IQSService.aidl
+++ b/core/java/android/service/quicksettings/IQSService.aidl
@@ -32,4 +32,6 @@
     boolean isLocked();
     boolean isSecure();
     void startUnlockAndRun(in Tile tile);
+
+    void onDialogHidden(in Tile tile);
 }
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index c02465b..0cf1175 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -28,6 +28,8 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
 import android.view.WindowManager;
 
 /**
@@ -206,6 +208,20 @@
     public final void showDialog(Dialog dialog) {
         dialog.getWindow().getAttributes().token = mToken;
         dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_QS_DIALOG);
+        dialog.getWindow().getDecorView().addOnAttachStateChangeListener(
+                new OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View v) {
+            }
+
+            @Override
+            public void onViewDetachedFromWindow(View v) {
+                try {
+                    mService.onDialogHidden(getQsTile());
+                } catch (RemoteException e) {
+                }
+            }
+        });
         dialog.show();
         try {
             mService.onShowDialog(mTile);
diff --git a/core/java/android/text/BidiFormatter.java b/core/java/android/text/BidiFormatter.java
index a535480..675803c 100644
--- a/core/java/android/text/BidiFormatter.java
+++ b/core/java/android/text/BidiFormatter.java
@@ -293,7 +293,7 @@
      * directionality is determined by scanning the end of the string, the overall directionality is
      * given explicitly by a heuristic to estimate the {@code str}'s directionality.
      *
-     * @param str String after which the mark may need to appear.
+     * @param str CharSequence after which the mark may need to appear.
      * @param heuristic The text direction heuristic that will be used to estimate the {@code str}'s
      *                  directionality.
      * @return LRM for RTL text in LTR context; RLM for LTR text in RTL context;
@@ -301,7 +301,7 @@
      *
      * @hide
      */
-    public String markAfter(String str, TextDirectionHeuristic heuristic) {
+    public String markAfter(CharSequence str, TextDirectionHeuristic heuristic) {
         final boolean isRtl = heuristic.isRtl(str, 0, str.length());
         // getExitDir() is called only if needed (short-circuit).
         if (!mIsRtlContext && (isRtl || getExitDir(str) == DIR_RTL)) {
@@ -322,7 +322,7 @@
      * entry directionality is determined by scanning the beginning of the string, the overall
      * directionality is given explicitly by a heuristic to estimate the {@code str}'s directionality.
      *
-     * @param str String before which the mark may need to appear.
+     * @param str CharSequence before which the mark may need to appear.
      * @param heuristic The text direction heuristic that will be used to estimate the {@code str}'s
      *                  directionality.
      * @return LRM for RTL text in LTR context; RLM for LTR text in RTL context;
@@ -330,7 +330,7 @@
      *
      * @hide
      */
-    public String markBefore(String str, TextDirectionHeuristic heuristic) {
+    public String markBefore(CharSequence str, TextDirectionHeuristic heuristic) {
         final boolean isRtl = heuristic.isRtl(str, 0, str.length());
         // getEntryDir() is called only if needed (short-circuit).
         if (!mIsRtlContext && (isRtl || getEntryDir(str) == DIR_RTL)) {
@@ -350,6 +350,13 @@
      *          false.
      */
     public boolean isRtl(String str) {
+        return isRtl((CharSequence) str);
+    }
+
+    /**
+     * @hide
+     */
+    public boolean isRtl(CharSequence str) {
         return mDefaultTextDirectionHeuristic.isRtl(str, 0, str.length());
     }
 
@@ -384,9 +391,16 @@
      *     {@code null}.
      */
     public String unicodeWrap(String str, TextDirectionHeuristic heuristic, boolean isolate) {
+        return unicodeWrap((CharSequence) str, heuristic, isolate).toString();
+    }
+
+    /**
+     * @hide
+     */
+    public CharSequence unicodeWrap(CharSequence str, TextDirectionHeuristic heuristic, boolean isolate) {
         if (str == null) return null;
         final boolean isRtl = heuristic.isRtl(str, 0, str.length());
-        StringBuilder result = new StringBuilder();
+        SpannableStringBuilder result = new SpannableStringBuilder();
         if (getStereoReset() && isolate) {
             result.append(markBefore(str,
                     isRtl ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR));
@@ -402,7 +416,7 @@
             result.append(markAfter(str,
                     isRtl ? TextDirectionHeuristics.RTL : TextDirectionHeuristics.LTR));
         }
-        return result.toString();
+        return result;
     }
 
     /**
@@ -419,6 +433,14 @@
     }
 
     /**
+     * @hide
+     */
+    public CharSequence unicodeWrap(CharSequence str, TextDirectionHeuristic heuristic) {
+        return unicodeWrap(str, heuristic, true /* isolate */);
+    }
+
+
+    /**
      * Operates like {@link #unicodeWrap(String, TextDirectionHeuristic, boolean)}, but uses the
      * formatter's default direction estimation algorithm.
      *
@@ -432,6 +454,13 @@
     }
 
     /**
+     * @hide
+     */
+    public CharSequence unicodeWrap(CharSequence str, boolean isolate) {
+        return unicodeWrap(str, mDefaultTextDirectionHeuristic, isolate);
+    }
+
+    /**
      * Operates like {@link #unicodeWrap(String, TextDirectionHeuristic, boolean)}, but uses the
      * formatter's default direction estimation algorithm and assumes {@code isolate} is true.
      *
@@ -442,6 +471,13 @@
         return unicodeWrap(str, mDefaultTextDirectionHeuristic, true /* isolate */);
     }
 
+    /**
+     * @hide
+     */
+    public CharSequence unicodeWrap(CharSequence str) {
+        return unicodeWrap(str, mDefaultTextDirectionHeuristic, true /* isolate */);
+    }
+
     private static BidiFormatter getDefaultInstanceFromContext(boolean isRtlContext) {
         return isRtlContext ? DEFAULT_RTL_INSTANCE : DEFAULT_LTR_INSTANCE;
     }
@@ -477,7 +513,7 @@
      *
      * @param str the string to check.
      */
-    private static int getExitDir(String str) {
+    private static int getExitDir(CharSequence str) {
         return new DirectionalityEstimator(str, false /* isHtml */).getExitDir();
     }
 
@@ -494,7 +530,7 @@
      *
      * @param str the string to check.
      */
-    private static int getEntryDir(String str) {
+    private static int getEntryDir(CharSequence str) {
         return new DirectionalityEstimator(str, false /* isHtml */).getEntryDir();
     }
 
@@ -532,7 +568,7 @@
         /**
          * The text to be scanned.
          */
-        private final String text;
+        private final CharSequence text;
 
         /**
          * Whether the text to be scanned is to be treated as HTML, i.e. skipping over tags and
@@ -565,7 +601,7 @@
          * @param isHtml Whether the text to be scanned is to be treated as HTML, i.e. skipping over
          *     tags and entities.
          */
-        DirectionalityEstimator(String text, boolean isHtml) {
+        DirectionalityEstimator(CharSequence text, boolean isHtml) {
             this.text = text;
             this.isHtml = isHtml;
             length = text.length();
@@ -896,4 +932,4 @@
             return Character.DIRECTIONALITY_OTHER_NEUTRALS;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/text/style/LocaleSpan.java b/core/java/android/text/style/LocaleSpan.java
index 117de774..4f687c8 100644
--- a/core/java/android/text/style/LocaleSpan.java
+++ b/core/java/android/text/style/LocaleSpan.java
@@ -97,12 +97,12 @@
      * @return The {@link Locale} for this span.  If multiple locales are associated with this
      * span, only the first locale is returned.  {@code null} if no {@link Locale} is specified.
      *
-     * @see LocaleList#getPrimary()
+     * @see LocaleList#get()
      * @see #getLocales()
      */
     @Nullable
     public Locale getLocale() {
-        return mLocales.getPrimary();
+        return mLocales.get(0);
     }
 
     /**
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
index 90a20bc..fc39004 100644
--- a/core/java/android/util/LocaleList.java
+++ b/core/java/android/util/LocaleList.java
@@ -47,12 +47,7 @@
     private static final LocaleList sEmptyLocaleList = new LocaleList();
 
     public Locale get(int location) {
-        return location < mList.length ? mList[location] : null;
-    }
-
-    @Nullable
-    public Locale getPrimary() {
-        return mList.length == 0 ? null : get(0);
+        return (0 <= location && location < mList.length) ? mList[location] : null;
     }
 
     public boolean isEmpty() {
@@ -464,7 +459,7 @@
                 // someone has called Locale.setDefault() since we last set or adjusted the default
                 // locale list. So let's recalculate the locale list.
                 if (sDefaultLocaleList != null
-                        && defaultLocale.equals(sDefaultLocaleList.getPrimary())) {
+                        && defaultLocale.equals(sDefaultLocaleList.get(0))) {
                     // The default Locale has changed, but it happens to be the first locale in the
                     // default locale list, so we don't need to construct a new locale list.
                     return sDefaultLocaleList;
diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java
index 78d5bcd..29a72fd 100644
--- a/core/java/android/util/PathParser.java
+++ b/core/java/android/util/PathParser.java
@@ -104,6 +104,7 @@
             }
             super.finalize();
         }
+
     }
 
     /**
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 27ea92d..1740f07 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -381,4 +381,9 @@
      * @param receiver The receiver to deliver the results to.
      */
     void requestAppKeyboardShortcuts(IResultReceiver receiver);
+
+    /**
+     * Retrieves the current stable insets from the primary display.
+     */
+    void getStableInsets(out Rect outInsets);
 }
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 34713ad..b9a7421 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -21,7 +21,6 @@
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.RemoteViews;
 import android.widget.TextView;
 
@@ -33,9 +32,9 @@
  * @hide
  */
 @RemoteViews.RemoteView
-public class NotificationHeaderView extends LinearLayout {
+public class NotificationHeaderView extends ViewGroup {
     public static final int NO_COLOR = -1;
-    private final int mHeaderMinWidth;
+    private final int mChildMinWidth;
     private final int mExpandTopPadding;
     private final int mContentEndMargin;
     private View mAppName;
@@ -46,6 +45,7 @@
     private View mIcon;
     private TextView mChildCount;
     private View mProfileBadge;
+    private View mInfo;
     private int mIconColor;
     private int mOriginalNotificationColor;
     private boolean mGroupHeader;
@@ -66,7 +66,7 @@
 
     public NotificationHeaderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        mHeaderMinWidth = getResources().getDimensionPixelSize(
+        mChildMinWidth = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.notification_header_shrink_min_width);
         mContentEndMargin = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.notification_content_margin_end);
@@ -82,6 +82,7 @@
         mIcon = findViewById(com.android.internal.R.id.icon);
         mChildCount = (TextView) findViewById(com.android.internal.R.id.number_of_children);
         mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
+        mInfo = findViewById(com.android.internal.R.id.header_content_info);
     }
 
     @Override
@@ -109,14 +110,23 @@
         }
         if (totalWidth > givenWidth) {
             int overFlow = totalWidth - givenWidth;
-            // We are overflowing, lets shrink
+            // 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
             final int appWidth = mAppName.getMeasuredWidth();
-            if (mAppName.getVisibility() != GONE && appWidth > mHeaderMinWidth) {
-                int newSize = appWidth - Math.min(appWidth - mHeaderMinWidth, overFlow);
+            if (overFlow > 0 && mAppName.getVisibility() != GONE && appWidth > mChildMinWidth) {
+                int newSize = appWidth - Math.min(appWidth - mChildMinWidth, overFlow);
                 int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
                 mAppName.measure(childWidthSpec, wrapContentHeightSpec);
                 overFlow -= appWidth - newSize;
             }
+            // still overflowing, finaly we shrink the subtext
             if (overFlow > 0 && mSubTextView.getVisibility() != GONE) {
                 // we're still too big
                 final int subTextWidth = mSubTextView.getMeasuredWidth();
@@ -124,37 +134,52 @@
                 int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
                 mSubTextView.measure(childWidthSpec, wrapContentHeightSpec);
             }
-            totalWidth = givenWidth;
         }
-        if (mProfileBadge.getVisibility() != View.GONE) {
-            totalWidth = givenWidth;
-        }
-        setMeasuredDimension(totalWidth, givenHeight);
+        setMeasuredDimension(givenWidth, givenHeight);
     }
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        super.onLayout(changed, l, t, r, b);
-        if (mProfileBadge.getVisibility() != View.GONE) {
-            int paddingEnd = getPaddingEnd();
-            if (mShowWorkBadgeAtEnd) {
-                paddingEnd = mContentEndMargin;
+        int left = getPaddingStart();
+        int childCount = getChildCount();
+        int ownHeight = getHeight() - getPaddingTop() - getPaddingBottom();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() == GONE) {
+                continue;
+            }
+            int childHeight = child.getMeasuredHeight();
+            MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
+            left += params.getMarginStart();
+            int right = left + child.getMeasuredWidth();
+            int top = (int) (getPaddingTop() + (ownHeight - childHeight) / 2.0f);
+            int bottom = top + childHeight;
+            int layoutLeft = left;
+            int layoutRight = right;
+            if (child == mProfileBadge) {
+                int paddingEnd = getPaddingEnd();
+                if (mShowWorkBadgeAtEnd) {
+                    paddingEnd = mContentEndMargin;
+                }
+                layoutRight = getWidth() - paddingEnd;
+                layoutLeft = layoutRight - child.getMeasuredWidth();
             }
             if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
-                mProfileBadge.layout(paddingEnd,
-                        mProfileBadge.getTop(),
-                        paddingEnd + mProfileBadge.getMeasuredWidth(),
-                        mProfileBadge.getBottom());
-            } else {
-                mProfileBadge.layout(getWidth() - paddingEnd - mProfileBadge.getMeasuredWidth(),
-                        mProfileBadge.getTop(),
-                        getWidth() - paddingEnd,
-                        mProfileBadge.getBottom());
+                int ltrLeft = layoutLeft;
+                layoutLeft = getWidth() - layoutRight;
+                layoutRight = getWidth() - ltrLeft;
             }
+            child.layout(layoutLeft, top, layoutRight, bottom);
+            left = right + params.getMarginEnd();
         }
         updateTouchListener();
     }
 
+    @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new ViewGroup.MarginLayoutParams(getContext(), attrs);
+    }
+
     private void updateTouchListener() {
         if (mExpandClickListener != null) {
             mTouchListener.bindTouchRects();
@@ -256,18 +281,16 @@
             mTouchRects.clear();
             addRectAroundViewView(mIcon);
             addRectAroundViewView(mExpandButton);
-            addInBetweenRect();
+            addWidthRect();
             mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
         }
 
-        private void addInBetweenRect() {
-            final Rect r = new Rect();
+        private void addWidthRect() {
+            Rect r = new Rect();
             r.top = 0;
             r.bottom = (int) (32 * getResources().getDisplayMetrics().density);
-            Rect leftRect = mTouchRects.get(0);
-            r.left = leftRect.right;
-            Rect rightRect = mTouchRects.get(1);
-            r.right = rightRect.left;
+            r.left = 0;
+            r.right = getWidth();
             mTouchRects.add(r);
         }
 
diff --git a/core/java/android/view/RemotableViewMethod.java b/core/java/android/view/RemotableViewMethod.java
index 4318290..e5cae84 100644
--- a/core/java/android/view/RemotableViewMethod.java
+++ b/core/java/android/view/RemotableViewMethod.java
@@ -29,6 +29,12 @@
 @Target({ ElementType.METHOD })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface RemotableViewMethod {
+    /**
+     * @return Method name which can be called on a background thread. It should have the
+     * same arguments as the original method and should return a {@link Runnable} (or null)
+     * which will be called on the UI thread.
+     */
+    String asyncImpl() default "";
 }
 
 
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 88bffb5..7017ff5 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -22,6 +22,7 @@
 import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.graphics.drawable.AnimatedVectorDrawable;
 
 /**
  * <p>A display list records a series of graphics related operations and can replay
@@ -135,6 +136,9 @@
     private RenderNode(String name, View owningView) {
         mNativeRenderNode = nCreate(name);
         mOwningView = owningView;
+        if (mOwningView instanceof SurfaceView) {
+            nRequestPositionUpdates(mNativeRenderNode, (SurfaceView) mOwningView);
+        }
     }
 
     /**
@@ -771,6 +775,14 @@
         mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
     }
 
+    public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimator animatorSet) {
+        if (mOwningView == null || mOwningView.mAttachInfo == null) {
+            throw new IllegalStateException("Cannot start this animator on a detached view!");
+        }
+        nAddAnimator(mNativeRenderNode, animatorSet.getAnimatorNativePtr());
+        mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
+    }
+
     public void endAllAnimators() {
         nEndAllAnimators(mNativeRenderNode);
     }
@@ -854,6 +866,8 @@
     private static native void nOutput(long renderNode);
     private static native int nGetDebugSize(long renderNode);
 
+    private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback);
+
     ///////////////////////////////////////////////////////////////////////////
     // Animations
     ///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/RenderNodeAnimatorSetHelper.java b/core/java/android/view/RenderNodeAnimatorSetHelper.java
new file mode 100644
index 0000000..ba592d29
--- /dev/null
+++ b/core/java/android/view/RenderNodeAnimatorSetHelper.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view;
+
+import android.animation.TimeInterpolator;
+import com.android.internal.view.animation.FallbackLUTInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
+
+/**
+ * This is a helper class to get access to methods and fields needed for RenderNodeAnimatorSet
+ * that are internal or package private to android.view package.
+ *
+ * @hide
+ */
+public class RenderNodeAnimatorSetHelper {
+
+    public static RenderNode getTarget(DisplayListCanvas recordingCanvas) {
+        return recordingCanvas.mNode;
+    }
+
+    public static long createNativeInterpolator(TimeInterpolator interpolator, long
+            duration) {
+        if (interpolator == null) {
+            // create LinearInterpolator
+            return NativeInterpolatorFactoryHelper.createLinearInterpolator();
+        } else if (RenderNodeAnimator.isNativeInterpolator(interpolator)) {
+            return ((NativeInterpolatorFactory)interpolator).createNativeInterpolator();
+        } else {
+            return FallbackLUTInterpolator.createNativeInterpolator(interpolator, duration);
+        }
+    }
+
+}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 5b48e28..a296051 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -135,7 +135,7 @@
         }
     };
 
-    final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
+    private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
             = new ViewTreeObserver.OnScrollChangedListener() {
                     @Override
                     public void onScrollChanged() {
@@ -143,6 +143,17 @@
                     }
             };
 
+    private final ViewTreeObserver.OnPreDrawListener mDrawListener =
+            new ViewTreeObserver.OnPreDrawListener() {
+                @Override
+                public boolean onPreDraw() {
+                    // reposition ourselves where the surface is
+                    mHaveFrame = getWidth() > 0 && getHeight() > 0;
+                    updateWindow(false, false);
+                    return true;
+                }
+            };
+
     boolean mRequestedVisible = false;
     boolean mWindowVisibility = false;
     boolean mViewVisibility = false;
@@ -168,17 +179,9 @@
     boolean mUpdateWindowNeeded;
     boolean mReportDrawNeeded;
     private Translator mTranslator;
+    private int mWindowInsetLeft;
+    private int mWindowInsetTop;
 
-    private final ViewTreeObserver.OnPreDrawListener mDrawListener =
-            new ViewTreeObserver.OnPreDrawListener() {
-                @Override
-                public boolean onPreDraw() {
-                    // reposition ourselves where the surface is
-                    mHaveFrame = getWidth() > 0 && getHeight() > 0;
-                    updateWindow(false, false);
-                    return true;
-                }
-            };
     private boolean mGlobalListenersAdded;
 
     public SurfaceView(Context context) {
@@ -443,17 +446,17 @@
         int myHeight = mRequestedHeight;
         if (myHeight <= 0) myHeight = getHeight();
 
-        getLocationInWindow(mLocation);
         final boolean creating = mWindow == null;
         final boolean formatChanged = mFormat != mRequestedFormat;
         final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight;
         final boolean visibleChanged = mVisible != mRequestedVisible;
         final boolean layoutSizeChanged = getWidth() != mLayout.width
                 || getHeight() != mLayout.height;
-        final boolean positionChanged = mWindowSpaceLeft != mLocation[0] || mWindowSpaceTop != mLocation[1];
 
         if (force || creating || formatChanged || sizeChanged || visibleChanged
             || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
+            getLocationInWindow(mLocation);
+
             if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
                     + " format=" + formatChanged + " size=" + sizeChanged
                     + " visible=" + visibleChanged
@@ -643,27 +646,69 @@
                 TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
                 " w=" + mLayout.width + " h=" + mLayout.height +
                 ", frame=" + mSurfaceFrame);
-        } else if (positionChanged || layoutSizeChanged) { // Only the position has changed
-            mWindowSpaceLeft = mLocation[0];
-            mWindowSpaceTop = mLocation[1];
-            // For our size changed check, we keep mLayout.width and mLayout.height
-            // in view local space.
-            mLocation[0] = mLayout.width = getWidth();
-            mLocation[1] = mLayout.height = getHeight();
+        } else if (!isHardwareAccelerated()) {
+            getLocationInWindow(mLocation);
+            final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
+                    || mWindowSpaceTop != mLocation[1];
+            if (positionChanged || layoutSizeChanged) { // Only the position has changed
+                mWindowSpaceLeft = mLocation[0];
+                mWindowSpaceTop = mLocation[1];
+                // For our size changed check, we keep mLayout.width and mLayout.height
+                // in view local space.
+                mLocation[0] = mLayout.width = getWidth();
+                mLocation[1] = mLayout.height = getHeight();
 
-            transformFromViewToWindowSpace(mLocation);
+                transformFromViewToWindowSpace(mLocation);
 
-            try {
-                mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop,
-                        mLocation[0], mLocation[1],
-                        viewRoot != null ? viewRoot.getNextFrameNumber() : -1,
-                        mWinFrame);
-            } catch (RemoteException ex) {
-                Log.e(TAG, "Exception from relayout", ex);
+                try {
+                    Log.d(TAG, String.format("updateWindowPosition UI, " +
+                            "postion = [%d, %d, %d, %d]", mWindowSpaceLeft, mWindowSpaceTop,
+                            mLocation[0], mLocation[1]));
+                    mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop,
+                            mLocation[0], mLocation[1], -1, mWinFrame);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Exception from relayout", ex);
+                }
             }
         }
     }
 
+    private Rect mRTLastReportedPosition = new Rect();
+
+    /**
+     * Called by native on RenderThread to update the window position
+     * @hide
+     */
+    public final void updateWindowPositionRT(long frameNumber,
+            int left, int top, int right, int bottom) {
+        IWindowSession session = mSession;
+        MyWindow window = mWindow;
+        if (session == null || window == null) {
+            // Guess we got detached, that sucks
+            return;
+        }
+        if (mRTLastReportedPosition.left == left
+                && mRTLastReportedPosition.top == top
+                && mRTLastReportedPosition.right == right
+                && mRTLastReportedPosition.bottom == bottom) {
+            return;
+        }
+        try {
+            if (DEBUG) {
+                Log.d(TAG, String.format("updateWindowPosition RT, frameNr = %d, " +
+                        "postion = [%d, %d, %d, %d]", frameNumber, left, top,
+                        right, bottom));
+            }
+            // Just using mRTLastReportedPosition as a dummy rect here
+            session.repositionChild(window, left, top, right, bottom, frameNumber,
+                    mRTLastReportedPosition);
+            // Now overwrite mRTLastReportedPosition with our values
+            mRTLastReportedPosition.set(left, top, right, bottom);
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Exception from repositionChild", ex);
+        }
+    }
+
     private SurfaceHolder.Callback[] getSurfaceCallbacks() {
         SurfaceHolder.Callback callbacks[];
         synchronized (mCallbacks) {
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 78a63a6..8b06ecf 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -252,6 +252,17 @@
     }
 
     /**
+     * Sets the library directory to use as a search path for vulkan layers.
+     *
+     * @param libDir A directory that contains vulkan layers
+     *
+     * @hide
+     */
+    public static void setLibDir(String libDir) {
+        ThreadedRenderer.setupVulkanLayerPath(libDir);
+    }
+
+    /**
      * Creates a hardware renderer using OpenGL.
      *
      * @param translucent True if the surface is translucent, false otherwise
@@ -979,6 +990,7 @@
     }
 
     static native void setupShadersDiskCache(String cacheFile);
+    static native void setupVulkanLayerPath(String layerPath);
 
     private static native void nSetAtlas(long nativeProxy, GraphicBuffer buffer, long[] map);
     private static native void nSetProcessStatsBuffer(long nativeProxy, int fd);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index dd0887f..127157b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4506,9 +4506,15 @@
                     }
                     break;
                 case R.styleable.View_pointerShape:
-                    final int pointerShape = a.getInt(attr, PointerIcon.STYLE_NOT_SPECIFIED);
-                    if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) {
-                        setPointerIcon(PointerIcon.getSystemIcon(context, pointerShape));
+                    final int resourceId = a.getResourceId(attr, 0);
+                    if (resourceId != 0) {
+                        setPointerIcon(PointerIcon.loadCustomIcon(
+                                context.getResources(), resourceId));
+                    } else {
+                        final int pointerShape = a.getInt(attr, PointerIcon.STYLE_NOT_SPECIFIED);
+                        if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) {
+                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerShape));
+                        }
                     }
                     break;
             }
@@ -6770,6 +6776,13 @@
 
         info.setVisibleToUser(isVisibleToUser());
 
+        if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
+                & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
+            info.setImportantForAccessibility(isImportantForAccessibility());
+        } else {
+            info.setImportantForAccessibility(true);
+        }
+
         info.setPackageName(mContext.getPackageName());
         info.setClassName(getAccessibilityClassName());
         info.setContentDescription(getContentDescription());
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 98e3289..96853e0 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1811,7 +1811,9 @@
                 final boolean dragResizing = freeformResizing || dockedResizing;
                 if (mDragResizing != dragResizing) {
                     if (dragResizing) {
-                        startDragResizing(mPendingBackDropFrame);
+                        startDragResizing(mPendingBackDropFrame,
+                                mWinFrame.equals(mPendingBackDropFrame), mPendingVisibleInsets,
+                                mPendingStableInsets);
                         mResizeMode = freeformResizing
                                 ? RESIZE_MODE_FREEFORM
                                 : RESIZE_MODE_DOCKED_DIVIDER;
@@ -5845,9 +5847,11 @@
         // Tell all listeners that we are resizing the window so that the chrome can get
         // updated as fast as possible on a separate thread,
         if (mDragResizing) {
+            boolean fullscreen = frame.equals(backDropFrame);
             synchronized (mWindowCallbacks) {
                 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
-                    mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame);
+                    mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame, fullscreen,
+                            visibleInsets, stableInsets);
                 }
             }
         }
@@ -6815,20 +6819,6 @@
         }
     }
 
-    long getNextFrameNumber() {
-        long frameNumber = -1;
-        if (mSurfaceHolder != null) {
-            mSurfaceHolder.mSurfaceLock.lock();
-        }
-        if (mSurface.isValid()) {
-            frameNumber =  mSurface.getNextFrameNumber();
-        }
-        if (mSurfaceHolder != null) {
-            mSurfaceHolder.mSurfaceLock.unlock();
-        }
-        return frameNumber;
-    }
-
     class TakenSurfaceHolder extends BaseSurfaceHolder {
         @Override
         public boolean onAllowLockCanvas() {
@@ -7060,12 +7050,14 @@
     /**
      * Start a drag resizing which will inform all listeners that a window resize is taking place.
      */
-    private void startDragResizing(Rect initialBounds) {
+    private void startDragResizing(Rect initialBounds, boolean fullscreen, Rect systemInsets,
+            Rect stableInsets) {
         if (!mDragResizing) {
             mDragResizing = true;
             synchronized (mWindowCallbacks) {
                 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
-                    mWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds);
+                    mWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds, fullscreen,
+                            systemInsets, stableInsets);
                 }
             }
             mFullRedrawNeeded = true;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index ee70891..c68a740 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -34,7 +34,6 @@
 import android.media.session.MediaController;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemProperties;
@@ -273,7 +272,7 @@
     private Callback mCallback;
     private OnWindowDismissedCallback mOnWindowDismissedCallback;
     private WindowControllerCallback mWindowControllerCallback;
-    private RestrictedCaptionAreaListener mRestrictedCaptionAreaListener;
+    private OnRestrictedCaptionAreaChangedListener mOnRestrictedCaptionAreaChangedListener;
     private Rect mRestrictedCaptionAreaRect;
     private WindowManager mWindowManager;
     private IBinder mAppToken;
@@ -596,7 +595,7 @@
     /**
      * Callback for clients that want to be aware of where caption draws content.
      */
-    public interface RestrictedCaptionAreaListener {
+    public interface OnRestrictedCaptionAreaChangedListener {
         /**
          * Called when the area where caption draws content changes.
          *
@@ -856,8 +855,8 @@
      *
      * @param listener Callback that will be called when the area changes.
      */
-    public final void setRestrictedCaptionAreaListener(RestrictedCaptionAreaListener listener) {
-        mRestrictedCaptionAreaListener = listener;
+    public final void setRestrictedCaptionAreaListener(OnRestrictedCaptionAreaChangedListener listener) {
+        mOnRestrictedCaptionAreaChangedListener = listener;
         mRestrictedCaptionAreaRect = listener != null ? new Rect() : null;
     }
 
@@ -2126,17 +2125,20 @@
 
     /** @hide */
     public void notifyRestrictedCaptionAreaCallback(int left, int top, int right, int bottom) {
-        if (mRestrictedCaptionAreaListener != null) {
+        if (mOnRestrictedCaptionAreaChangedListener != null) {
             mRestrictedCaptionAreaRect.set(left, top, right, bottom);
-            mRestrictedCaptionAreaListener.onRestrictedCaptionAreaChanged(
+            mOnRestrictedCaptionAreaChangedListener.onRestrictedCaptionAreaChanged(
                     mRestrictedCaptionAreaRect);
         }
     }
 
     /**
      * Set what color should the caption controls be. By default the system will try to determine
-     * the color from the theme. You can overwrite this by using {@link #DECOR_CAPTION_SHADE_DARK}
-     * or {@link #DECOR_CAPTION_SHADE_DARK}.
+     * the color from the theme. You can overwrite this by using {@link #DECOR_CAPTION_SHADE_DARK},
+     * {@link #DECOR_CAPTION_SHADE_LIGHT}, or {@link #DECOR_CAPTION_SHADE_AUTO}.
+     * @see #DECOR_CAPTION_SHADE_DARK
+     * @see #DECOR_CAPTION_SHADE_LIGHT
+     * @see #DECOR_CAPTION_SHADE_AUTO
      */
     public abstract void setDecorCaptionShade(int decorCaptionShade);
 
@@ -2154,7 +2156,7 @@
      * Called when the activity changes from fullscreen mode to multi-window mode and visa-versa.
      * @hide
      */
-    public abstract void onMultiWindowModeChanged();
+    public abstract void onMultiWindowChanged();
 
     /**
      * Called when the activity just relaunched.
diff --git a/core/java/android/view/WindowCallbacks.java b/core/java/android/view/WindowCallbacks.java
index def0236..d2bfca7 100644
--- a/core/java/android/view/WindowCallbacks.java
+++ b/core/java/android/view/WindowCallbacks.java
@@ -28,20 +28,30 @@
 public interface WindowCallbacks {
     /**
      * Called by the system when the window got changed by the user, before the layouter got called.
-     * It can be used to perform a "quick and dirty" resize which should never take more then 4ms to
-     * complete.
+     * It also gets called when the insets changed, or when the window switched between a fullscreen
+     * layout or a non-fullscreen layout. It can be used to perform a "quick and dirty" resize which
+     * should never take more then 4ms to complete.
      *
      * <p>At the time the layouting has not happened yet.
      *
      * @param newBounds The new window frame bounds.
+     * @param fullscreen Whether the window is currently drawing in fullscreen.
+     * @param systemInsets The current visible system insets for the window.
+     * @param stableInsets The stable insets for the window.
      */
-    void onWindowSizeIsChanging(Rect newBounds);
+    void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
+            Rect stableInsets);
 
     /**
      * Called when a drag resize starts.
+     *
      * @param initialBounds The initial bounds where the window will be.
+     * @param fullscreen Whether the window is currently drawing in fullscreen.
+     * @param systemInsets The current visible system insets for the window.
+     * @param stableInsets The stable insets for the window.
      */
-    void onWindowDragResizeStart(Rect initialBounds);
+    void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen, Rect systemInsets,
+            Rect stableInsets);
 
     /**
      * Called when a drag resize ends.
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 89b1eb9..c22d60d 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -268,4 +268,9 @@
 
     /** Returns true if the stack with the input Id is currently visible. */
     public abstract boolean isStackVisible(int stackId);
+
+    /**
+     * @return True if and only if the docked divider is currently in resize mode.
+     */
+    public abstract boolean isDockedDividerResizing();
 }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index b673386..bdaf291 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -16,6 +16,7 @@
 
 package android.view.accessibility;
 
+import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.Nullable;
 import android.graphics.Rect;
@@ -568,6 +569,8 @@
 
     private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
 
+    private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000;
+
     /**
      * Bits that provide the id of a virtual descendant of a view.
      */
@@ -2156,6 +2159,33 @@
     }
 
     /**
+     * Returns whether the node originates from a view considered important for accessibility.
+     *
+     * @return {@code true} if the node originates from a view considered important for
+     *         accessibility, {@code false} otherwise
+     *
+     * @see View#isImportantForAccessibility()
+     */
+    public boolean isImportantForAccessibility() {
+        return getBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE);
+    }
+
+    /**
+     * Sets whether the node is considered important for accessibility.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param important {@code true} if the node is considered important for accessibility,
+     *                  {@code false} otherwise
+     */
+    public void setImportantForAccessibility(boolean important) {
+        setBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE, important);
+    }
+
+    /**
      * Gets the package this node comes from.
      *
      * @return The package name.
@@ -3311,9 +3341,21 @@
      * </li>
      * <li><strong>Overriden standard actions</strong> - These are actions that override
      * standard actions to customize them. For example, an app may add a label to the
-     * standard click action to announce that this action clears browsing history.
+     * standard {@link #ACTION_CLICK} action to announce that this action clears browsing history.
      * </ul>
      * </p>
+     * <p>
+     * Actions are typically added to an {@link AccessibilityNodeInfo} by using
+     * {@link AccessibilityNodeInfo#addAction(AccessibilityAction)} within
+     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} and are performed
+     * within {@link View#performAccessibilityAction(int, Bundle)}.
+     * </p>
+     * <p class="note">
+     * <strong>Note:</strong> Views which support these actions should invoke
+     * {@link View#setImportantForAccessibility(int)} with
+     * {@link View#IMPORTANT_FOR_ACCESSIBILITY_YES} to ensure an {@link AccessibilityService}
+     * can discover the set of supported actions.
+     * </p>
      */
     public static final class AccessibilityAction {
 
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 4ca8971..9a68593 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -955,7 +955,7 @@
                 if (!canUserSetProgress()) {
                     return false;
                 }
-                int increment = Math.max(1, Math.round((float) getMax() / 5));
+                int increment = Math.max(1, Math.round((float) getMax() / 20));
                 if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
                     increment = -increment;
                 }
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index ee73092..1321221 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -2404,7 +2404,7 @@
         }
 
         final LayoutParams lp = (LayoutParams) view.getLayoutParams();
-        final boolean isHeading = lp != null && lp.viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
+        final boolean isHeading = lp != null && lp.viewType == ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
         final boolean isSelected = isItemChecked(position);
         final CollectionItemInfo itemInfo = CollectionItemInfo.obtain(
                 row, 1, column, 1, isHeading, isSelected);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 6e90baf..f601f7d 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -392,6 +392,26 @@
         return mDrawable;
     }
 
+    private class ImageDrawableCallback implements Runnable {
+
+        private final Drawable drawable;
+        private final Uri uri;
+        private final int resource;
+
+        ImageDrawableCallback(Drawable drawable, Uri uri, int resource) {
+            this.drawable = drawable;
+            this.uri = uri;
+            this.resource = resource;
+        }
+
+        @Override
+        public void run() {
+            setImageDrawable(drawable);
+            mUri = uri;
+            mResource = resource;
+        }
+    }
+
     /**
      * Sets a drawable as the content of this ImageView.
      *
@@ -405,7 +425,7 @@
      *
      * @attr ref android.R.styleable#ImageView_src
      */
-    @android.view.RemotableViewMethod
+    @android.view.RemotableViewMethod(asyncImpl="setImageResourceAsync")
     public void setImageResource(@DrawableRes int resId) {
         // The resource configuration may have changed, so we should always
         // try to load the resource even if the resId hasn't changed.
@@ -424,6 +444,11 @@
         invalidate();
     }
 
+    /** @hide **/
+    public Runnable setImageResourceAsync(@DrawableRes int resId) {
+        return new ImageDrawableCallback(getContext().getDrawable(resId), null, resId);
+    }
+
     /**
      * Sets the content of this ImageView to the specified Uri.
      *
@@ -435,7 +460,7 @@
      *
      * @param uri the Uri of an image, or {@code null} to clear the content
      */
-    @android.view.RemotableViewMethod
+    @android.view.RemotableViewMethod(asyncImpl="setImageURIAsync")
     public void setImageURI(@Nullable Uri uri) {
         if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) {
             updateDrawable(null);
@@ -454,6 +479,19 @@
         }
     }
 
+    /** @hide **/
+    public Runnable setImageURIAsync(@Nullable Uri uri) {
+        if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) {
+            Drawable d = uri == null ? null : getDrawableFromUri(uri);
+            if (d == null) {
+                // Do not set the URI if the drawable couldn't be loaded.
+                uri = null;
+            }
+            return new ImageDrawableCallback(d, uri, 0);
+        }
+        return null;
+    }
+
     /**
      * Sets a drawable as the content of this ImageView.
      *
@@ -490,11 +528,16 @@
      * @param icon an Icon holding the desired image, or {@code null} to clear
      *             the content
      */
-    @android.view.RemotableViewMethod
+    @android.view.RemotableViewMethod(asyncImpl="setImageIconAsync")
     public void setImageIcon(@Nullable Icon icon) {
         setImageDrawable(icon == null ? null : icon.loadDrawable(mContext));
     }
 
+    /** @hide **/
+    public Runnable setImageIconAsync(@Nullable Icon icon) {
+        return new ImageDrawableCallback(icon == null ? null : icon.loadDrawable(mContext), null, 0);
+    }
+
     /**
      * Applies a tint to the image drawable. Does not modify the current tint
      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
@@ -786,8 +829,7 @@
             return;
         }
 
-        final Resources res = getResources();
-        if (res == null) {
+        if (getResources() == null) {
             return;
         }
 
@@ -802,37 +844,7 @@
                 mUri = null;
             }
         } else if (mUri != null) {
-            final String scheme = mUri.getScheme();
-            if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
-                try {
-                    // Load drawable through Resources, to get the source density information
-                    ContentResolver.OpenResourceIdResult r =
-                            mContext.getContentResolver().getResourceId(mUri);
-                    d = r.r.getDrawable(r.id, mContext.getTheme());
-                } catch (Exception e) {
-                    Log.w(LOG_TAG, "Unable to open content: " + mUri, e);
-                }
-            } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
-                    || ContentResolver.SCHEME_FILE.equals(scheme)) {
-                InputStream stream = null;
-                try {
-                    stream = mContext.getContentResolver().openInputStream(mUri);
-                    d = Drawable.createFromResourceStream(
-                            mUseCorrectStreamDensity ? res : null, null, stream, null);
-                } catch (Exception e) {
-                    Log.w(LOG_TAG, "Unable to open content: " + mUri, e);
-                } finally {
-                    if (stream != null) {
-                        try {
-                            stream.close();
-                        } catch (IOException e) {
-                            Log.w(LOG_TAG, "Unable to close content: " + mUri, e);
-                        }
-                    }
-                }
-            } else {
-                d = Drawable.createFromPath(mUri.toString());
-            }
+            d = getDrawableFromUri(mUri);
 
             if (d == null) {
                 Log.w(LOG_TAG, "resolveUri failed on bad bitmap uri: " + mUri);
@@ -846,6 +858,41 @@
         updateDrawable(d);
     }
 
+    private Drawable getDrawableFromUri(Uri uri) {
+        final String scheme = uri.getScheme();
+        if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
+            try {
+                // Load drawable through Resources, to get the source density information
+                ContentResolver.OpenResourceIdResult r =
+                        mContext.getContentResolver().getResourceId(uri);
+                return r.r.getDrawable(r.id, mContext.getTheme());
+            } catch (Exception e) {
+                Log.w(LOG_TAG, "Unable to open content: " + uri, e);
+            }
+        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
+                || ContentResolver.SCHEME_FILE.equals(scheme)) {
+            InputStream stream = null;
+            try {
+                stream = mContext.getContentResolver().openInputStream(uri);
+                return Drawable.createFromResourceStream(
+                        mUseCorrectStreamDensity ? getResources() : null, null, stream, null);
+            } catch (Exception e) {
+                Log.w(LOG_TAG, "Unable to open content: " + uri, e);
+            } finally {
+                if (stream != null) {
+                    try {
+                        stream.close();
+                    } catch (IOException e) {
+                        Log.w(LOG_TAG, "Unable to close content: " + uri, e);
+                    }
+                }
+            }
+        } else {
+            return Drawable.createFromPath(uri.toString());
+        }
+        return null;
+    }
+
     @Override
     public int[] onCreateDrawableState(int extraSpace) {
         if (mState == null) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index a11897d..5b4a368 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3930,7 +3930,7 @@
         super.onInitializeAccessibilityNodeInfoForItem(view, position, info);
 
         final LayoutParams lp = (LayoutParams) view.getLayoutParams();
-        final boolean isHeading = lp != null && lp.viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
+        final boolean isHeading = lp != null && lp.viewType == ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
         final boolean isSelected = isItemChecked(position);
         final CollectionItemInfo itemInfo = CollectionItemInfo.obtain(
                 position, 1, 0, 1, isHeading, isSelected);
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 584df08..8fa71a2 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -43,6 +43,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.view.ViewParent;
@@ -164,7 +165,20 @@
         com.android.internal.R.attr.state_above_anchor
     };
 
+    private final OnAttachStateChangeListener mOnAnchorRootDetachedListener =
+            new OnAttachStateChangeListener() {
+                @Override
+                public void onViewAttachedToWindow(View v) {}
+
+                @Override
+                public void onViewDetachedFromWindow(View v) {
+                    mIsAnchorRootAttached = false;
+                }
+            };
+
     private WeakReference<View> mAnchor;
+    private WeakReference<View> mAnchorRoot;
+    private boolean mIsAnchorRootAttached;
 
     private final OnScrollChangedListener mOnScrollChangedListener = new OnScrollChangedListener() {
         @Override
@@ -1037,7 +1051,7 @@
 
         TransitionManager.endTransitions(mDecorView);
 
-        unregisterForScrollChanged();
+        unregisterForViewTreeChanges();
 
         mIsShowing = true;
         mIsDropdown = false;
@@ -1120,7 +1134,7 @@
 
         TransitionManager.endTransitions(mDecorView);
 
-        registerForScrollChanged(anchor, xoff, yoff, gravity);
+        registerForViewTreeChanges(anchor, xoff, yoff, gravity);
 
         mIsShowing = true;
         mIsDropdown = true;
@@ -1633,14 +1647,23 @@
         mIsShowing = false;
         mIsTransitioningToDismiss = true;
 
+        // This method may be called as part of window detachment, in which
+        // case the anchor view (and its root) will still return true from
+        // isAttachedToWindow() during execution of this method; however, we
+        // can expect the OnAttachStateChangeListener to have been called prior
+        // to executing this method, so we can rely on that instead.
         final Transition exitTransition = mExitTransition;
-        if (exitTransition != null && decorView.isLaidOut()) {
+        if (!mIsAnchorRootAttached && exitTransition != null && decorView.isLaidOut()) {
             // The decor view is non-interactive during exit transitions.
             final LayoutParams p = (LayoutParams) decorView.getLayoutParams();
             p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
             p.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
             mWindowManager.updateViewLayout(decorView, p);
 
+            // Once we start dismissing the decor view, all state (including
+            // the anchor root) needs to be moved to the decor view since we
+            // may open another popup while it's busy exiting.
+            final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
             final Rect epicenter = getTransitionEpicenter();
             exitTransition.setEpicenterCallback(new EpicenterCallback() {
                 @Override
@@ -1648,18 +1671,19 @@
                     return epicenter;
                 }
             });
-            decorView.startExitTransition(exitTransition, new TransitionListenerAdapter() {
-                @Override
-                public void onTransitionEnd(Transition transition) {
-                    dismissImmediate(decorView, contentHolder, contentView);
-                }
-            });
+            decorView.startExitTransition(exitTransition, anchorRoot,
+                    new TransitionListenerAdapter() {
+                        @Override
+                        public void onTransitionEnd(Transition transition) {
+                            dismissImmediate(decorView, contentHolder, contentView);
+                        }
+                    });
         } else {
             dismissImmediate(decorView, contentHolder, contentView);
         }
 
         // Clears the anchor view.
-        unregisterForScrollChanged();
+        unregisterForViewTreeChanges();
 
         if (mOnDismissListener != null) {
             mOnDismissListener.onDismiss();
@@ -1925,7 +1949,7 @@
         final WeakReference<View> oldAnchor = mAnchor;
         final boolean needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);
         if (oldAnchor == null || oldAnchor.get() != anchor || (needsUpdate && !mIsDropdown)) {
-            registerForScrollChanged(anchor, xoff, yoff, mAnchoredGravity);
+            registerForViewTreeChanges(anchor, xoff, yoff, mAnchoredGravity);
         } else if (needsUpdate) {
             // No need to register again if this is a DropDown, showAsDropDown already did.
             mAnchorXoff = xoff;
@@ -1969,27 +1993,38 @@
         public void onDismiss();
     }
 
-    private void unregisterForScrollChanged() {
-        final WeakReference<View> anchorRef = mAnchor;
-        final View anchor = anchorRef == null ? null : anchorRef.get();
+    private void unregisterForViewTreeChanges() {
+        final View anchor = mAnchor != null ? mAnchor.get() : null;
         if (anchor != null) {
             final ViewTreeObserver vto = anchor.getViewTreeObserver();
             vto.removeOnScrollChangedListener(mOnScrollChangedListener);
         }
 
+        final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
+        if (anchorRoot != null) {
+            anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+        }
+
         mAnchor = null;
+        mAnchorRoot = null;
+        mIsAnchorRootAttached = false;
     }
 
-    private void registerForScrollChanged(View anchor, int xoff, int yoff, int gravity) {
-        unregisterForScrollChanged();
-
-        mAnchor = new WeakReference<>(anchor);
+    private void registerForViewTreeChanges(View anchor, int xoff, int yoff, int gravity) {
+        unregisterForViewTreeChanges();
 
         final ViewTreeObserver vto = anchor.getViewTreeObserver();
         if (vto != null) {
             vto.addOnScrollChangedListener(mOnScrollChangedListener);
         }
 
+        final View anchorRoot = anchor.getRootView();
+        anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+
+        mAnchor = new WeakReference<>(anchor);
+        mAnchorRoot = new WeakReference<>(anchorRoot);
+        mIsAnchorRootAttached = anchorRoot.isAttachedToWindow();
+
         mAnchorXoff = xoff;
         mAnchorYoff = yoff;
         mAnchoredGravity = gravity;
@@ -2109,16 +2144,23 @@
          * its {@code onTransitionEnd} method called even if the transition
          * never starts; however, it may be called with a {@code null} argument.
          */
-        public void startExitTransition(Transition transition, final TransitionListener listener) {
+        public void startExitTransition(Transition transition, final View anchorRoot,
+                final TransitionListener listener) {
             if (transition == null) {
                 return;
             }
 
+            // The anchor view's window may go away while we're executing our
+            // transition, in which case we need to end the transition
+            // immediately and execute the listener to remove the popup.
+            anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+
             // The exit listener MUST be called for cleanup, even if the
             // transition never starts or ends. Stash it for later.
             mPendingExitListener = new TransitionListenerAdapter() {
                 @Override
                 public void onTransitionEnd(Transition transition) {
+                    anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
                     listener.onTransitionEnd(transition);
 
                     // The listener was called. Our job here is done.
@@ -2153,6 +2195,19 @@
                 mPendingExitListener.onTransitionEnd(null);
             }
         }
+
+        private final OnAttachStateChangeListener mOnAnchorRootDetachedListener =
+                new OnAttachStateChangeListener() {
+                    @Override
+                    public void onViewAttachedToWindow(View v) {}
+
+                    @Override
+                    public void onViewDetachedFromWindow(View v) {
+                        v.removeOnAttachStateChangeListener(this);
+
+                        TransitionManager.endTransitions(PopupDecorView.this);
+                    }
+                };
     }
 
     private class PopupBackgroundView extends FrameLayout {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0dd803a2..dee25d3 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -39,8 +39,10 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.StrictMode;
@@ -66,6 +68,7 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.concurrent.Executor;
 
 /**
  * A class that describes a view hierarchy that can be displayed in
@@ -146,6 +149,8 @@
     private static final Object[] sMethodsLock = new Object[0];
     private static final ArrayMap<Class<? extends View>, ArrayMap<MutablePair<String, Class<?>>, Method>> sMethods =
             new ArrayMap<Class<? extends View>, ArrayMap<MutablePair<String, Class<?>>, Method>>();
+    private static final ArrayMap<Method, Method> sAsyncMethods = new ArrayMap<>();
+
     private static final ThreadLocal<Object[]> sInvokeArgsTls = new ThreadLocal<Object[]>() {
         @Override
         protected Object[] initialValue() {
@@ -293,10 +298,40 @@
             return (getActionName() + viewId);
         }
 
+        /**
+         * This is called on the background thread. It should perform any non-ui computations
+         * and return the final action which will run on the UI thread.
+         * Override this if some of the tasks can be performed async.
+         */
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
+            return this;
+        }
+
         int viewId;
     }
 
     /**
+     * Action class used during async inflation of RemoteViews. Subclasses are not parcelable.
+     */
+    private static abstract class RuntimeAction extends Action {
+        @Override
+        public final String getActionName() {
+            return "RuntimeAction";
+        }
+
+        @Override
+        public final void writeToParcel(Parcel dest, int flags) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    // Constant used during async execution. It is not parcelable.
+    private static final Action ACTION_NOOP = new RuntimeAction() {
+        @Override
+        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) { }
+    };
+
+    /**
      * Merges the passed RemoteViews actions with this RemoteViews actions according to
      * action-specific merge rules.
      *
@@ -810,6 +845,36 @@
         return method;
     }
 
+    /**
+     * @return the async implementation of the provided method.
+     */
+    private Method getAsyncMethod(Method method) {
+        synchronized (sAsyncMethods) {
+            int valueIndex = sAsyncMethods.indexOfKey(method);
+            if (valueIndex >= 0) {
+                return sAsyncMethods.valueAt(valueIndex);
+            }
+
+            RemotableViewMethod annotation = method.getAnnotation(RemotableViewMethod.class);
+            Method asyncMethod = null;
+            if (!annotation.asyncImpl().isEmpty()) {
+                try {
+                    asyncMethod = method.getDeclaringClass()
+                            .getMethod(annotation.asyncImpl(), method.getParameterTypes());
+                    if (!asyncMethod.getReturnType().equals(Runnable.class)) {
+                        throw new ActionException("Async implementation for " + method.getName() +
+                            " does not return a Runnable");
+                    }
+                } catch (NoSuchMethodException ex) {
+                    throw new ActionException("Async implementation declared but not defined for " +
+                            method.getName());
+                }
+            }
+            sAsyncMethods.put(method, asyncMethod);
+            return asyncMethod;
+        }
+    }
+
     private static String getParameters(Class<?> paramType) {
         if (paramType == null) return "()";
         return "(" + paramType + ")";
@@ -1324,6 +1389,37 @@
             }
         }
 
+        @Override
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
+            final View view = root.findViewById(viewId);
+            if (view == null) return ACTION_NOOP;
+
+            Class<?> param = getParameterType();
+            if (param == null) {
+                throw new ActionException("bad type: " + this.type);
+            }
+
+            try {
+                Method method = getMethod(view, this.methodName, param);
+                Method asyncMethod = getAsyncMethod(method);
+
+                if (asyncMethod != null) {
+                    Runnable endAction = (Runnable) asyncMethod.invoke(view, wrapArg(this.value));
+                    if (endAction == null) {
+                        return ACTION_NOOP;
+                    } else {
+                        return new RunnableAction(endAction);
+                    }
+                }
+            } catch (ActionException e) {
+                throw e;
+            } catch (Exception ex) {
+                throw new ActionException(ex);
+            }
+
+            return this;
+        }
+
         public int mergeBehavior() {
             // smoothScrollBy is cumulative, everything else overwites.
             if (methodName.equals("smoothScrollBy")) {
@@ -1340,6 +1436,22 @@
         }
     }
 
+    /**
+     * This is only used for async execution of actions and it not parcelable.
+     */
+    private static final class RunnableAction extends RuntimeAction {
+        private final Runnable mRunnable;
+
+        RunnableAction(Runnable r) {
+            mRunnable = r;
+        }
+
+        @Override
+        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+            mRunnable.run();
+        }
+    }
+
     private void configureRemoteViewsAsChild(RemoteViews rv) {
         mBitmapCache.assimilate(rv.mBitmapCache);
         rv.setBitmapCache(mBitmapCache);
@@ -1401,6 +1513,43 @@
         }
 
         @Override
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
+            // In the async implementation, update the view tree so that subsequent calls to
+            // findViewById return the currect view.
+            root.createTree();
+            ViewTree target = root.findViewTreeById(viewId);
+            if ((target == null) || !(target.mRoot instanceof ViewGroup)) {
+                return ACTION_NOOP;
+            }
+            if (nestedViews == null) {
+                // Clear all children when nested views omitted
+                target.mChildren = null;
+                return this;
+            } else {
+                // Inflate nested views and perform all the async tasks for the child remoteView.
+                final Context context = root.mRoot.getContext();
+                final AsyncApplyTask task = nestedViews.getAsyncApplyTask(
+                        context, (ViewGroup) target.mRoot, null, handler);
+                final ViewTree tree = task.doInBackground();
+
+                // Update the global view tree, so that next call to findViewTreeById
+                // goes through the subtree as well.
+                target.addChild(tree);
+
+                return new RuntimeAction() {
+
+                    @Override
+                    public void apply(View root, ViewGroup rootParent, OnClickHandler handler) throws ActionException {
+                        // This view will exist as we have already made sure
+                        final ViewGroup target = (ViewGroup) root.findViewById(viewId);
+                        task.onPostExecute(tree);
+                        target.addView(task.mResult);
+                    }
+                };
+            }
+        }
+
+        @Override
         public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
             if (nestedViews != null) {
                 counter.increment(nestedViews.estimateMemoryUsage());
@@ -1520,7 +1669,13 @@
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final TextView target = (TextView) root.findViewById(viewId);
             if (target == null) return;
-            if (useIcons) {
+            if (drawablesLoaded) {
+                if (isRelative) {
+                    target.setCompoundDrawablesRelativeWithIntrinsicBounds(id1, id2, id3, id4);
+                } else {
+                    target.setCompoundDrawablesWithIntrinsicBounds(id1, id2, id3, id4);
+                }
+            } else if (useIcons) {
                 final Context ctx = target.getContext();
                 final Drawable id1 = i1 == null ? null : i1.loadDrawable(ctx);
                 final Drawable id2 = i2 == null ? null : i2.loadDrawable(ctx);
@@ -1540,6 +1695,33 @@
             }
         }
 
+        @Override
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
+            final TextView target = (TextView) root.findViewById(viewId);
+            if (target == null) return ACTION_NOOP;
+
+            TextViewDrawableAction copy = useIcons ?
+                    new TextViewDrawableAction(viewId, isRelative, i1, i2, i3, i4) :
+                    new TextViewDrawableAction(viewId, isRelative, d1, d2, d3, d4);
+
+            // Load the drawables on the background thread.
+            copy.drawablesLoaded = true;
+            final Context ctx = target.getContext();
+
+            if (useIcons) {
+                copy.id1 = i1 == null ? null : i1.loadDrawable(ctx);
+                copy.id2 = i2 == null ? null : i2.loadDrawable(ctx);
+                copy.id3 = i3 == null ? null : i3.loadDrawable(ctx);
+                copy.id4 = i4 == null ? null : i4.loadDrawable(ctx);
+            } else {
+                copy.id1 = d1 == 0 ? null : ctx.getDrawable(d1);
+                copy.id2 = d2 == 0 ? null : ctx.getDrawable(d2);
+                copy.id3 = d3 == 0 ? null : ctx.getDrawable(d3);
+                copy.id4 = d4 == 0 ? null : ctx.getDrawable(d4);
+            }
+            return copy;
+        }
+
         public String getActionName() {
             return "TextViewDrawableAction";
         }
@@ -1549,6 +1731,9 @@
         int d1, d2, d3, d4;
         Icon i1, i2, i3, i4;
 
+        boolean drawablesLoaded = false;
+        Drawable id1, id2, id3, id4;
+
         public final static int TAG = 11;
     }
 
@@ -2852,7 +3037,15 @@
     public View apply(Context context, ViewGroup parent, OnClickHandler handler) {
         RemoteViews rvToApply = getRemoteViewsToApply(context);
 
-        View result;
+        View result = inflateView(context, rvToApply, parent);
+        loadTransitionOverride(context, handler);
+
+        rvToApply.performApply(result, parent, handler);
+
+        return result;
+    }
+
+    private View inflateView(Context context, RemoteViews rv, ViewGroup parent) {
         // RemoteViews may be built by an application installed in another
         // user. So build a context that loads resources from that user but
         // still returns the current users userId so settings like data / time formats
@@ -2880,13 +3073,7 @@
         // we don't add a filter to the static version returned by getSystemService.
         inflater = inflater.cloneInContext(inflationContext);
         inflater.setFilter(this);
-        result = inflater.inflate(rvToApply.getLayoutId(), parent, false);
-
-        loadTransitionOverride(context, handler);
-
-        rvToApply.performApply(result, parent, handler);
-
-        return result;
+        return inflater.inflate(rv.getLayoutId(), parent, false);
     }
 
     private static void loadTransitionOverride(Context context,
@@ -2908,6 +3095,143 @@
     }
 
     /**
+     * Implement this interface to receive a callback when
+     * {@link #applyAsync} or {@link #reapplyAsync} is finished.
+     * @hide
+     */
+    public interface OnViewAppliedListener {
+        void onViewApplied(View v);
+
+        void onError(Exception e);
+    }
+
+    /**
+     * Applies the views asynchronously, moving as much of the task on the background
+     * thread as possible.
+     *
+     * @see {@link #apply(Context, ViewGroup)}
+     * @param context Default context to use
+     * @param parent Parent that the resulting view hierarchy will be attached to. This method
+     * does <strong>not</strong> attach the hierarchy. The caller should do so when appropriate.
+     * @param listener the callback to run when all actions have been applied. May be null.
+     * @param executor The executor to use. If null {@link AsyncTask#THREAD_POOL_EXECUTOR} is used.
+     * @return CancellationSignal
+     * @hide
+     */
+    public CancellationSignal applyAsync(
+            Context context, ViewGroup parent, Executor executor, OnViewAppliedListener listener) {
+        return applyAsync(context, parent, executor, listener, null);
+    }
+
+    private CancellationSignal startTaskOnExecutor(AsyncApplyTask task, Executor executor) {
+        CancellationSignal cancelSignal = new CancellationSignal();
+        cancelSignal.setOnCancelListener(task);
+
+        task.executeOnExecutor(executor == null ? AsyncTask.THREAD_POOL_EXECUTOR : executor);
+        return cancelSignal;
+    }
+
+    /** @hide */
+    public CancellationSignal applyAsync(Context context, ViewGroup parent,
+            Executor executor, OnViewAppliedListener listener, OnClickHandler handler) {
+        return startTaskOnExecutor(getAsyncApplyTask(context, parent, listener, handler), executor);
+    }
+
+    private AsyncApplyTask getAsyncApplyTask(Context context, ViewGroup parent,
+            OnViewAppliedListener listener, OnClickHandler handler) {
+        return new AsyncApplyTask(getRemoteViewsToApply(context), parent, context, listener,
+                handler, null);
+    }
+
+    private class AsyncApplyTask extends AsyncTask<Void, Void, ViewTree>
+            implements CancellationSignal.OnCancelListener {
+        final RemoteViews mRV;
+        final ViewGroup mParent;
+        final Context mContext;
+        final OnViewAppliedListener mListener;
+        final OnClickHandler mHandler;
+
+        private View mResult;
+        private ViewTree mTree;
+        private Action[] mActions;
+        private Exception mError;
+
+        private AsyncApplyTask(
+                RemoteViews rv, ViewGroup parent, Context context, OnViewAppliedListener listener,
+                OnClickHandler handler, View result) {
+            mRV = rv;
+            mParent = parent;
+            mContext = context;
+            mListener = listener;
+            mHandler = handler;
+
+            mResult = result;
+            loadTransitionOverride(context, handler);
+        }
+
+        @Override
+        protected ViewTree doInBackground(Void... params) {
+            try {
+                if (mResult == null) {
+                    mResult = inflateView(mContext, mRV, mParent);
+                }
+
+                mTree = new ViewTree(mResult);
+                if (mRV.mActions != null) {
+                    int count = mRV.mActions.size();
+                    mActions = new Action[count];
+                    for (int i = 0; i < count && !isCancelled(); i++) {
+                        // TODO: check if isCanclled in nested views.
+                        mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler);
+                    }
+                } else {
+                    mActions = null;
+                }
+                return mTree;
+            } catch (Exception e) {
+                mError = e;
+                return null;
+            }
+        }
+
+        @Override
+        protected void onPostExecute(ViewTree viewTree) {
+            if (mError == null) {
+                try {
+                    if (mActions != null) {
+                        OnClickHandler handler = mHandler == null
+                                ? DEFAULT_ON_CLICK_HANDLER : mHandler;
+                        for (Action a : mActions) {
+                            a.apply(viewTree.mRoot, mParent, handler);
+                        }
+                    }
+                } catch (Exception e) {
+                    mError = e;
+                }
+            }
+
+            if (mListener != null) {
+                if (mError != null) {
+                    mListener.onError(mError);
+                } else {
+                    mListener.onViewApplied(viewTree.mRoot);
+                }
+            } else if (mError != null) {
+                if (mError instanceof ActionException) {
+                    throw (ActionException) mError;
+                } else {
+                    throw new ActionException(mError);
+                }
+            }
+        }
+
+        @Override
+        public void onCancel() {
+            cancel(true);
+        }
+    }
+
+    /**
      * Applies all of the actions to the provided view.
      *
      * <p><strong>Caller beware: this may throw</strong>
@@ -2936,6 +3260,43 @@
         rvToApply.performApply(v, (ViewGroup) v.getParent(), handler);
     }
 
+    /**
+     * Applies all the actions to the provided view, moving as much of the task on the background
+     * thread as possible.
+     *
+     * @see {@link #reapply(Context, View)}
+     * @param context Default context to use
+     * @param v The view to apply the actions to.  This should be the result of
+     * the {@link #apply(Context,ViewGroup)} call.
+     * @param listener the callback to run when all actions have been applied. May be null.
+     * @param executor The executor to use. If null {@link AsyncTask#THREAD_POOL_EXECUTOR} is used
+     * @return CancellationSignal
+     * @hide
+     */
+    public CancellationSignal reapplyAsync(
+            Context context, View v, Executor executor, OnViewAppliedListener listener) {
+        return reapplyAsync(context, v, executor, listener, null);
+    }
+
+    /** @hide */
+    public CancellationSignal reapplyAsync(Context context, View v, Executor executor,
+            OnViewAppliedListener listener, OnClickHandler handler) {
+        RemoteViews rvToApply = getRemoteViewsToApply(context);
+
+        // In the case that a view has this RemoteViews applied in one orientation, is persisted
+        // across orientation change, and has the RemoteViews re-applied in the new orientation,
+        // we throw an exception, since the layouts may be completely unrelated.
+        if (hasLandscapeAndPortraitLayouts()) {
+            if (v.getId() != rvToApply.getLayoutId()) {
+                throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
+                        " that does not share the same root layout id.");
+            }
+        }
+
+        return startTaskOnExecutor(new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
+                context, listener, handler, v), executor);
+    }
+
     private void performApply(View v, ViewGroup parent, OnClickHandler handler) {
         if (mActions != null) {
             handler = handler == null ? DEFAULT_ON_CLICK_HANDLER : handler;
@@ -3058,4 +3419,90 @@
             return new RemoteViews[size];
         }
     };
+
+    /**
+     * A representation of the view hierarchy. Only views which have a valid ID are added
+     * and can be searched.
+     */
+    private static class ViewTree {
+        private final View mRoot;
+
+        private ArrayList<ViewTree> mChildren;
+
+        private ViewTree(View root) {
+            mRoot = root;
+        }
+
+        public void createTree() {
+            if (mChildren != null) {
+                return;
+            }
+
+            mChildren = new ArrayList<>();
+            if (mRoot instanceof ViewGroup && mRoot.isRootNamespace()) {
+                ViewGroup vg = (ViewGroup) mRoot;
+                int count = vg.getChildCount();
+                for (int i = 0; i < count; i++) {
+                    addViewChild(vg.getChildAt(i));
+                }
+            }
+        }
+
+        public ViewTree findViewTreeById(int id) {
+            if (mRoot.getId() == id) {
+                return this;
+            }
+            if (mChildren == null) {
+                return null;
+            }
+            for (ViewTree tree : mChildren) {
+                ViewTree result = tree.findViewTreeById(id);
+                if (result != null) {
+                    return result;
+                }
+            }
+            return null;
+        }
+
+        public View findViewById(int id) {
+            if (mChildren == null) {
+                return mRoot.findViewById(id);
+            }
+            ViewTree tree = findViewTreeById(id);
+            return tree == null ? null : tree.mRoot;
+        }
+
+        public void addChild(ViewTree child) {
+            if (mChildren == null) {
+                mChildren = new ArrayList<>();
+            }
+            child.createTree();
+            mChildren.add(child);
+        }
+
+        private void addViewChild(View v) {
+            final ViewTree target;
+
+            // If the view has a valid id, i.e., if can be found using findViewById, add it to the
+            // tree, otherwise skip this view and add its children instead.
+            if (v.getId() != 0) {
+                ViewTree tree = new ViewTree(v);
+                mChildren.add(tree);
+                target = tree;
+            } else {
+                target = this;
+            }
+
+            if (v instanceof ViewGroup && v.isRootNamespace()) {
+                if (target.mChildren == null) {
+                    target.mChildren = new ArrayList<>();
+                    ViewGroup vg = (ViewGroup) v;
+                    int count = vg.getChildCount();
+                    for (int i = 0; i < count; i++) {
+                        target.addViewChild(vg.getChildAt(i));
+                    }
+                }
+            }
+        }
+    }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index c626af6..712a04b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -115,7 +115,6 @@
 import android.view.DragEvent;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
-import android.view.InputDevice;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -395,6 +394,14 @@
         }
 
         /**
+         * @return {@code true} if this object contains metadata that needs to
+         *         be retained, {@code false} otherwise
+         */
+        public boolean hasMetadata() {
+            return mDrawablePadding != 0 || mHasTintMode || mHasTint;
+        }
+
+        /**
          * Updates the list of displayed drawables to account for the current
          * layout direction.
          *
@@ -2174,7 +2181,7 @@
         if (!drawables) {
             // Clearing drawables...  can we free the data structure?
             if (dr != null) {
-                if (dr.mDrawablePadding == 0) {
+                if (!dr.hasMetadata()) {
                     mDrawables = null;
                 } else {
                     // We need to retain the last set padding, so just clear
@@ -2377,7 +2384,7 @@
         if (!drawables) {
             // Clearing drawables...  can we free the data structure?
             if (dr != null) {
-                if (dr.mDrawablePadding == 0) {
+                if (!dr.hasMetadata()) {
                     mDrawables = null;
                 } else {
                     // We need to retain the last set padding, so just clear
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 27c3b72..aac7bc3 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -43,7 +43,6 @@
 import android.view.Window;
 import android.view.WindowInsets;
 import android.view.WindowManager;
-import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ArrayAdapter;
@@ -115,6 +114,8 @@
     private int mSingleChoiceItemLayout;
     private int mListItemLayout;
 
+    private boolean mShowTitle;
+
     private int mButtonPanelLayoutHint = AlertDialog.LAYOUT_HINT_NONE;
 
     private Handler mHandler;
@@ -150,7 +151,7 @@
         private WeakReference<DialogInterface> mDialog;
 
         public ButtonHandler(DialogInterface dialog) {
-            mDialog = new WeakReference<DialogInterface>(dialog);
+            mDialog = new WeakReference<>(dialog);
         }
 
         @Override
@@ -200,6 +201,7 @@
         mListItemLayout = a.getResourceId(
                 R.styleable.AlertDialog_listItemLayout,
                 R.layout.select_dialog_item);
+        mShowTitle = a.getBoolean(R.styleable.AlertDialog_showTitle, true);
 
         a.recycle();
     }
@@ -232,7 +234,6 @@
         int contentView = selectContentView();
         mWindow.setContentView(contentView);
         setupView();
-        setupDecor();
     }
 
     private int selectContentView() {
@@ -429,27 +430,6 @@
         return mScrollView != null && mScrollView.executeKeyEvent(event);
     }
 
-    private void setupDecor() {
-        final View decor = mWindow.getDecorView();
-        final View parent = mWindow.findViewById(R.id.parentPanel);
-        if (parent != null && decor != null) {
-            decor.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
-                @Override
-                public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
-                    if (insets.isRound()) {
-                        // TODO: Get the padding as a function of the window size.
-                        int roundOffset = mContext.getResources().getDimensionPixelOffset(
-                                R.dimen.alert_dialog_round_padding);
-                        parent.setPadding(roundOffset, roundOffset, roundOffset, roundOffset);
-                    }
-                    return insets.consumeSystemWindowInsets();
-                }
-            });
-            decor.setFitsSystemWindows(true);
-            decor.requestApplyInsets();
-        }
-    }
-
     /**
      * Resolves whether a custom or default panel should be used. Removes the
      * default panel if a custom panel should be used. If the resolved panel is
@@ -600,21 +580,21 @@
     }
 
     private void setupTitle(ViewGroup topPanel) {
-        if (mCustomTitleView != null) {
+        if (mCustomTitleView != null && mShowTitle) {
             // Add the custom title view directly to the topPanel layout
-            LayoutParams lp = new LayoutParams(
+            final LayoutParams lp = new LayoutParams(
                     LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
 
             topPanel.addView(mCustomTitleView, 0, lp);
 
             // Hide the title template
-            View titleTemplate = mWindow.findViewById(R.id.title_template);
+            final View titleTemplate = mWindow.findViewById(R.id.title_template);
             titleTemplate.setVisibility(View.GONE);
         } else {
             mIconView = (ImageView) mWindow.findViewById(R.id.icon);
 
             final boolean hasTextTitle = !TextUtils.isEmpty(mTitle);
-            if (hasTextTitle) {
+            if (hasTextTitle && mShowTitle) {
                 // Display the title if a title is supplied, else hide it.
                 mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle);
                 mTitleView.setText(mTitle);
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 2733391..b0fb93b 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -25,6 +25,7 @@
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
 import android.content.ServiceConnection;
+import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
 import android.content.pm.LabeledIntent;
 import android.content.pm.PackageManager;
@@ -35,6 +36,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -68,6 +70,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -91,6 +94,11 @@
     private ChooserListAdapter mChooserListAdapter;
     private ChooserRowAdapter mChooserRowAdapter;
 
+    private SharedPreferences mPinnedSharedPrefs;
+    private static final float PINNED_TARGET_SCORE_BOOST = 1000.f;
+    private static final String PINNED_SHARED_PREFS_NAME = "chooser_pin_settings";
+    private static final String TARGET_DETAILS_FRAGMENT_TAG = "targetDetailsFragment";
+
     private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>();
 
     private static final int CHOOSER_TARGET_SERVICE_RESULT = 1;
@@ -207,12 +215,30 @@
         mRefinementIntentSender = intent.getParcelableExtra(
                 Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER);
         setSafeForwardingMode(true);
+
+        mPinnedSharedPrefs = getPinnedSharedPrefs(this);
         super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
                 null, false);
 
         MetricsLogger.action(this, MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN);
     }
 
+    static SharedPreferences getPinnedSharedPrefs(Context context) {
+        // The code below is because in the android:ui process, no one can hear you scream.
+        // The package info in the context isn't initialized in the way it is for normal apps,
+        // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we
+        // build the path manually below using the same policy that appears in ContextImpl.
+        // This fails silently under the hood if there's a problem, so if we find ourselves in
+        // the case where we don't have access to credential encrypted storage we just won't
+        // have our pinned target info.
+        final File prefsFile = new File(new File(
+                Environment.getDataUserCredentialEncryptedPackageDirectory(null,
+                        context.getUserId(), context.getPackageName()),
+                "shared_prefs"),
+                PINNED_SHARED_PREFS_NAME + ".xml");
+        return context.getSharedPreferences(prefsFile, MODE_PRIVATE);
+    }
+
     @Override
     protected void onDestroy() {
         super.onDestroy();
@@ -243,7 +269,7 @@
     }
 
     @Override
-    void onActivityStarted(TargetInfo cti) {
+    public void onActivityStarted(TargetInfo cti) {
         if (mChosenComponentSender != null) {
             final ComponentName target = cti.getResolvedComponentName();
             if (target != null) {
@@ -259,7 +285,7 @@
     }
 
     @Override
-    void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
+    public void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
             boolean alwaysUseOption) {
         final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null;
         mChooserListAdapter = (ChooserListAdapter) adapter;
@@ -272,17 +298,17 @@
     }
 
     @Override
-    int getLayoutResource() {
+    public int getLayoutResource() {
         return R.layout.chooser_grid;
     }
 
     @Override
-    boolean shouldGetActivityMetadata() {
+    public boolean shouldGetActivityMetadata() {
         return true;
     }
 
     @Override
-    boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
+    public boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
         final Intent intent = target.getResolvedIntent();
         final ResolveInfo resolve = target.getResolveInfo();
 
@@ -299,6 +325,16 @@
         return false;
     }
 
+    @Override
+    public void showTargetDetails(ResolveInfo ri) {
+        ComponentName name = ri.activityInfo.getComponentName();
+        boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
+        ResolverTargetActionsDialogFragment f =
+                new ResolverTargetActionsDialogFragment(ri.loadLabel(getPackageManager()),
+                        name, pinned);
+        f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
+    }
+
     private void modifyTargetIntent(Intent in) {
         final String action = in.getAction();
         if (Intent.ACTION_SEND.equals(action) ||
@@ -340,7 +376,7 @@
     }
 
     @Override
-    void startSelected(int which, boolean always, boolean filtered) {
+    public void startSelected(int which, boolean always, boolean filtered) {
         super.startSelected(which, always, filtered);
 
         if (mChooserListAdapter != null) {
@@ -471,7 +507,7 @@
         mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
     }
 
-    void onSetupVoiceInteraction() {
+    public void onSetupVoiceInteraction() {
         // Do nothing. We'll send the voice stuff ourselves.
     }
 
@@ -543,7 +579,7 @@
     }
 
     @Override
-    ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
+    public ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
             Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
             boolean filterLastUsed) {
         final ChooserListAdapter adapter = new ChooserListAdapter(context, payloadIntents,
@@ -711,6 +747,11 @@
             }
             return results;
         }
+
+        @Override
+        public boolean isPinned() {
+            return mSourceInfo != null ? mSourceInfo.isPinned() : false;
+        }
     }
 
     public class ChooserListAdapter extends ResolveListAdapter {
@@ -720,6 +761,7 @@
         public static final int TARGET_STANDARD = 2;
 
         private static final int MAX_SERVICE_TARGETS = 8;
+        private static final int MAX_TARGETS_PER_SERVICE = 4;
 
         private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
         private final List<TargetInfo> mCallerTargets = new ArrayList<>();
@@ -777,6 +819,20 @@
         }
 
         @Override
+        public boolean isComponentPinned(ComponentName name) {
+            return mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
+        }
+
+        @Override
+        public float getScore(DisplayResolveInfo target) {
+            float score = super.getScore(target);
+            if (target.isPinned()) {
+                score += PINNED_TARGET_SCORE_BOOST;
+            }
+            return score;
+        }
+
+        @Override
         public View onCreateView(ViewGroup parent) {
             return mInflater.inflate(
                     com.android.internal.R.layout.resolve_grid_item, parent, false);
@@ -870,7 +926,7 @@
             final float parentScore = getScore(origTarget);
             Collections.sort(targets, mBaseTargetComparator);
             float lastScore = 0;
-            for (int i = 0, N = targets.size(); i < N; i++) {
+            for (int i = 0, N = Math.min(targets.size(), MAX_TARGETS_PER_SERVICE); i < N; i++) {
                 final ChooserTarget target = targets.get(i);
                 float targetScore = target.getScore();
                 targetScore *= parentScore;
@@ -1121,7 +1177,7 @@
                 v.setOnLongClickListener(new OnLongClickListener() {
                     @Override
                     public boolean onLongClick(View v) {
-                        showAppDetails(
+                        showTargetDetails(
                                 mChooserListAdapter.resolveInfoForPosition(
                                         holder.itemIndices[column], true));
                         return true;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index ec53a2e..74fe94f 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -124,4 +124,5 @@
 
     void noteBleScanStarted(in WorkSource ws);
     void noteBleScanStopped(in WorkSource ws);
+    void noteResetBleScan();
 }
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index dbec740..015e60d 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -85,8 +85,10 @@
         int callingUserId = getUserId();
 
         if (canForward(newIntent, targetUserId)) {
-            if (newIntent.getAction().equals(Intent.ACTION_CHOOSER)) {
+            if (Intent.ACTION_CHOOSER.equals(newIntent.getAction())) {
                 Intent innerIntent = (Intent) newIntent.getParcelableExtra(Intent.EXTRA_INTENT);
+                // At this point, innerIntent is not null. Otherwise, canForward would have returned
+                // false.
                 innerIntent.prepareToLeaveUser(callingUserId);
             } else {
                 newIntent.prepareToLeaveUser(callingUserId);
@@ -124,7 +126,7 @@
                 Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show();
             }
         } else {
-            Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user "
+            Slog.wtf(TAG, "the intent: " + newIntent + " cannot be forwarded from user "
                     + callingUserId + " to user " + targetUserId);
         }
         finish();
@@ -132,7 +134,7 @@
 
     boolean canForward(Intent intent, int targetUserId)  {
         IPackageManager ipm = AppGlobals.getPackageManager();
-        if (intent.getAction().equals(Intent.ACTION_CHOOSER)) {
+        if (Intent.ACTION_CHOOSER.equals(intent.getAction())) {
             // The EXTRA_INITIAL_INTENTS may not be allowed to be forwarded.
             if (intent.hasExtra(Intent.EXTRA_INITIAL_INTENTS)) {
                 Slog.wtf(TAG, "An chooser intent with extra initial intents cannot be forwarded to"
@@ -145,6 +147,11 @@
                 return false;
             }
             intent = (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT);
+            if (intent == null) {
+                Slog.wtf(TAG, "Cannot forward a chooser intent with no extra "
+                        + Intent.EXTRA_INTENT);
+                return false;
+            }
         }
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         if (intent.getSelector() != null) {
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index 9a17883..956ee8c 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -138,22 +138,12 @@
         super.onCreate(savedInstanceState);
         setHasOptionsMenu(true);
 
-        Locale sortingLocale;
-        if (mCountryMode) {
-            if (mParentLocale == null) {
-                sortingLocale = Locale.getDefault();
-                this.getActivity().setTitle(R.string.country_selection_title);
-            } else {
-                sortingLocale = mParentLocale.getLocale();
-                this.getActivity().setTitle(mParentLocale.getFullNameNative());
-            }
-        } else {
-            sortingLocale = Locale.getDefault();
-            this.getActivity().setTitle(R.string.language_selection_title);
-        }
+        final Locale sortingLocale = (mCountryMode && mParentLocale != null)
+                ? mParentLocale.getLocale()
+                : Locale.getDefault();
 
         mAdapter = new SuggestedLocaleAdapter(mLocaleList, mCountryMode);
-        LocaleHelper.LocaleInfoComparator comp =
+        final LocaleHelper.LocaleInfoComparator comp =
                 new LocaleHelper.LocaleInfoComparator(sortingLocale);
         mAdapter.sort(comp);
         setListAdapter(mAdapter);
@@ -173,6 +163,17 @@
     @Override
     public void onResume() {
         super.onResume();
+
+        if (mCountryMode) {
+            if (mParentLocale == null) {
+                this.getActivity().setTitle(R.string.country_selection_title);
+            } else {
+                this.getActivity().setTitle(mParentLocale.getFullNameNative());
+            }
+        } else {
+            this.getActivity().setTitle(R.string.language_selection_title);
+        }
+
         getListView().requestFocus();
     }
 
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ec148c55..3fb768f 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -22,6 +22,7 @@
 import android.app.VoiceInteractor.PickOptionRequest;
 import android.app.VoiceInteractor.PickOptionRequest.Option;
 import android.app.VoiceInteractor.Prompt;
+import android.content.pm.ComponentInfo;
 import android.os.AsyncTask;
 import android.provider.Settings;
 import android.text.TextUtils;
@@ -51,6 +52,7 @@
 import android.os.Bundle;
 import android.os.PatternMatcher;
 import android.os.RemoteException;
+import android.os.StrictMode;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
@@ -172,6 +174,10 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
+        // We're dispatching intents that might be coming from legacy apps, so
+        // don't kill ourselves.
+        StrictMode.disableDeathOnFileUriExposure();
+
         // Use a specialized prompt when we're handling the 'Home' app startActivity()
         final Intent intent = makeMyIntent();
         final Set<String> categories = intent.getCategories();
@@ -336,12 +342,12 @@
     /**
      * Perform any initialization needed for voice interaction.
      */
-    void onSetupVoiceInteraction() {
+    public void onSetupVoiceInteraction() {
         // Do it right now. Subclasses may delay this and send it later.
         sendVoiceChoicesIfNeeded();
     }
 
-    void sendVoiceChoicesIfNeeded() {
+    public void sendVoiceChoicesIfNeeded() {
         if (!isVoiceInteraction()) {
             // Clearly not needed.
             return;
@@ -382,7 +388,7 @@
         return null;
     }
 
-    int getLayoutResource() {
+    public int getLayoutResource() {
         return R.layout.resolver_list;
     }
 
@@ -591,7 +597,7 @@
                 mAlwaysUseOption);
     }
 
-    void startSelected(int which, boolean always, boolean filtered) {
+    public void startSelected(int which, boolean always, boolean filtered) {
         if (isFinishing()) {
             return;
         }
@@ -761,7 +767,7 @@
         return true;
     }
 
-    void safelyStartActivity(TargetInfo cti) {
+    public void safelyStartActivity(TargetInfo cti) {
         // If needed, show that intent is forwarded
         // from managed profile to owner or other way around.
         if (mProfileSwitchMessageId != -1) {
@@ -791,26 +797,26 @@
         }
     }
 
-    void onActivityStarted(TargetInfo cti) {
+    public void onActivityStarted(TargetInfo cti) {
         // Do nothing
     }
 
-    boolean shouldGetActivityMetadata() {
+    public boolean shouldGetActivityMetadata() {
         return false;
     }
 
-    boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
+    public boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
         return true;
     }
 
-    void showAppDetails(ResolveInfo ri) {
+    public void showTargetDetails(ResolveInfo ri) {
         Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                 .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
         startActivity(in);
     }
 
-    ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
+    public ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
             Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
             boolean filterLastUsed) {
         return new ResolveListAdapter(context, payloadIntents, initialIntents, rList,
@@ -820,7 +826,7 @@
     /**
      * Returns true if the activity is finishing and creation should halt
      */
-    boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,
+    public boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,
             List<ResolveInfo> rList, boolean alwaysUseOption) {
         // The last argument of createAdapter is whether to do special handling
         // of the last used choice to highlight it in the list.  We need to always
@@ -867,7 +873,7 @@
         return false;
     }
 
-    void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
+    public void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
             boolean alwaysUseOption) {
         final boolean useHeader = adapter.hasFilteredItem();
         final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null;
@@ -898,7 +904,7 @@
                 && Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName);
     }
 
-    final class DisplayResolveInfo implements TargetInfo {
+    public final class DisplayResolveInfo implements TargetInfo {
         private final ResolveInfo mResolveInfo;
         private final CharSequence mDisplayLabel;
         private Drawable mDisplayIcon;
@@ -906,8 +912,9 @@
         private final CharSequence mExtendedInfo;
         private final Intent mResolvedIntent;
         private final List<Intent> mSourceIntents = new ArrayList<>();
+        private boolean mPinned;
 
-        DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
+        public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
                 CharSequence pInfo, Intent pOrigIntent) {
             mSourceIntents.add(originalIntent);
             mResolveInfo = pri;
@@ -932,6 +939,7 @@
             mExtendedInfo = other.mExtendedInfo;
             mResolvedIntent = new Intent(other.mResolvedIntent);
             mResolvedIntent.fillIn(fillInIntent, flags);
+            mPinned = other.mPinned;
         }
 
         public ResolveInfo getResolveInfo() {
@@ -1026,6 +1034,15 @@
             activity.startActivityAsUser(mResolvedIntent, options, user);
             return false;
         }
+
+        @Override
+        public boolean isPinned() {
+            return mPinned;
+        }
+
+        public void setPinned(boolean pinned) {
+            mPinned = pinned;
+        }
     }
 
     /**
@@ -1039,7 +1056,7 @@
          *
          * @return the resolved intent for this target
          */
-        public Intent getResolvedIntent();
+        Intent getResolvedIntent();
 
         /**
          * Get the resolved component name that represents this target. Note that this may not
@@ -1048,7 +1065,7 @@
          *
          * @return the resolved ComponentName for this target
          */
-        public ComponentName getResolvedComponentName();
+        ComponentName getResolvedComponentName();
 
         /**
          * Start the activity referenced by this target.
@@ -1057,7 +1074,7 @@
          * @param options ActivityOptions bundle
          * @return true if the start completed successfully
          */
-        public boolean start(Activity activity, Bundle options);
+        boolean start(Activity activity, Bundle options);
 
         /**
          * Start the activity referenced by this target as if the ResolverActivity's caller
@@ -1068,7 +1085,7 @@
          * @param userId userId to start as or {@link UserHandle#USER_NULL} for activity's caller
          * @return true if the start completed successfully
          */
-        public boolean startAsCaller(Activity activity, Bundle options, int userId);
+        boolean startAsCaller(Activity activity, Bundle options, int userId);
 
         /**
          * Start the activity referenced by this target as a given user.
@@ -1078,7 +1095,7 @@
          * @param user handle for the user to start the activity as
          * @return true if the start completed successfully
          */
-        public boolean startAsUser(Activity activity, Bundle options, UserHandle user);
+        boolean startAsUser(Activity activity, Bundle options, UserHandle user);
 
         /**
          * Return the ResolveInfo about how and why this target matched the original query
@@ -1086,14 +1103,14 @@
          *
          * @return ResolveInfo representing this target's match
          */
-        public ResolveInfo getResolveInfo();
+        ResolveInfo getResolveInfo();
 
         /**
          * Return the human-readable text label for this target.
          *
          * @return user-visible target label
          */
-        public CharSequence getDisplayLabel();
+        CharSequence getDisplayLabel();
 
         /**
          * Return any extended info for this target. This may be used to disambiguate
@@ -1101,35 +1118,40 @@
          *
          * @return human-readable disambig string or null if none present
          */
-        public CharSequence getExtendedInfo();
+        CharSequence getExtendedInfo();
 
         /**
          * @return The drawable that should be used to represent this target
          */
-        public Drawable getDisplayIcon();
+        Drawable getDisplayIcon();
 
         /**
          * @return The (small) icon to badge the target with
          */
-        public Drawable getBadgeIcon();
+        Drawable getBadgeIcon();
 
         /**
          * @return The content description for the badge icon
          */
-        public CharSequence getBadgeContentDescription();
+        CharSequence getBadgeContentDescription();
 
         /**
          * Clone this target with the given fill-in information.
          */
-        public TargetInfo cloneFilledIn(Intent fillInIntent, int flags);
+        TargetInfo cloneFilledIn(Intent fillInIntent, int flags);
 
         /**
          * @return the list of supported source intents deduped against this single target
          */
-        public List<Intent> getAllSourceIntents();
+        List<Intent> getAllSourceIntents();
+
+        /**
+         * @return true if this target should be pinned to the front by the request of the user
+         */
+        boolean isPinned();
     }
 
-    class ResolveListAdapter extends BaseAdapter {
+    public class ResolveListAdapter extends BaseAdapter {
         private final List<Intent> mIntents;
         private final Intent[] mInitialIntents;
         private final List<ResolveInfo> mBaseResolveList;
@@ -1376,9 +1398,12 @@
                     }
                 }
                 if (!found) {
-                    into.add(new ResolvedComponentInfo(new ComponentName(
-                            newInfo.activityInfo.packageName, newInfo.activityInfo.name),
-                            intent, newInfo));
+                    final ComponentName name = new ComponentName(
+                            newInfo.activityInfo.packageName, newInfo.activityInfo.name);
+                    final ResolvedComponentInfo rci = new ResolvedComponentInfo(name,
+                            intent, newInfo);
+                    rci.setPinned(isComponentPinned(name));
+                    into.add(rci);
                 }
             }
         }
@@ -1454,6 +1479,7 @@
             final Intent replaceIntent = getReplacementIntent(add.activityInfo, intent);
             final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, roLabel,
                     extraInfo, replaceIntent);
+            dri.setPinned(rci.isPinned());
             addResolveInfo(dri);
             if (replaceIntent == intent) {
                 // Only add alternates if we didn't get a specific replacement from
@@ -1537,11 +1563,11 @@
             return false;
         }
 
-        protected int getDisplayResolveInfoCount() {
+        public int getDisplayResolveInfoCount() {
             return mDisplayList.size();
         }
 
-        protected DisplayResolveInfo getDisplayResolveInfo(int index) {
+        public DisplayResolveInfo getDisplayResolveInfo(int index) {
             // Used to query services. We only query services for primary targets, not alternates.
             return mDisplayList.get(index);
         }
@@ -1571,6 +1597,10 @@
             return !TextUtils.isEmpty(info.getExtendedInfo());
         }
 
+        public boolean isComponentPinned(ComponentName name) {
+            return false;
+        }
+
         public final void bindView(int position, View view) {
             onBindView(view, getItem(position));
         }
@@ -1607,6 +1637,7 @@
 
     static final class ResolvedComponentInfo {
         public final ComponentName name;
+        private boolean mPinned;
         private final List<Intent> mIntents = new ArrayList<>();
         private final List<ResolveInfo> mResolveInfos = new ArrayList<>();
 
@@ -1649,6 +1680,14 @@
             }
             return -1;
         }
+
+        public boolean isPinned() {
+            return mPinned;
+        }
+
+        public void setPinned(boolean pinned) {
+            mPinned = pinned;
+        }
     }
 
     static class ViewHolder {
@@ -1702,7 +1741,7 @@
                 return false;
             }
             ResolveInfo ri = mAdapter.resolveInfoForPosition(position, true);
-            showAppDetails(ri);
+            showTargetDetails(ri);
             return true;
         }
 
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 31556e2..03a3a38 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -47,12 +47,12 @@
 
     private static final boolean DEBUG = false;
 
-    // Two weeks
-    private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
+    // One week
+    private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 7;
 
     private static final long RECENCY_TIME_PERIOD = 1000 * 60 * 60 * 12;
 
-    private static final float RECENCY_MULTIPLIER = 3.f;
+    private static final float RECENCY_MULTIPLIER = 2.f;
 
     private final Collator mCollator;
     private final boolean mHttp;
@@ -171,15 +171,27 @@
             }
         }
 
-        if (mStats != null) {
-            final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName(
-                    lhs.activityInfo.packageName, lhs.activityInfo.name));
-            final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
-                    rhs.activityInfo.packageName, rhs.activityInfo.name));
-            final float diff = rhsTarget.score - lhsTarget.score;
+        final boolean lPinned = lhsp.isPinned();
+        final boolean rPinned = rhsp.isPinned();
 
-            if (diff != 0) {
-                return diff > 0 ? 1 : -1;
+        if (lPinned && !rPinned) {
+            return -1;
+        } else if (!lPinned && rPinned) {
+            return 1;
+        }
+
+        // Pinned items stay stable within a normal lexical sort and ignore scoring.
+        if (!lPinned && !rPinned) {
+            if (mStats != null) {
+                final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName(
+                        lhs.activityInfo.packageName, lhs.activityInfo.name));
+                final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
+                        rhs.activityInfo.packageName, rhs.activityInfo.name));
+                final float diff = rhsTarget.score - lhsTarget.score;
+
+                if (diff != 0) {
+                    return diff > 0 ? 1 : -1;
+                }
             }
         }
 
diff --git a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
new file mode 100644
index 0000000..8156f79
--- /dev/null
+++ b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.internal.app;
+
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.ComponentName;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import com.android.internal.R;
+
+/**
+ * Shows a dialog with actions to take on a chooser target
+ */
+public class ResolverTargetActionsDialogFragment extends DialogFragment
+        implements DialogInterface.OnClickListener {
+    private static final String NAME_KEY = "componentName";
+    private static final String PINNED_KEY = "pinned";
+    private static final String TITLE_KEY = "title";
+
+    // Sync with R.array.resolver_target_actions_* resources
+    private static final int TOGGLE_PIN_INDEX = 0;
+    private static final int APP_INFO_INDEX = 1;
+
+    public ResolverTargetActionsDialogFragment() {
+    }
+
+    public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name,
+            boolean pinned) {
+        Bundle args = new Bundle();
+        args.putCharSequence(TITLE_KEY, title);
+        args.putParcelable(NAME_KEY, name);
+        args.putBoolean(PINNED_KEY, pinned);
+        setArguments(args);
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        final Bundle args = getArguments();
+        final int itemRes = args.getBoolean(PINNED_KEY, false)
+                ? R.array.resolver_target_actions_unpin
+                : R.array.resolver_target_actions_pin;
+        return new Builder(getContext())
+                .setCancelable(true)
+                .setItems(itemRes, this)
+                .setTitle(args.getCharSequence(TITLE_KEY))
+                .create();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        final Bundle args = getArguments();
+        ComponentName name = args.getParcelable(NAME_KEY);
+        switch (which) {
+            case TOGGLE_PIN_INDEX:
+                SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext());
+                final String key = name.flattenToString();
+                boolean currentVal = sp.getBoolean(name.flattenToString(), false);
+                if (currentVal) {
+                    sp.edit().remove(key).apply();
+                } else {
+                    sp.edit().putBoolean(key, true).apply();
+                }
+
+                // Force the chooser to requery and resort things
+                getActivity().recreate();
+                break;
+            case APP_INFO_INDEX:
+                Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+                        .setData(Uri.fromParts("package", name.getPackageName(), null))
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+                startActivity(in);
+                break;
+        }
+        dismiss();
+    }
+}
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index c4ec714..478a56d 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.app;
 
+import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -165,6 +166,14 @@
                     localized.setVisibility(View.VISIBLE);
                     text.setTextLocale(Locale.getDefault());
                 }
+                if (mCountryMode) {
+                    int layoutDir = TextUtils.getLayoutDirectionFromLocale(item.getParent());
+                    //noinspection ResourceType
+                    convertView.setLayoutDirection(layoutDir);
+                    text.setTextDirection(layoutDir == View.LAYOUT_DIRECTION_RTL
+                            ? View.TEXT_DIRECTION_RTL
+                            : View.TEXT_DIRECTION_LTR);
+                }
         }
         return convertView;
     }
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index 049d3eb..d92e596 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -44,6 +44,7 @@
     public long wakeLockTimeMs;
     public long cameraTimeMs;
     public long flashlightTimeMs;
+    public long bluetoothRunningTimeMs;
 
     public long mobileRxPackets;
     public long mobileTxPackets;
@@ -56,6 +57,8 @@
     public long mobileTxBytes;
     public long wifiRxBytes;
     public long wifiTxBytes;
+    public long btRxBytes;
+    public long btTxBytes;
     public double percent;
     public double noCoveragePercent;
     public String[] mPackages;
@@ -71,6 +74,7 @@
     public double sensorPowerMah;
     public double cameraPowerMah;
     public double flashlightPowerMah;
+    public double bluetoothPowerMah;
 
     public enum DrainType {
         IDLE,
@@ -142,6 +146,7 @@
         wakeLockTimeMs += other.wakeLockTimeMs;
         cameraTimeMs += other.cameraTimeMs;
         flashlightTimeMs += other.flashlightTimeMs;
+        bluetoothRunningTimeMs += other.bluetoothRunningTimeMs;
         mobileRxPackets += other.mobileRxPackets;
         mobileTxPackets += other.mobileTxPackets;
         mobileActive += other.mobileActive;
@@ -152,6 +157,8 @@
         mobileTxBytes += other.mobileTxBytes;
         wifiRxBytes += other.wifiRxBytes;
         wifiTxBytes += other.wifiTxBytes;
+        btRxBytes += other.btRxBytes;
+        btTxBytes += other.btTxBytes;
         wifiPowerMah += other.wifiPowerMah;
         gpsPowerMah += other.gpsPowerMah;
         cpuPowerMah += other.cpuPowerMah;
@@ -160,6 +167,7 @@
         wakeLockPowerMah += other.wakeLockPowerMah;
         cameraPowerMah += other.cameraPowerMah;
         flashlightPowerMah += other.flashlightPowerMah;
+        bluetoothPowerMah += other.bluetoothPowerMah;
     }
 
     /**
@@ -169,6 +177,6 @@
     public double sumPower() {
         return totalPowerMah = usagePowerMah + wifiPowerMah + gpsPowerMah + cpuPowerMah +
                 sensorPowerMah + mobileRadioPowerMah + wakeLockPowerMah + cameraPowerMah +
-                flashlightPowerMah;
+                flashlightPowerMah + bluetoothPowerMah;
     }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index e2ccaae..648b1a5 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -107,7 +107,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 140 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 141 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -186,8 +186,13 @@
     }
 
     public interface ExternalStatsSync {
-        void scheduleSync(String reason);
-        void scheduleWifiSync(String reason);
+        public static final int UPDATE_CPU = 0x01;
+        public static final int UPDATE_WIFI = 0x02;
+        public static final int UPDATE_RADIO = 0x04;
+        public static final int UPDATE_BT = 0x08;
+        public static final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
+
+        void scheduleSync(String reason, int flags);
         void scheduleCpuSyncDueToRemovedUid(int uid);
     }
 
@@ -224,6 +229,7 @@
     final ArrayList<StopwatchTimer> mVideoTurnedOnTimers = new ArrayList<>();
     final ArrayList<StopwatchTimer> mFlashlightTurnedOnTimers = new ArrayList<>();
     final ArrayList<StopwatchTimer> mCameraTurnedOnTimers = new ArrayList<>();
+    final ArrayList<StopwatchTimer> mBluetoothScanOnTimers = new ArrayList<>();
 
     // Last partial timers we use for distributing CPU usage.
     final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<>();
@@ -435,6 +441,9 @@
     final StopwatchTimer[] mWifiSignalStrengthsTimer =
             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
 
+    int mBluetoothScanNesting;
+    StopwatchTimer mBluetoothScanTimer;
+
     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
     long mMobileRadioActiveStartTime;
     StopwatchTimer mMobileRadioActiveTimer;
@@ -3714,7 +3723,7 @@
             addHistoryRecordLocked(elapsedRealtime, uptime);
             mWifiOn = true;
             mWifiOnTimer.startRunningLocked(elapsedRealtime);
-            scheduleSyncExternalWifiStatsLocked("wifi-off");
+            scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
         }
     }
 
@@ -3728,7 +3737,7 @@
             addHistoryRecordLocked(elapsedRealtime, uptime);
             mWifiOn = false;
             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
-            scheduleSyncExternalWifiStatsLocked("wifi-on");
+            scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
         }
     }
 
@@ -3946,6 +3955,65 @@
         }
     }
 
+    private void noteBluetoothScanStartedLocked(int uid) {
+        uid = mapUid(uid);
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long uptime = SystemClock.uptimeMillis();
+        if (mBluetoothScanNesting == 0) {
+            mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
+            if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: "
+                    + Integer.toHexString(mHistoryCur.states2));
+            addHistoryRecordLocked(elapsedRealtime, uptime);
+        }
+        mBluetoothScanNesting++;
+        getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime);
+    }
+
+    public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws) {
+        final int N = ws.size();
+        for (int i = 0; i < N; i++) {
+            noteBluetoothScanStartedLocked(ws.get(i));
+        }
+    }
+
+    private void noteBluetoothScanStoppedLocked(int uid) {
+        uid = mapUid(uid);
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long uptime = SystemClock.uptimeMillis();
+        mBluetoothScanNesting--;
+        if (mBluetoothScanNesting == 0) {
+            mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
+            if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: "
+                    + Integer.toHexString(mHistoryCur.states2));
+            addHistoryRecordLocked(elapsedRealtime, uptime);
+        }
+        getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime);
+    }
+
+    public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws) {
+        final int N = ws.size();
+        for (int i = 0; i < N; i++) {
+            noteBluetoothScanStoppedLocked(ws.get(i));
+        }
+    }
+
+    public void noteResetBluetoothScanLocked() {
+        if (mBluetoothScanNesting > 0) {
+            final long elapsedRealtime = SystemClock.elapsedRealtime();
+            final long uptime = SystemClock.uptimeMillis();
+            mBluetoothScanNesting = 0;
+            mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG;
+            if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: "
+                    + Integer.toHexString(mHistoryCur.states2));
+            addHistoryRecordLocked(elapsedRealtime, uptime);
+            mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime);
+            for (int i=0; i<mUidStats.size(); i++) {
+                BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+                uid.noteResetBluetoothScanLocked(elapsedRealtime);
+            }
+        }
+    }
+
     public void noteWifiRadioPowerState(int powerState, long timestampNs) {
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         final long uptime = SystemClock.uptimeMillis();
@@ -3980,7 +4048,7 @@
                 int uid = mapUid(ws.get(i));
                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
             }
-            scheduleSyncExternalWifiStatsLocked("wifi-running");
+            scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
         } else {
             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
         }
@@ -4019,7 +4087,7 @@
                 int uid = mapUid(ws.get(i));
                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
             }
-            scheduleSyncExternalWifiStatsLocked("wifi-stopped");
+            scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
         } else {
             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
         }
@@ -4034,7 +4102,7 @@
             }
             mWifiState = wifiState;
             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
-            scheduleSyncExternalWifiStatsLocked("wifi-state");
+            scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
         }
     }
 
@@ -4530,6 +4598,11 @@
     }
 
     @Override
+    public long getBluetoothScanTime(long elapsedRealtimeUs, int which) {
+        return mBluetoothScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+    }
+
+    @Override
     public long getNetworkActivityBytes(int type, int which) {
         if (type >= 0 && type < mNetworkByteActivityCounters.length) {
             return mNetworkByteActivityCounters[type].getCountLocked(which);
@@ -4603,9 +4676,8 @@
         StopwatchTimer mVideoTurnedOnTimer;
         StopwatchTimer mFlashlightTurnedOnTimer;
         StopwatchTimer mCameraTurnedOnTimer;
-
-
         StopwatchTimer mForegroundActivityTimer;
+        StopwatchTimer mBluetoothScanTimer;
 
         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
         StopwatchTimer[] mProcessStateTimer;
@@ -4997,6 +5069,30 @@
             return mForegroundActivityTimer;
         }
 
+        public StopwatchTimer createBluetoothScanTimerLocked() {
+            if (mBluetoothScanTimer == null) {
+                mBluetoothScanTimer = new StopwatchTimer(Uid.this, BLUETOOTH_SCAN_ON,
+                        mBluetoothScanOnTimers, mOnBatteryTimeBase);
+            }
+            return mBluetoothScanTimer;
+        }
+
+        public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs) {
+            createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
+        }
+
+        public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs) {
+            if (mBluetoothScanTimer != null) {
+                mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
+            }
+        }
+
+        public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
+            if (mBluetoothScanTimer != null) {
+                mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
+            }
+        }
+
         @Override
         public void noteActivityResumedLocked(long elapsedRealtimeMs) {
             // We always start, since we want multiple foreground PIDs to nest
@@ -5110,6 +5206,11 @@
             return mForegroundActivityTimer;
         }
 
+        @Override
+        public Timer getBluetoothScanTimer() {
+            return mBluetoothScanTimer;
+        }
+
         void makeProcessState(int i, Parcel in) {
             if (i < 0 || i >= NUM_PROCESS_STATE) return;
 
@@ -5335,6 +5436,9 @@
             if (mForegroundActivityTimer != null) {
                 active |= !mForegroundActivityTimer.reset(false);
             }
+            if (mBluetoothScanTimer != null) {
+                active |= !mBluetoothScanTimer.reset(false);
+            }
             if (mProcessStateTimer != null) {
                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
                     if (mProcessStateTimer[i] != null) {
@@ -5509,6 +5613,10 @@
                     mForegroundActivityTimer.detach();
                     mForegroundActivityTimer = null;
                 }
+                if (mBluetoothScanTimer != null) {
+                    mBluetoothScanTimer.detach();
+                    mBluetoothScanTimer = null;
+                }
                 if (mUserActivityCounters != null) {
                     for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
                         mUserActivityCounters[i].detach();
@@ -5669,6 +5777,12 @@
             } else {
                 out.writeInt(0);
             }
+            if (mBluetoothScanTimer != null) {
+                out.writeInt(1);
+                mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
+            } else {
+                out.writeInt(0);
+            }
             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
                 if (mProcessStateTimer[i] != null) {
                     out.writeInt(1);
@@ -5874,6 +5988,12 @@
             } else {
                 mForegroundActivityTimer = null;
             }
+            if (in.readInt() != 0) {
+                mBluetoothScanTimer = new StopwatchTimer(Uid.this, BLUETOOTH_SCAN_ON,
+                        mBluetoothScanOnTimers, mOnBatteryTimeBase, in);
+            } else {
+                mBluetoothScanTimer = null;
+            }
             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
                 if (in.readInt() != 0) {
@@ -7133,6 +7253,7 @@
         mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
         mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase);
         mCameraOnTimer = new StopwatchTimer(null, -13, null, mOnBatteryTimeBase);
+        mBluetoothScanTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase);
         mOnBattery = mOnBatteryInternal = false;
         long uptime = SystemClock.uptimeMillis() * 1000;
         long realtime = SystemClock.elapsedRealtime() * 1000;
@@ -7732,6 +7853,7 @@
         mVideoOnTimer.reset(false);
         mFlashlightOnTimer.reset(false);
         mCameraOnTimer.reset(false);
+        mBluetoothScanTimer.reset(false);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i].reset(false);
         }
@@ -8264,41 +8386,168 @@
             Slog.d(TAG, "Updating bluetooth stats: " + info);
         }
 
-        if (info != null && mOnBatteryInternal) {
-            mHasBluetoothReporting = true;
-            mBluetoothActivity.getRxTimeCounter().addCountLocked(
-                    info.getControllerRxTimeMillis());
-            mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(
-                    info.getControllerTxTimeMillis());
-            mBluetoothActivity.getIdleTimeCounter().addCountLocked(
-                    info.getControllerIdleTimeMillis());
+        if (info == null || !mOnBatteryInternal) {
+            return;
+        }
 
-            // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
-            final double opVolt = mPowerProfile.getAveragePower(
-                    PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
-            if (opVolt != 0) {
-                // We store the power drain as mAms.
-                mBluetoothActivity.getPowerCounter().addCountLocked(
-                        (long) (info.getControllerEnergyUsed() / opVolt));
+        mHasBluetoothReporting = true;
+
+        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
+        final long rxTimeMs = info.getControllerRxTimeMillis();
+        final long txTimeMs = info.getControllerTxTimeMillis();
+
+        if (DEBUG_ENERGY) {
+            Slog.d(TAG, "------ BEGIN BLE power blaming ------");
+            Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
+            Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
+            Slog.d(TAG, "  Idle Time:  " + info.getControllerIdleTimeMillis() + " ms");
+        }
+
+        long totalScanTimeMs = 0;
+
+        final int uidCount = mUidStats.size();
+        for (int i = 0; i < uidCount; i++) {
+            final Uid u = mUidStats.valueAt(i);
+            if (u.mBluetoothScanTimer == null) {
+                continue;
             }
 
-            final UidTraffic[] uidTraffic = info.getUidTraffic();
-            final int numUids = uidTraffic != null ? uidTraffic.length : 0;
+            totalScanTimeMs += u.mBluetoothScanTimer.getTimeSinceMarkLocked(
+                    elapsedRealtimeMs * 1000) / 1000;
+        }
+
+        final boolean normalizeScanRxTime = (totalScanTimeMs > rxTimeMs);
+        final boolean normalizeScanTxTime = (totalScanTimeMs > txTimeMs);
+
+        if (DEBUG_ENERGY) {
+            Slog.d(TAG, "Normalizing scan power for RX=" + normalizeScanRxTime
+                    + " TX=" + normalizeScanTxTime);
+        }
+
+        long leftOverRxTimeMs = rxTimeMs;
+        long leftOverTxTimeMs = txTimeMs;
+
+        for (int i = 0; i < uidCount; i++) {
+            final Uid u = mUidStats.valueAt(i);
+            if (u.mBluetoothScanTimer == null) {
+                continue;
+            }
+
+            long scanTimeSinceMarkMs = u.mBluetoothScanTimer.getTimeSinceMarkLocked(
+                    elapsedRealtimeMs * 1000) / 1000;
+            if (scanTimeSinceMarkMs > 0) {
+                // Set the new mark so that next time we get new data since this point.
+                u.mBluetoothScanTimer.setMark(elapsedRealtimeMs);
+
+                long scanTimeRxSinceMarkMs = scanTimeSinceMarkMs;
+                long scanTimeTxSinceMarkMs = scanTimeSinceMarkMs;
+
+                if (normalizeScanRxTime) {
+                    // Scan time is longer than the total rx time in the controller,
+                    // so distribute the scan time proportionately. This means regular traffic
+                    // will not blamed, but scans are more expensive anyways.
+                    scanTimeRxSinceMarkMs = (rxTimeMs * scanTimeRxSinceMarkMs) / totalScanTimeMs;
+                }
+
+                if (normalizeScanTxTime) {
+                    // Scan time is longer than the total tx time in the controller,
+                    // so distribute the scan time proportionately. This means regular traffic
+                    // will not blamed, but scans are more expensive anyways.
+                    scanTimeTxSinceMarkMs = (txTimeMs * scanTimeTxSinceMarkMs) / totalScanTimeMs;
+                }
+
+                final ControllerActivityCounterImpl counter =
+                        u.getOrCreateBluetoothControllerActivityLocked();
+                counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
+                counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
+
+                leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
+                leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
+            }
+        }
+
+        if (DEBUG_ENERGY) {
+            Slog.d(TAG, "Left over time for traffic RX=" + leftOverRxTimeMs
+                    + " TX=" + leftOverTxTimeMs);
+        }
+
+        //
+        // Now distribute blame to apps that did bluetooth traffic.
+        //
+
+        long totalTxBytes = 0;
+        long totalRxBytes = 0;
+
+        final UidTraffic[] uidTraffic = info.getUidTraffic();
+        final int numUids = uidTraffic != null ? uidTraffic.length : 0;
+        for (int i = 0; i < numUids; i++) {
+            final UidTraffic traffic = uidTraffic[i];
+
+            // Add to the global counters.
+            mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(
+                    traffic.getRxBytes());
+            mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(
+                    traffic.getTxBytes());
+
+            // Add to the UID counters.
+            final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
+            u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, traffic.getRxBytes(), 0);
+            u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, traffic.getTxBytes(), 0);
+
+            // Calculate the total traffic.
+            totalTxBytes += traffic.getTxBytes();
+            totalRxBytes += traffic.getRxBytes();
+        }
+
+        if ((totalTxBytes != 0 || totalRxBytes != 0) &&
+                (leftOverRxTimeMs != 0 || leftOverTxTimeMs != 0)) {
             for (int i = 0; i < numUids; i++) {
                 final UidTraffic traffic = uidTraffic[i];
 
-                // Add to the global counters.
-                mNetworkByteActivityCounters[NETWORK_BT_RX_DATA].addCountLocked(
-                        traffic.getRxBytes());
-                mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(
-                        traffic.getTxBytes());
-
-                // Add to the UID counters.
                 final Uid u = getUidStatsLocked(mapUid(traffic.getUid()));
-                u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, traffic.getRxBytes(), 0);
-                u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, traffic.getTxBytes(), 0);
+                final ControllerActivityCounterImpl counter =
+                        u.getOrCreateBluetoothControllerActivityLocked();
+
+                if (totalRxBytes > 0 && traffic.getRxBytes() > 0) {
+                    final long timeRxMs = (leftOverRxTimeMs * traffic.getRxBytes()) / totalRxBytes;
+
+                    if (DEBUG_ENERGY) {
+                        Slog.d(TAG, "UID=" + traffic.getUid() + " rx_bytes=" + traffic.getRxBytes()
+                                + " rx_time=" + timeRxMs);
+                    }
+                    counter.getRxTimeCounter().addCountLocked(timeRxMs);
+                    leftOverRxTimeMs -= timeRxMs;
+                }
+
+                if (totalTxBytes > 0 && traffic.getTxBytes() > 0) {
+                    final long timeTxMs = (leftOverTxTimeMs * traffic.getTxBytes()) / totalTxBytes;
+
+                    if (DEBUG_ENERGY) {
+                        Slog.d(TAG, "UID=" + traffic.getUid() + " tx_bytes=" + traffic.getTxBytes()
+                                + " tx_time=" + timeTxMs);
+                    }
+
+                    counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
+                    leftOverTxTimeMs -= timeTxMs;
+                }
             }
         }
+
+        mBluetoothActivity.getRxTimeCounter().addCountLocked(
+                info.getControllerRxTimeMillis());
+        mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(
+                info.getControllerTxTimeMillis());
+        mBluetoothActivity.getIdleTimeCounter().addCountLocked(
+                info.getControllerIdleTimeMillis());
+
+        // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
+        final double opVolt = mPowerProfile.getAveragePower(
+                PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+        if (opVolt != 0) {
+            // We store the power drain as mAms.
+            mBluetoothActivity.getPowerCounter().addCountLocked(
+                    (long) (info.getControllerEnergyUsed() / opVolt));
+        }
     }
 
     /**
@@ -8739,15 +8988,9 @@
         }
     }
 
-    private void scheduleSyncExternalStatsLocked(String reason) {
+    private void scheduleSyncExternalStatsLocked(String reason, int updateFlags) {
         if (mExternalSync != null) {
-            mExternalSync.scheduleSync(reason);
-        }
-    }
-
-    private void scheduleSyncExternalWifiStatsLocked(String reason) {
-        if (mExternalSync != null) {
-            mExternalSync.scheduleWifiSync(reason);
+            mExternalSync.scheduleSync(reason, updateFlags);
         }
     }
 
@@ -8815,7 +9058,7 @@
 
                 // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
                 // which will pull external stats.
-                scheduleSyncExternalStatsLocked("battery-level");
+                scheduleSyncExternalStatsLocked("battery-level", ExternalStatsSync.UPDATE_ALL);
             }
             if (mHistoryCur.batteryStatus != status) {
                 mHistoryCur.batteryStatus = (byte)status;
@@ -9596,6 +9839,8 @@
         mFlashlightOnTimer.readSummaryFromParcelLocked(in);
         mCameraOnNesting = 0;
         mCameraOnTimer.readSummaryFromParcelLocked(in);
+        mBluetoothScanNesting = 0;
+        mBluetoothScanTimer.readSummaryFromParcelLocked(in);
 
         int NKW = in.readInt();
         if (NKW > 10000) {
@@ -9666,6 +9911,9 @@
             if (in.readInt() != 0) {
                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
             }
+            if (in.readInt() != 0) {
+                u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
+            }
             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
                 if (in.readInt() != 0) {
@@ -9928,6 +10176,7 @@
         out.writeInt(mNumConnectivityChange);
         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
 
         out.writeInt(mKernelWakelockStats.size());
         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
@@ -10021,6 +10270,12 @@
             } else {
                 out.writeInt(0);
             }
+            if (u.mBluetoothScanTimer != null) {
+                out.writeInt(1);
+                u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+            } else {
+                out.writeInt(0);
+            }
             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
                 if (u.mProcessStateTimer[i] != null) {
                     out.writeInt(1);
@@ -10289,6 +10544,8 @@
         mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase, in);
         mCameraOnNesting = 0;
         mCameraOnTimer = new StopwatchTimer(null, -13, null, mOnBatteryTimeBase, in);
+        mBluetoothScanNesting = 0;
+        mBluetoothScanTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase, in);
         mDischargeUnplugLevel = in.readInt();
         mDischargePlugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
@@ -10436,6 +10693,7 @@
         out.writeInt(mUnpluggedNumConnectivityChange);
         mFlashlightOnTimer.writeToParcel(out, uSecRealtime);
         mCameraOnTimer.writeToParcel(out, uSecRealtime);
+        mBluetoothScanTimer.writeToParcel(out, uSecRealtime);
         out.writeInt(mDischargeUnplugLevel);
         out.writeInt(mDischargePlugLevel);
         out.writeInt(mDischargeCurrentLevel);
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 531d1fa..2f383eac 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -24,6 +24,8 @@
     private final double mIdleMa;
     private final double mRxMa;
     private final double mTxMa;
+    private double mAppTotalPowerMah = 0;
+    private long mAppTotalTimeMs = 0;
 
     public BluetoothPowerCalculator(PowerProfile profile) {
         mIdleMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE);
@@ -34,7 +36,31 @@
     @Override
     public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
                              long rawUptimeUs, int statsType) {
-        // No per-app distribution yet.
+
+        final BatteryStats.ControllerActivityCounter counter = u.getBluetoothControllerActivity();
+        if (counter == null) {
+            return;
+        }
+
+        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
+        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
+        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+        final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
+        double powerMah = counter.getPowerCounter().getCountLocked(statsType)
+                / (double)(1000*60*60);
+
+        if (powerMah == 0) {
+            powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
+                    / (1000*60*60);
+        }
+
+        app.bluetoothPowerMah = powerMah;
+        app.bluetoothRunningTimeMs = totalTimeMs;
+        app.btRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, statsType);
+        app.btTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, statsType);
+
+        mAppTotalPowerMah += powerMah;
+        mAppTotalTimeMs += totalTimeMs;
     }
 
     @Override
@@ -56,12 +82,21 @@
                     / (1000*60*60);
         }
 
+        // Subtract what the apps used, but clamp to 0.
+        powerMah = Math.max(0, powerMah - mAppTotalPowerMah);
+
         if (DEBUG && powerMah != 0) {
             Log.d(TAG, "Bluetooth active: time=" + (totalTimeMs)
                     + " power=" + BatteryStatsHelper.makemAh(powerMah));
         }
 
-        app.usagePowerMah = powerMah;
-        app.usageTimeMs = totalTimeMs;
+        app.bluetoothPowerMah = powerMah;
+        app.bluetoothRunningTimeMs = Math.max(0, totalTimeMs - mAppTotalTimeMs);
+    }
+
+    @Override
+    public void reset() {
+        mAppTotalPowerMah = 0;
+        mAppTotalTimeMs = 0;
     }
 }
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 2a27f70..b447039 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -29,6 +29,7 @@
     private final double mTxCurrentMa;
     private final double mRxCurrentMa;
     private double mTotalAppPowerDrain = 0;
+    private long mTotalAppRunningTime = 0;
 
     public WifiPowerCalculator(PowerProfile profile) {
         mIdleCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
@@ -48,6 +49,8 @@
         final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType);
         final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
         app.wifiRunningTimeMs = idleTime + rxTime + txTime;
+        mTotalAppRunningTime += app.wifiRunningTimeMs;
+
         app.wifiPowerMah =
                 ((idleTime * mIdleCurrentMa) + (txTime * mTxCurrentMa) + (rxTime * mRxCurrentMa))
                 / (1000*60*60);
@@ -76,7 +79,9 @@
         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
-        app.wifiRunningTimeMs = idleTimeMs + rxTimeMs + txTimeMs;
+
+        app.wifiRunningTimeMs = Math.max(0,
+                (idleTimeMs + rxTimeMs + txTimeMs) - mTotalAppRunningTime);
 
         double powerDrainMah = counter.getPowerCounter().getCountLocked(statsType)
                 / (double)(1000*60*60);
@@ -95,5 +100,6 @@
     @Override
     public void reset() {
         mTotalAppPowerDrain = 0;
+        mTotalAppRunningTime = 0;
     }
 }
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index de54d96..6931193 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -24,7 +24,6 @@
 import android.view.DisplayListCanvas;
 import android.view.RenderNode;
 import android.view.ThreadedRenderer;
-import android.view.View;
 
 /**
  * The thread which draws a fill in background while the app is resizing in areas where the app
@@ -49,6 +48,7 @@
 
     private final Rect mOldTargetRect = new Rect();
     private final Rect mNewTargetRect = new Rect();
+
     private Choreographer mChoreographer;
 
     // Cached size values from the last render for the case that the view hierarchy is gone
@@ -66,15 +66,23 @@
     private Drawable mUserCaptionBackgroundDrawable;
     private Drawable mResizingBackgroundDrawable;
     private ColorDrawable mStatusBarColor;
+    private ColorDrawable mNavigationBarColor;
+    private boolean mOldFullscreen;
+    private boolean mFullscreen;
+    private final Rect mOldSystemInsets = new Rect();
+    private final Rect mOldStableInsets = new Rect();
+    private final Rect mSystemInsets = new Rect();
+    private final Rect mStableInsets = new Rect();
 
     public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
             Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
-            Drawable userCaptionBackgroundDrawable, int statusBarColor) {
+            Drawable userCaptionBackgroundDrawable, int statusBarColor, int navigationBarColor,
+            boolean fullscreen, Rect systemInsets, Rect stableInsets) {
         setName("ResizeFrame");
 
         mRenderer = renderer;
         onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable,
-                userCaptionBackgroundDrawable, statusBarColor);
+                userCaptionBackgroundDrawable, statusBarColor, navigationBarColor);
 
         // Create a render node for the content and frame backdrop
         // which can be resized independently from the content.
@@ -84,8 +92,14 @@
 
         // Set the initial bounds and draw once so that we do not get a broken frame.
         mTargetRect.set(initialBounds);
+        mFullscreen = fullscreen;
+        mOldFullscreen = fullscreen;
+        mSystemInsets.set(systemInsets);
+        mStableInsets.set(stableInsets);
+        mOldSystemInsets.set(systemInsets);
+        mOldStableInsets.set(stableInsets);
         synchronized (this) {
-            changeWindowSizeLocked(initialBounds);
+            redrawLocked(initialBounds, fullscreen, mSystemInsets, mStableInsets);
         }
 
         // Kick off our draw thread.
@@ -94,7 +108,7 @@
 
     void onResourcesLoaded(DecorView decorView, Drawable resizingBackgroundDrawable,
             Drawable captionBackgroundDrawableDrawable, Drawable userCaptionBackgroundDrawable,
-            int statusBarColor) {
+            int statusBarColor, int navigationBarColor) {
         mDecorView = decorView;
         mResizingBackgroundDrawable = resizingBackgroundDrawable;
         mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable;
@@ -108,6 +122,12 @@
         } else {
             mStatusBarColor = null;
         }
+        if (navigationBarColor != 0) {
+            mNavigationBarColor = new ColorDrawable(navigationBarColor);
+            addSystemBarNodeIfNeeded();
+        } else {
+            mNavigationBarColor = null;
+        }
     }
 
     private void addSystemBarNodeIfNeeded() {
@@ -119,13 +139,22 @@
     }
 
     /**
-     * Call this function asynchronously when the window size has been changed. The change will
-     * be picked up once per frame and the frame will be re-rendered accordingly.
+     * Call this function asynchronously when the window size has been changed or when the insets
+     * have changed or whether window switched between a fullscreen or non-fullscreen layout.
+     * The change will be picked up once per frame and the frame will be re-rendered accordingly.
+     *
      * @param newTargetBounds The new target bounds.
+     * @param fullscreen Whether the window is currently drawing in fullscreen.
+     * @param systemInsets The current visible system insets for the window.
+     * @param stableInsets The stable insets for the window.
      */
-    public void setTargetRect(Rect newTargetBounds) {
+    public void setTargetRect(Rect newTargetBounds, boolean fullscreen, Rect systemInsets,
+            Rect stableInsets) {
         synchronized (this) {
+            mFullscreen = fullscreen;
             mTargetRect.set(newTargetBounds);
+            mSystemInsets.set(systemInsets);
+            mStableInsets.set(stableInsets);
             // Notify of a bounds change.
             pingRenderLocked();
         }
@@ -204,16 +233,23 @@
                 return;
             }
             mNewTargetRect.set(mTargetRect);
-            if (!mNewTargetRect.equals(mOldTargetRect) || mReportNextDraw) {
+            if (!mNewTargetRect.equals(mOldTargetRect)
+                    || mOldFullscreen != mFullscreen
+                    || !mStableInsets.equals(mOldStableInsets)
+                    || !mSystemInsets.equals(mOldSystemInsets)
+                    || mReportNextDraw) {
+                mOldFullscreen = mFullscreen;
                 mOldTargetRect.set(mNewTargetRect);
-                changeWindowSizeLocked(mNewTargetRect);
+                mOldSystemInsets.set(mSystemInsets);
+                mOldStableInsets.set(mStableInsets);
+                redrawLocked(mNewTargetRect, mFullscreen, mSystemInsets, mStableInsets);
             }
         }
     }
 
     /**
      * The content is about to be drawn and we got the location of where it will be shown.
-     * If a "changeWindowSizeLocked" call has already been processed, we will re-issue the call
+     * If a "redrawLocked" call has already been processed, we will re-issue the call
      * if the previous call was ignored since the size was unknown.
      * @param xOffset The x offset where the content is drawn to.
      * @param yOffset The y offset where the content is drawn to.
@@ -235,8 +271,8 @@
                     mLastYOffset,
                     mLastXOffset + mLastContentWidth,
                     mLastYOffset + mLastCaptionHeight + mLastContentHeight);
-            // If this was the first call and changeWindowSizeLocked got already called prior
-            // to us, we should re-issue a changeWindowSizeLocked now.
+            // If this was the first call and redrawLocked got already called prior
+            // to us, we should re-issue a redrawLocked now.
             return firstCall
                     && (mLastCaptionHeight != 0 || !mDecorView.isShowingCaption());
         }
@@ -251,16 +287,20 @@
     }
 
     /**
-     * Resizing the frame to fit the new window size.
+     * Redraws the background, the caption and the system inset backgrounds if something changed.
+     *
      * @param newBounds The window bounds which needs to be drawn.
+     * @param fullscreen Whether the window is currently drawing in fullscreen.
+     * @param systemInsets The current visible system insets for the window.
+     * @param stableInsets The stable insets for the window.
      */
-    private void changeWindowSizeLocked(Rect newBounds) {
+    private void redrawLocked(Rect newBounds, boolean fullscreen, Rect systemInsets,
+            Rect stableInsets) {
 
         // While a configuration change is taking place the view hierarchy might become
         // inaccessible. For that case we remember the previous metrics to avoid flashes.
         // Note that even when there is no visible caption, the caption child will exist.
         final int captionHeight = mDecorView.getCaptionHeight();
-        final int statusBarHeight = mDecorView.getStatusBarHeight();
 
         // The caption height will probably never dynamically change while we are resizing.
         // Once set to something other then 0 it should be kept that way.
@@ -289,22 +329,20 @@
         DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
         final Drawable drawable = mUserCaptionBackgroundDrawable != null
                 ? mUserCaptionBackgroundDrawable : mCaptionBackgroundDrawable;
-        drawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
-        drawable.draw(canvas);
+
+        if (drawable != null) {
+            drawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
+            drawable.draw(canvas);
+        }
 
         // The backdrop: clear everything with the background. Clipping is done elsewhere.
-        mResizingBackgroundDrawable.setBounds(0, mLastCaptionHeight, left + width, top + height);
-        mResizingBackgroundDrawable.draw(canvas);
+        if (mResizingBackgroundDrawable != null) {
+            mResizingBackgroundDrawable.setBounds(0, mLastCaptionHeight, left + width, top + height);
+            mResizingBackgroundDrawable.draw(canvas);
+        }
         mFrameAndBackdropNode.end(canvas);
 
-        if (mSystemBarBackgroundNode != null && mStatusBarColor != null) {
-            canvas = mSystemBarBackgroundNode.start(width, height);
-            mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
-            mStatusBarColor.setBounds(0, 0, left + width, statusBarHeight);
-            mStatusBarColor.draw(canvas);
-            mSystemBarBackgroundNode.end(canvas);
-            mRenderer.drawRenderNode(mSystemBarBackgroundNode);
-        }
+        drawColorViews(left, top, width, height, fullscreen, systemInsets, stableInsets);
 
         // We need to render the node explicitly
         mRenderer.drawRenderNode(mFrameAndBackdropNode);
@@ -312,6 +350,39 @@
         reportDrawIfNeeded();
     }
 
+    private void drawColorViews(int left, int top, int width, int height,
+            boolean fullscreen, Rect systemInsets, Rect stableInsets) {
+        if (mSystemBarBackgroundNode == null) {
+            return;
+        }
+        DisplayListCanvas canvas = mSystemBarBackgroundNode.start(width, height);
+        mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
+        final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
+        final int bottomInset = DecorView.getColorViewBottomInset(stableInsets.bottom,
+                systemInsets.bottom);
+        final int rightInset = DecorView.getColorViewRightInset(stableInsets.right,
+                systemInsets.right);
+        if (mStatusBarColor != null) {
+            mStatusBarColor.setBounds(0, 0, left + width, topInset);
+            mStatusBarColor.draw(canvas);
+        }
+
+        // We only want to draw the navigation bar if our window is currently fullscreen because we
+        // don't want the navigation bar background be moving around when resizing in docked mode.
+        // However, we need it for the transitions into/out of docked mode.
+        if (mNavigationBarColor != null && fullscreen) {
+            final int size = DecorView.getNavBarSize(bottomInset, rightInset);
+            if (DecorView.isNavBarToRightEdge(bottomInset, rightInset)) {
+                mNavigationBarColor.setBounds(width - size, 0, width, height);
+            } else {
+                mNavigationBarColor.setBounds(0, height - size, width, height);
+            }
+            mNavigationBarColor.draw(canvas);
+        }
+        mSystemBarBackgroundNode.end(canvas);
+        mRenderer.drawRenderNode(mSystemBarBackgroundNode);
+    }
+
     /** Notify view root that a frame has been drawn by us, if it has requested so. */
     private void reportDrawIfNeeded() {
         if (mReportNextDraw) {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 36009dc..d4ada95 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -205,6 +205,9 @@
     private float mAvailableWidth;
 
     String mLogTag = TAG;
+    private final Rect mFloatingInsets = new Rect();
+    private boolean mApplyFloatingVerticalInsets = false;
+    private boolean mApplyFloatingHorizontalInsets = false;
 
     DecorView(Context context, int featureId, PhoneWindow window,
             WindowManager.LayoutParams params) {
@@ -567,6 +570,7 @@
         final int heightMode = getMode(heightMeasureSpec);
 
         boolean fixedWidth = false;
+        mApplyFloatingHorizontalInsets = false;
         if (widthMode == AT_MOST) {
             final TypedValue tvw = isPortrait ? mWindow.mFixedWidthMinor : mWindow.mFixedWidthMajor;
             if (tvw != null && tvw.type != TypedValue.TYPE_NULL) {
@@ -584,10 +588,16 @@
                     widthMeasureSpec = MeasureSpec.makeMeasureSpec(
                             Math.min(w, widthSize), EXACTLY);
                     fixedWidth = true;
+                } else {
+                    widthMeasureSpec = MeasureSpec.makeMeasureSpec(
+                            widthMeasureSpec - mFloatingInsets.left - mFloatingInsets.right,
+                            AT_MOST);
+                    mApplyFloatingHorizontalInsets = true;
                 }
             }
         }
 
+        mApplyFloatingVerticalInsets = false;
         if (heightMode == AT_MOST) {
             final TypedValue tvh = isPortrait ? mWindow.mFixedHeightMajor
                     : mWindow.mFixedHeightMinor;
@@ -601,10 +611,14 @@
                     h = 0;
                 }
                 if (DEBUG_MEASURE) Log.d(mLogTag, "Fixed height: " + h);
+                final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
                 if (h > 0) {
-                    final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
                     heightMeasureSpec = MeasureSpec.makeMeasureSpec(
                             Math.min(h, heightSize), EXACTLY);
+                } else if ((mWindow.getAttributes().flags & FLAG_FULLSCREEN) == 0) {
+                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                            heightSize - mFloatingInsets.top - mFloatingInsets.bottom, AT_MOST);
+                    mApplyFloatingVerticalInsets = true;
                 }
             }
         }
@@ -672,6 +686,12 @@
         if (mOutsets.top > 0) {
             offsetTopAndBottom(-mOutsets.top);
         }
+        if (mApplyFloatingVerticalInsets) {
+            offsetTopAndBottom(mFloatingInsets.top);
+        }
+        if (mApplyFloatingHorizontalInsets) {
+            offsetLeftAndRight(mFloatingInsets.left);
+        }
 
         // If the application changed its SystemUI metrics, we might also have to adapt
         // our shadow elevation.
@@ -868,6 +888,25 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        final WindowManager.LayoutParams attrs = mWindow.getAttributes();
+        mFloatingInsets.setEmpty();
+        if ((attrs.flags & FLAG_FULLSCREEN) == 0) {
+            // For dialog windows we want to make sure they don't go over the status bar or nav bar.
+            // We consume the system insets and we will reuse them later during the measure phase.
+            // We allow the app to ignore this and handle insets itself by using FLAG_FULLSCREEN.
+            if (attrs.height == WindowManager.LayoutParams.WRAP_CONTENT) {
+                mFloatingInsets.top = insets.getSystemWindowInsetTop();
+                mFloatingInsets.bottom = insets.getSystemWindowInsetBottom();
+                insets = insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), 0,
+                        insets.getSystemWindowInsetRight(), 0);
+            }
+            if (mWindow.getAttributes().width == WindowManager.LayoutParams.WRAP_CONTENT) {
+                mFloatingInsets.left = insets.getSystemWindowInsetTop();
+                mFloatingInsets.right = insets.getSystemWindowInsetBottom();
+                insets = insets.replaceSystemWindowInsets(0, insets.getSystemWindowInsetTop(),
+                        0, insets.getSystemWindowInsetBottom());
+            }
+        }
         mFrameOffsets.set(insets.getSystemWindowInsets());
         insets = updateColorViews(insets, true /* animate */);
         insets = updateStatusGuard(insets);
@@ -883,6 +922,26 @@
         return false;
     }
 
+    static int getColorViewTopInset(int stableTop, int systemTop) {
+        return Math.min(stableTop, systemTop);
+    }
+
+    static int getColorViewBottomInset(int stableBottom, int systemBottom) {
+        return Math.min(stableBottom, systemBottom);
+    }
+
+    static int getColorViewRightInset(int stableRight, int systemRight) {
+        return Math.min(stableRight, systemRight);
+    }
+
+    static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
+        return bottomInset == 0 && rightInset > 0;
+    }
+
+    static int getNavBarSize(int bottomInset, int rightInset) {
+        return isNavBarToRightEdge(bottomInset, rightInset) ? rightInset : bottomInset;
+    }
+
     WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
         WindowManager.LayoutParams attrs = mWindow.getAttributes();
         int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
@@ -894,11 +953,11 @@
             mLastWindowFlags = attrs.flags;
 
             if (insets != null) {
-                mLastTopInset = Math.min(insets.getStableInsetTop(),
+                mLastTopInset = getColorViewTopInset(insets.getStableInsetTop(),
                         insets.getSystemWindowInsetTop());
-                mLastBottomInset = Math.min(insets.getStableInsetBottom(),
+                mLastBottomInset = getColorViewBottomInset(insets.getStableInsetBottom(),
                         insets.getSystemWindowInsetBottom());
-                mLastRightInset = Math.min(insets.getStableInsetRight(),
+                mLastRightInset = getColorViewRightInset(insets.getStableInsetRight(),
                         insets.getSystemWindowInsetRight());
 
                 // Don't animate if the presence of stable insets has changed, because that
@@ -917,8 +976,8 @@
                 mLastHasRightStableInset = hasRightStableInset;
             }
 
-            boolean navBarToRightEdge = mLastBottomInset == 0 && mLastRightInset > 0;
-            int navBarSize = navBarToRightEdge ? mLastRightInset : mLastBottomInset;
+            boolean navBarToRightEdge = isNavBarToRightEdge(mLastBottomInset, mLastRightInset);
+            int navBarSize = getNavBarSize(mLastBottomInset, mLastRightInset);
             updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
                     mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge,
                     0 /* rightInset */, animate && !disallowAnimate, false /* force */);
@@ -1002,14 +1061,14 @@
      */
     private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
             int size, boolean verticalBar, int rightMargin, boolean animate, boolean force) {
-        state.present = size > 0 && (sysUiVis & state.systemUiHideFlag) == 0
+        state.present = (sysUiVis & state.systemUiHideFlag) == 0
                 && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
                 && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
                         || force);
         boolean show = state.present
                 && (color & Color.BLACK) != 0
                 && ((mWindow.getAttributes().flags & state.translucentFlag) == 0  || force);
-        boolean showView = show && !isResizing();
+        boolean showView = show && !isResizing() && size > 0;
 
         boolean visibilityChanged = false;
         View view = state.view;
@@ -1633,7 +1692,8 @@
             loadBackgroundDrawablesIfNeeded();
             mBackdropFrameRenderer.onResourcesLoaded(
                     this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
-                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState));
+                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
+                    getCurrentColor(mNavigationColorViewState));
         }
 
         mDecorCaptionView = createDecorCaptionView(inflater);
@@ -1815,14 +1875,16 @@
     }
 
     @Override
-    public void onWindowSizeIsChanging(Rect newBounds) {
+    public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
+            Rect stableInsets) {
         if (mBackdropFrameRenderer != null) {
-            mBackdropFrameRenderer.setTargetRect(newBounds);
+            mBackdropFrameRenderer.setTargetRect(newBounds, fullscreen, systemInsets, stableInsets);
         }
     }
 
     @Override
-    public void onWindowDragResizeStart(Rect initialBounds) {
+    public void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen, Rect systemInsets,
+            Rect stableInsets) {
         if (mWindow.isDestroyed()) {
             // If the owner's window is gone, we should not be able to come here anymore.
             releaseThreadedRenderer();
@@ -1836,7 +1898,9 @@
             loadBackgroundDrawablesIfNeeded();
             mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
                     initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
-                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState));
+                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
+                    getCurrentColor(mNavigationColorViewState), fullscreen, systemInsets,
+                    stableInsets);
 
             // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
             // If we want to get the shadow shown while resizing, we would need to elevate a new
@@ -1932,10 +1996,6 @@
         return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
     }
 
-    int getStatusBarHeight() {
-        return mStatusColorViewState.view != null ? mStatusColorViewState.view.getHeight() : 0;
-    }
-
     /**
      * Converts a DIP measure into physical pixels.
      * @param dip The dip value.
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index a38139f..597c522 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -58,6 +58,7 @@
     private final Rect mInsets = new Rect();
     private final int mSnapMode;
     private final float mFixedRatio;
+    private boolean mIsHorizontalDivision;
 
     /** The first target which is still splitting the screen */
     private final SnapTarget mFirstSplitTarget;
@@ -78,6 +79,7 @@
         mDividerSize = dividerSize;
         mDisplayWidth = displayWidth;
         mDisplayHeight = displayHeight;
+        mIsHorizontalDivision = isHorizontalDivision;
         mInsets.set(insets);
         mSnapMode = res.getInteger(
                 com.android.internal.R.integer.config_dockedStackDividerSnapMode);
@@ -130,10 +132,12 @@
 
     public float calculateDismissingFraction(int position) {
         if (position < mFirstSplitTarget.position) {
-            return 1f - (float) position / mFirstSplitTarget.position;
+            return 1f - (float) (position - getStartInset())
+                    / (mFirstSplitTarget.position - getStartInset());
         } else if (position > mLastSplitTarget.position) {
             return (float) (position - mLastSplitTarget.position)
-                    / (mDismissEndTarget.position - mLastSplitTarget.position);
+                    / (mDismissEndTarget.position - getEndInset()
+                            - mLastSplitTarget.position - mDividerSize);
         }
         return 0f;
     }
@@ -167,6 +171,22 @@
         return mDismissEndTarget;
     }
 
+    private int getStartInset() {
+        if (mIsHorizontalDivision) {
+            return mInsets.top;
+        } else {
+            return mInsets.left;
+        }
+    }
+
+    private int getEndInset() {
+        if (mIsHorizontalDivision) {
+            return mInsets.bottom;
+        } else {
+            return mInsets.right;
+        }
+    }
+
     private SnapTarget snap(int position, boolean hardDismiss) {
         int minIndex = -1;
         float minDistance = Float.MAX_VALUE;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 19ed11a..7637eec 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -675,7 +675,7 @@
     }
 
     @Override
-    public void onMultiWindowModeChanged() {
+    public void onMultiWindowChanged() {
         if (mDecor != null) {
             mDecor.onConfigurationChanged(getContext().getResources().getConfiguration());
         }
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 3854923..6e374e2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.statusbar;
 
+import android.content.ComponentName;
 import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
 
@@ -88,4 +89,8 @@
      * Picture-in-picture overlay menu will be shown instead otherwise.
      */
     void requestTvPictureInPicture();
+
+    void addQsTile(in ComponentName tile);
+    void remQsTile(in ComponentName tile);
+    void clickQsTile(in ComponentName tile);
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index a6fd9f9..bec18ec 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.statusbar;
 
+import android.content.ComponentName;
 import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
 
@@ -103,4 +104,8 @@
      * Picture-in-picture overlay menu will be shown instead otherwise.
      */
     void requestTvPictureInPicture();
+
+    void addTile(in ComponentName tile);
+    void remTile(in ComponentName tile);
+    void clickTile(in ComponentName tile);
 }
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index a502fcc..29a9c8e 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -80,11 +80,15 @@
     private final OnGlobalLayoutListener mGlobalLayoutListener = new OnGlobalLayoutListener() {
         @Override
         public void onGlobalLayout() {
-            if (isShowing()) {
+            // Only move the popup if it's showing and non-modal. We don't want
+            // to be moving around the only interactive window, since there's a
+            // good chance the user is interacting with it.
+            if (isShowing() && mShowingMenus.size() > 0
+                    && !mShowingMenus.get(0).window.isModal()) {
                 final View anchor = mShownAnchorView;
                 if (anchor == null || !anchor.isShown()) {
                     dismiss();
-                } else if (isShowing()) {
+                } else {
                     // Recompute window sizes and positions.
                     for (CascadingMenuInfo info : mShowingMenus) {
                         info.window.show();
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 2d4baa2..2cb224e 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -59,11 +59,14 @@
     private final OnGlobalLayoutListener mGlobalLayoutListener = new OnGlobalLayoutListener() {
         @Override
         public void onGlobalLayout() {
-            if (isShowing()) {
+            // Only move the popup if it's showing and non-modal. We don't want
+            // to be moving around the only interactive window, since there's a
+            // good chance the user is interacting with it.
+            if (isShowing() && !mPopup.isModal()) {
                 final View anchor = mShownAnchorView;
                 if (anchor == null || !anchor.isShown()) {
                     dismiss();
-                } else if (isShowing()) {
+                } else {
                     // Recompute window size and position
                     mPopup.show();
                 }
diff --git a/core/java/com/android/internal/widget/AlertDialogLayout.java b/core/java/com/android/internal/widget/AlertDialogLayout.java
new file mode 100644
index 0000000..cc0db51
--- /dev/null
+++ b/core/java/com/android/internal/widget/AlertDialogLayout.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StyleRes;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.internal.R;
+
+/**
+ * Special implementation of linear layout that's capable of laying out alert
+ * dialog components.
+ * <p>
+ * A dialog consists of up to three panels. All panels are optional, and a
+ * dialog may contain only a single panel. The panels are laid out according
+ * to the following guidelines:
+ * <ul>
+ *     <li>topPanel: exactly wrap_content</li>
+ *     <li>contentPanel OR customPanel: at most fill_parent, first priority for
+ *         extra space</li>
+ *     <li>buttonPanel: at least minHeight, at most wrap_content, second
+ *         priority for extra space</li>
+ * </ul>
+ */
+public class AlertDialogLayout extends LinearLayout {
+
+    public AlertDialogLayout(@Nullable Context context) {
+        super(context);
+    }
+
+    public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs,
+            @AttrRes int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs,
+            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (!tryOnMeasure(widthMeasureSpec, heightMeasureSpec)) {
+            // Failed to perform custom measurement, let superclass handle it.
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+    }
+
+    private boolean tryOnMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        View topPanel = null;
+        View buttonPanel = null;
+        View middlePanel = null;
+
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getVisibility() == View.GONE) {
+                continue;
+            }
+
+            final int id = child.getId();
+            switch (id) {
+                case R.id.topPanel:
+                    topPanel = child;
+                    break;
+                case R.id.buttonPanel:
+                    buttonPanel = child;
+                    break;
+                case R.id.contentPanel:
+                case R.id.customPanel:
+                    if (middlePanel != null) {
+                        // Both the content and custom are visible. Abort!
+                        return false;
+                    }
+                    middlePanel = child;
+                    break;
+                default:
+                    // Unknown top-level child. Abort!
+                    return false;
+            }
+        }
+
+        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+        // Treat all panel widths as MATCH_PARENT
+        // by translating AT_MOST to EXACTLY.
+        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        if (widthMode == MeasureSpec.AT_MOST) {
+            final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+            widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
+        }
+
+        int childState = 0;
+        int usedHeight = getPaddingTop() + getPaddingBottom();
+
+        if (topPanel != null) {
+            topPanel.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
+
+            usedHeight += topPanel.getMeasuredHeight();
+            childState = combineMeasuredStates(childState, topPanel.getMeasuredState());
+        }
+
+        int buttonHeight = 0;
+        int buttonWantsHeight = 0;
+        if (buttonPanel != null) {
+            buttonPanel.measure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
+            buttonHeight = resolveMinimumHeight(buttonPanel);
+            buttonWantsHeight = buttonPanel.getMeasuredHeight() - buttonHeight;
+
+            usedHeight += buttonHeight;
+            childState = combineMeasuredStates(childState, buttonPanel.getMeasuredState());
+        }
+
+        int middleHeight = 0;
+        if (middlePanel != null) {
+            final int childHeightSpec;
+            if (heightMode == MeasureSpec.UNSPECIFIED) {
+                childHeightSpec = MeasureSpec.UNSPECIFIED;
+            } else {
+                childHeightSpec = MeasureSpec.makeMeasureSpec(
+                        Math.max(0, heightSize - usedHeight), heightMode);
+            }
+
+            middlePanel.measure(widthMeasureSpec, childHeightSpec);
+            middleHeight = middlePanel.getMeasuredHeight();
+
+            usedHeight += middleHeight;
+            childState = combineMeasuredStates(childState, middlePanel.getMeasuredState());
+        }
+
+        int remainingHeight = heightSize - usedHeight;
+
+        // Time for the "real" button measure pass. If we have remaining space,
+        // make the button pane bigger up to its target height. Otherwise,
+        // just remeasure the button at whatever height it needs.
+        if (buttonPanel != null) {
+            usedHeight -= buttonHeight;
+
+            final int heightToGive = Math.min(remainingHeight, buttonWantsHeight);
+            if (heightToGive > 0) {
+                remainingHeight -= heightToGive;
+                buttonHeight += heightToGive;
+            }
+
+            final int childHeightSpec = MeasureSpec.makeMeasureSpec(
+                    buttonHeight, MeasureSpec.EXACTLY);
+            buttonPanel.measure(widthMeasureSpec, childHeightSpec);
+
+            usedHeight += buttonPanel.getMeasuredHeight();
+            childState = combineMeasuredStates(childState, buttonPanel.getMeasuredState());
+        }
+
+        // If we still have remaining space, make the middle pane bigger up
+        // to the maximum height.
+        if (middlePanel != null && remainingHeight > 0) {
+            usedHeight -= middleHeight;
+
+            final int heightToGive = remainingHeight;
+            remainingHeight -= heightToGive;
+            middleHeight += heightToGive;
+
+            // Pass the same height mode as we're using for the dialog itself.
+            // If it's EXACTLY, then the middle pane MUST use the entire
+            // height.
+            final int childHeightSpec = MeasureSpec.makeMeasureSpec(
+                    middleHeight, heightMode);
+            middlePanel.measure(widthMeasureSpec, childHeightSpec);
+
+            usedHeight += middlePanel.getMeasuredHeight();
+            childState = combineMeasuredStates(childState, middlePanel.getMeasuredState());
+        }
+
+        // Compute desired width as maximum child width.
+        int maxWidth = 0;
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE) {
+                maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
+            }
+        }
+        maxWidth += getPaddingLeft() + getPaddingRight();
+
+        final int widthSizeAndState = resolveSizeAndState(maxWidth, widthMeasureSpec, childState);
+        final int heightSizeAndState = resolveSizeAndState(usedHeight, heightMeasureSpec, 0);
+        setMeasuredDimension(widthSizeAndState, heightSizeAndState);
+        return true;
+    }
+
+    /**
+     * Attempts to resolve the minimum height of a view.
+     * <p>
+     * If the view doesn't have a minimum height set and only contains a single
+     * child, attempts to resolve the minimum height of the child view.
+     *
+     * @param v the view whose minimum height to resolve
+     * @return the minimum height
+     */
+    private int resolveMinimumHeight(View v) {
+        final int minHeight = v.getMinimumHeight();
+        if (minHeight > 0) {
+            return minHeight;
+        }
+
+        if (v instanceof ViewGroup) {
+            final ViewGroup vg = (ViewGroup) v;
+            if (vg.getChildCount() == 1) {
+                return resolveMinimumHeight(vg.getChildAt(0));
+            }
+        }
+
+        return 0;
+    }
+}
diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java
index a694aca..6a0edef 100644
--- a/core/java/com/android/internal/widget/ButtonBarLayout.java
+++ b/core/java/com/android/internal/widget/ButtonBarLayout.java
@@ -30,15 +30,19 @@
  * orientation when it can't fit its child views horizontally.
  */
 public class ButtonBarLayout extends LinearLayout {
-    // Whether to allow vertically stacked button bars. This is disabled for
-    // configurations with a small (e.g. less than 320dp) screen height. -->
+    /** Minimum screen height required for button stacking. */
     private static final int ALLOW_STACKING_MIN_HEIGHT_DP = 320;
 
+    /** Amount of the second button to "peek" above the fold when stacked. */
+    private static final int PEEK_BUTTON_DP = 16;
+
     /** Whether the current configuration allows stacking. */
     private boolean mAllowStacking;
 
     private int mLastWidthSize = -1;
 
+    private int mMinimumHeight = 0;
+
     public ButtonBarLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -105,6 +109,44 @@
         if (needsRemeasure) {
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         }
+
+        // Compute minimum height such that, when stacked, some portion of the
+        // second button is visible.
+        int minHeight = 0;
+        final int firstVisible = getNextVisibleChildIndex(0);
+        if (firstVisible >= 0) {
+            final View firstButton = getChildAt(firstVisible);
+            final LayoutParams firstParams = (LayoutParams) firstButton.getLayoutParams();
+            minHeight += getPaddingTop() + firstButton.getMeasuredHeight()
+                    + firstParams.topMargin + firstParams.bottomMargin;
+            if (isStacked()) {
+                final int secondVisible = getNextVisibleChildIndex(firstVisible + 1);
+                if (secondVisible >= 0) {
+                    minHeight += getChildAt(secondVisible).getPaddingTop()
+                            + PEEK_BUTTON_DP * getResources().getDisplayMetrics().density;
+                }
+            } else {
+                minHeight += getPaddingBottom();
+            }
+        }
+
+        if (getMinimumHeight() != minHeight) {
+            setMinimumHeight(minHeight);
+        }
+    }
+
+    private int getNextVisibleChildIndex(int index) {
+        for (int i = index, count = getChildCount(); i < count; i++) {
+            if (getChildAt(i).getVisibility() == View.VISIBLE) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    @Override
+    public int getMinimumHeight() {
+        return Math.max(mMinimumHeight, super.getMinimumHeight());
     }
 
     private void setStacked(boolean stacked) {
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 480d806..ce03bb8 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -21,9 +21,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
-import android.content.ComponentCallbacks;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.Point;
@@ -42,6 +40,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.MeasureSpec;
+import android.view.View.OnLayoutChangeListener;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.Window;
@@ -90,6 +89,7 @@
             };
 
     private final Context mContext;
+    private final Window mWindow;
     private final FloatingToolbarPopup mPopup;
 
     private final Rect mContentRect = new Rect();
@@ -102,26 +102,31 @@
     private int mSuggestedWidth;
     private boolean mWidthChanged = true;
 
-    private final ComponentCallbacks mOrientationChangeHandler = new ComponentCallbacks() {
+    private final OnLayoutChangeListener mOrientationChangeHandler = new OnLayoutChangeListener() {
+
+        private final Rect mNewRect = new Rect();
+        private final Rect mOldRect = new Rect();
+
         @Override
-        public void onConfigurationChanged(Configuration newConfig) {
-            if (mPopup.isShowing() && mPopup.viewPortHasChanged()) {
+        public void onLayoutChange(
+                View view,
+                int newLeft, int newRight, int newTop, int newBottom,
+                int oldLeft, int oldRight, int oldTop, int oldBottom) {
+            mNewRect.set(newLeft, newRight, newTop, newBottom);
+            mOldRect.set(oldLeft, oldRight, oldTop, oldBottom);
+            if (mPopup.isShowing() && !mNewRect.equals(mOldRect)) {
                 mWidthChanged = true;
                 updateLayout();
             }
         }
-
-        @Override
-        public void onLowMemory() {}
     };
 
     /**
      * Initializes a floating toolbar.
      */
     public FloatingToolbar(Context context, Window window) {
-        Preconditions.checkNotNull(context);
-        Preconditions.checkNotNull(window);
-        mContext = applyDefaultTheme(context);
+        mContext = applyDefaultTheme(Preconditions.checkNotNull(context));
+        mWindow = Preconditions.checkNotNull(window);
         mPopup = new FloatingToolbarPopup(mContext, window.getDecorView());
     }
 
@@ -179,21 +184,8 @@
      * Shows this floating toolbar.
      */
     public FloatingToolbar show() {
-        mContext.unregisterComponentCallbacks(mOrientationChangeHandler);
-        mContext.registerComponentCallbacks(mOrientationChangeHandler);
-        List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu);
-        if (!isCurrentlyShowing(menuItems) || mWidthChanged) {
-            mPopup.dismiss();
-            mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
-            mShowingMenuItems = getShowingMenuItemsReferences(menuItems);
-        }
-        if (!mPopup.isShowing()) {
-            mPopup.show(mContentRect);
-        } else if (!mPreviousContentRect.equals(mContentRect)) {
-            mPopup.updateCoordinates(mContentRect);
-        }
-        mWidthChanged = false;
-        mPreviousContentRect.set(mContentRect);
+        registerOrientationHandler();
+        doShow();
         return this;
     }
 
@@ -203,8 +195,7 @@
      */
     public FloatingToolbar updateLayout() {
         if (mPopup.isShowing()) {
-            // show() performs all the logic we need here.
-            show();
+            doShow();
         }
         return this;
     }
@@ -213,7 +204,7 @@
      * Dismisses this floating toolbar.
      */
     public void dismiss() {
-        mContext.unregisterComponentCallbacks(mOrientationChangeHandler);
+        unregisterOrientationHandler();
         mPopup.dismiss();
     }
 
@@ -239,6 +230,22 @@
         return mPopup.isHidden();
     }
 
+    private void doShow() {
+        List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu);
+        if (!isCurrentlyShowing(menuItems) || mWidthChanged) {
+            mPopup.dismiss();
+            mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
+            mShowingMenuItems = getShowingMenuItemsReferences(menuItems);
+        }
+        if (!mPopup.isShowing()) {
+            mPopup.show(mContentRect);
+        } else if (!mPreviousContentRect.equals(mContentRect)) {
+            mPopup.updateCoordinates(mContentRect);
+        }
+        mWidthChanged = false;
+        mPreviousContentRect.set(mContentRect);
+    }
+
     /**
      * Returns true if this floating toolbar is currently showing the specified menu items.
      */
@@ -278,6 +285,15 @@
         return references;
     }
 
+    private void registerOrientationHandler() {
+        unregisterOrientationHandler();
+        mWindow.getDecorView().addOnLayoutChangeListener(mOrientationChangeHandler);
+    }
+
+    private void unregisterOrientationHandler() {
+        mWindow.getDecorView().removeOnLayoutChangeListener(mOrientationChangeHandler);
+    }
+
 
     /**
      * A popup window used by the floating toolbar.
@@ -306,7 +322,7 @@
         /* View components */
         private final ViewGroup mContentContainer;  // holds all contents.
         private final ViewGroup mMainPanel;  // holds menu items that are initially displayed.
-        private final ListView mOverflowPanel;  // holds menu items hidden in the overflow.
+        private final OverflowPanel mOverflowPanel;  // holds menu items hidden in the overflow.
         private final ImageButton mOverflowButton;  // opens/closes the overflow.
         /* overflow button drawables. */
         private final Drawable mArrow;
@@ -879,6 +895,7 @@
 
         private void setPanelsStatesAtRestingPosition() {
             mOverflowButton.setEnabled(true);
+            mOverflowPanel.awakenScrollBars();
 
             if (mIsOverflowOpen) {
                 // Set open state.
@@ -1012,11 +1029,6 @@
             mParent.getWindowVisibleDisplayFrame(mViewPortOnScreen);
         }
 
-        private boolean viewPortHasChanged() {
-            mParent.getWindowVisibleDisplayFrame(mTmpRect);
-            return !mTmpRect.equals(mViewPortOnScreen);
-        }
-
         private int getAdjustedToolbarWidth(int suggestedWidth) {
             int width = suggestedWidth;
             refreshViewPort();
@@ -1322,27 +1334,8 @@
             return overflowButton;
         }
 
-        private ListView createOverflowPanel() {
-            final ListView overflowPanel = new ListView(FloatingToolbarPopup.this.mContext) {
-                @Override
-                protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-                    // Update heightMeasureSpec to make sure that this view is not clipped
-                    // as we offset it's coordinates with respect to it's parent.
-                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(
-                            mOverflowPanelSize.getHeight() - mOverflowButtonSize.getHeight(),
-                            MeasureSpec.EXACTLY);
-                    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-                }
-
-                @Override
-                public boolean dispatchTouchEvent(MotionEvent ev) {
-                    if (isOverflowAnimating()) {
-                        // Eat the touch event.
-                        return true;
-                    }
-                    return super.dispatchTouchEvent(ev);
-                }
-            };
+        private OverflowPanel createOverflowPanel() {
+            final OverflowPanel overflowPanel = new OverflowPanel(this);
             overflowPanel.setLayoutParams(new ViewGroup.LayoutParams(
                     ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
             overflowPanel.setDivider(null);
@@ -1453,6 +1446,43 @@
         }
 
         /**
+         * A custom ListView for the overflow panel.
+         */
+        private static final class OverflowPanel extends ListView {
+
+            private final FloatingToolbarPopup mPopup;
+
+            OverflowPanel(FloatingToolbarPopup popup) {
+                super(Preconditions.checkNotNull(popup).mContext);
+                this.mPopup = popup;
+            }
+
+            @Override
+            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+                // Update heightMeasureSpec to make sure that this view is not clipped
+                // as we offset it's coordinates with respect to it's parent.
+                int height = mPopup.mOverflowPanelSize.getHeight()
+                        - mPopup.mOverflowButtonSize.getHeight();
+                heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
+                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            }
+
+            @Override
+            public boolean dispatchTouchEvent(MotionEvent ev) {
+                if (mPopup.isOverflowAnimating()) {
+                    // Eat the touch event.
+                    return true;
+                }
+                return super.dispatchTouchEvent(ev);
+            }
+
+            @Override
+            protected boolean awakenScrollBars() {
+                return super.awakenScrollBars();
+            }
+        }
+
+        /**
          * A custom interpolator used for various floating toolbar animations.
          */
         private static final class LogAccelerateInterpolator implements Interpolator {
@@ -1663,4 +1693,4 @@
         a.recycle();
         return new ContextThemeWrapper(originalContext, themeId);
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index ba456f9..e239852 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -883,6 +883,15 @@
     }
 
     /**
+     * Determine if the device is file encrypted
+     * @return true if device is file encrypted
+     */
+    public static boolean isFileEncryptionEnabled() {
+        final String status = SystemProperties.get("ro.crypto.type", "");
+        return "file".equalsIgnoreCase(status);
+    }
+
+    /**
      * Clears the encryption password.
      */
     public void clearEncryptionPassword() {
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 9211eaa..96492e2 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -334,6 +334,7 @@
         mExploreByTouchHelper = new PatternExploreByTouchHelper(this);
         setAccessibilityDelegate(mExploreByTouchHelper);
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        a.recycle();
     }
 
     public CellState[][] getCellStates() {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 8c4683d..1b6b53a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -51,6 +51,7 @@
     android_database_SQLiteConnection.cpp \
     android_database_SQLiteGlobal.cpp \
     android_database_SQLiteDebug.cpp \
+    android_graphics_drawable_AnimatedVectorDrawable.cpp \
     android_graphics_drawable_VectorDrawable.cpp \
     android_view_DisplayEventReceiver.cpp \
     android_view_DisplayListCanvas.cpp \
@@ -184,6 +185,7 @@
     $(LOCAL_PATH)/android/graphics \
     $(LOCAL_PATH)/../../libs/hwui \
     $(LOCAL_PATH)/../../../native/opengl/libs \
+    $(LOCAL_PATH)/../../../native/vulkan/include \
     $(call include-path-for, bluedroid) \
     $(call include-path-for, libhardware)/hardware \
     $(call include-path-for, libhardware_legacy)/hardware_legacy \
@@ -233,6 +235,7 @@
     libEGL \
     libGLESv1_CM \
     libGLESv2 \
+    libvulkan \
     libETC1 \
     libhardware \
     libhardware_legacy \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2e45f8c..223fc1a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -131,6 +131,7 @@
 extern int register_android_graphics_Region(JNIEnv* env);
 extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
 extern int register_android_graphics_Xfermode(JNIEnv* env);
+extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env);
 extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env);
 extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
 extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
@@ -1321,6 +1322,7 @@
     REG_JNI(register_android_graphics_Typeface),
     REG_JNI(register_android_graphics_Xfermode),
     REG_JNI(register_android_graphics_YuvImage),
+    REG_JNI(register_android_graphics_drawable_AnimatedVectorDrawable),
     REG_JNI(register_android_graphics_drawable_VectorDrawable),
     REG_JNI(register_android_graphics_pdf_PdfDocument),
     REG_JNI(register_android_graphics_pdf_PdfEditor),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 80ccb61..43e26b3 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1087,6 +1087,8 @@
     p->writeInt32(density);
 
     if (bitmap.colorType() == kIndex_8_SkColorType) {
+        // The bitmap needs to be locked to access its color table.
+        SkAutoLockPixels alp(bitmap);
         SkColorTable* ctable = bitmap.getColorTable();
         if (ctable != NULL) {
             int count = ctable->count();
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 3d5091a..bd01c73 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -746,10 +746,12 @@
     if (mNeedsCopy) {
         SkPixelRef* recycledPixels = mRecycledBitmap->refPixelRef();
         void* dst = recycledPixels->pixels();
-        size_t dstRowBytes = mRecycledBitmap->rowBytes();
-        size_t bytesToCopy = SkTMin(mRecycledBitmap->info().minRowBytes(),
+        const size_t dstRowBytes = mRecycledBitmap->rowBytes();
+        const size_t bytesToCopy = std::min(mRecycledBitmap->info().minRowBytes(),
                 mSkiaBitmap->info().minRowBytes());
-        for (int y = 0; y < mRecycledBitmap->info().height(); y++) {
+        const int rowsToCopy = std::min(mRecycledBitmap->info().height(),
+                mSkiaBitmap->info().height());
+        for (int y = 0; y < rowsToCopy; y++) {
             memcpy(dst, mSkiaBitmap->getAddr(0, y), bytesToCopy);
             dst = SkTAddOffset<void>(dst, dstRowBytes);
         }
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 35b5016..cf73316 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -510,7 +510,7 @@
 
         size_t glyphCount = end - start;
 
-        if (CC_UNLIKELY(canvas->isHighContrastText())) {
+        if (CC_UNLIKELY(canvas->isHighContrastText() && paint.getAlpha() != 0)) {
             // high contrast draw path
             int color = paint.getColor();
             int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
new file mode 100644
index 0000000..7a3c598
--- /dev/null
+++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "OpenGLRenderer"
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include "core_jni_helpers.h"
+#include "log/log.h"
+
+#include "Animator.h"
+#include "Interpolator.h"
+#include "PropertyValuesAnimatorSet.h"
+#include "PropertyValuesHolder.h"
+#include "VectorDrawable.h"
+
+namespace android {
+using namespace uirenderer;
+using namespace VectorDrawable;
+
+static struct {
+    jclass clazz;
+    jmethodID callOnFinished;
+} gVectorDrawableAnimatorClassInfo;
+
+static JNIEnv* getEnv(JavaVM* vm) {
+    JNIEnv* env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        return 0;
+    }
+    return env;
+}
+
+static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener) {
+    class AnimationListenerBridge : public AnimationListener {
+    public:
+        AnimationListenerBridge(JNIEnv* env, jobject finishListener) {
+            mFinishListener = env->NewGlobalRef(finishListener);
+            env->GetJavaVM(&mJvm);
+        }
+
+        virtual ~AnimationListenerBridge() {
+            if (mFinishListener) {
+                onAnimationFinished(NULL);
+            }
+        }
+
+        virtual void onAnimationFinished(BaseRenderNodeAnimator*) {
+            LOG_ALWAYS_FATAL_IF(!mFinishListener, "Finished listener twice?");
+            JNIEnv* env = getEnv(mJvm);
+            env->CallStaticVoidMethod(
+                    gVectorDrawableAnimatorClassInfo.clazz,
+                    gVectorDrawableAnimatorClassInfo.callOnFinished,
+                    mFinishListener);
+            releaseJavaObject();
+        }
+
+    private:
+        void releaseJavaObject() {
+            JNIEnv* env = getEnv(mJvm);
+            env->DeleteGlobalRef(mFinishListener);
+            mFinishListener = NULL;
+        }
+
+        JavaVM* mJvm;
+        jobject mFinishListener;
+    };
+    return new AnimationListenerBridge(env, finishListener);
+}
+
+static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr,
+        jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount) {
+    PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
+    PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr);
+    Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr);
+    set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount);
+}
+
+static jlong createAnimatorSet(JNIEnv*, jobject) {
+    PropertyValuesAnimatorSet* animatorSet = new PropertyValuesAnimatorSet();
+    return reinterpret_cast<jlong>(animatorSet);
+}
+
+static jlong createGroupPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId,
+        jfloat startValue, jfloat endValue) {
+    VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(nativePtr);
+    GroupPropertyValuesHolder* newHolder = new GroupPropertyValuesHolder(group, propertyId,
+            startValue, endValue);
+    return reinterpret_cast<jlong>(newHolder);
+}
+
+static jlong createPathDataPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jlong startValuePtr,
+        jlong endValuePtr) {
+    VectorDrawable::Path* path = reinterpret_cast<VectorDrawable::Path*>(nativePtr);
+    PathData* startData = reinterpret_cast<PathData*>(startValuePtr);
+    PathData* endData = reinterpret_cast<PathData*>(endValuePtr);
+    PathDataPropertyValuesHolder* newHolder = new PathDataPropertyValuesHolder(path,
+            startData, endData);
+    return reinterpret_cast<jlong>(newHolder);
+}
+
+static jlong createPathColorPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId,
+        int startValue, jint endValue) {
+    VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr);
+    FullPathColorPropertyValuesHolder* newHolder = new FullPathColorPropertyValuesHolder(fullPath,
+            propertyId, startValue, endValue);
+    return reinterpret_cast<jlong>(newHolder);
+}
+
+static jlong createPathPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId,
+        float startValue, jfloat endValue) {
+    VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr);
+    FullPathPropertyValuesHolder* newHolder = new FullPathPropertyValuesHolder(fullPath,
+            propertyId, startValue, endValue);
+    return reinterpret_cast<jlong>(newHolder);
+}
+
+static jlong createRootAlphaPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jfloat startValue,
+        float endValue) {
+    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(nativePtr);
+    RootAlphaPropertyValuesHolder* newHolder = new RootAlphaPropertyValuesHolder(tree,
+            startValue, endValue);
+    return reinterpret_cast<jlong>(newHolder);
+}
+static void setPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr,
+        jfloatArray srcData, jint length) {
+
+    jfloat* propertyData = env->GetFloatArrayElements(srcData, nullptr);
+    PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr);
+    holder->setPropertyDataSource(propertyData, length);
+    env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT);
+}
+static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
+    PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
+    // TODO: keep a ref count in finish listener
+    AnimationListener* listener = createAnimationListener(env, finishListener);
+    set->start(listener);
+}
+
+static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
+    // TODO: implement reverse
+}
+
+static void end(JNIEnv*, jobject, jlong animatorSetPtr) {
+    PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
+    set->end();
+}
+
+static void reset(JNIEnv*, jobject, jlong animatorSetPtr) {
+    PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
+    set->reset();
+}
+
+static const JNINativeMethod gMethods[] = {
+    {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet},
+    {"nAddAnimator", "(JJJJJI)V", (void*)addAnimator},
+    {"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder},
+    {"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder},
+    {"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder},
+    {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder},
+    {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder},
+    {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData},
+    {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)start},
+    {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)reverse},
+    {"nEnd", "!(J)V", (void*)end},
+    {"nReset", "!(J)V", (void*)reset},
+};
+
+const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator";
+int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) {
+    gVectorDrawableAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName);
+    gVectorDrawableAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env,
+            gVectorDrawableAnimatorClassInfo.clazz);
+
+    gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie(
+            env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished",
+            "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V");
+    return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable",
+            gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index 563ec8b..7314fbc 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -32,11 +32,6 @@
     return reinterpret_cast<jlong>(tree);
 }
 
-static void deleteTree(JNIEnv*, jobject, jlong treePtr) {
-    VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
-    delete tree;
-}
-
 static void setTreeViewportSize(JNIEnv*, jobject, jlong treePtr,
         jfloat viewportWidth, jfloat viewportHeight) {
     VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr);
@@ -143,11 +138,6 @@
     return reinterpret_cast<jlong>(newGroup);
 }
 
-static void deleteNode(JNIEnv*, jobject, jlong nodePtr) {
-    VectorDrawable::Node* node = reinterpret_cast<VectorDrawable::Node*>(nodePtr);
-    delete node;
-}
-
 static void setNodeName(JNIEnv* env, jobject, jlong nodePtr, jstring nameStr) {
     VectorDrawable::Node* node = reinterpret_cast<VectorDrawable::Node*>(nodePtr);
     const char* nodeName = env->GetStringUTFChars(nameStr, NULL);
@@ -333,7 +323,6 @@
 
 static const JNINativeMethod gMethods[] = {
         {"nCreateRenderer", "!(J)J", (void*)createTree},
-        {"nDestroyRenderer", "!(J)V", (void*)deleteTree},
         {"nSetRendererViewportSize", "!(JFF)V", (void*)setTreeViewportSize},
         {"nSetRootAlpha", "!(JF)Z", (void*)setRootAlpha},
         {"nGetRootAlpha", "!(J)F", (void*)getRootAlpha},
@@ -352,7 +341,6 @@
         {"nCreateClipPath", "!(J)J", (void*)createClipPath},
         {"nCreateGroup", "!()J", (void*)createEmptyGroup},
         {"nCreateGroup", "!(J)J", (void*)createGroup},
-        {"nDestroy", "!(J)V", (void*)deleteNode},
         {"nSetName", "(JLjava/lang/String;)V", (void*)setNodeName},
         {"nUpdateGroupProperties", "!(JFFFFFFF)V", (void*)updateGroupProperties},
 
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 4842e1b..e39bb1c 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -205,8 +205,8 @@
     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
 
     Sensor const* const* sensorList;
-    size_t count = mgr->getSensorList(&sensorList);
-    if (size_t(index) >= count) {
+    ssize_t count = mgr->getSensorList(&sensorList);
+    if (ssize_t(index) >= count) {
         return false;
     }
 
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 048b3c7..793d132 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -68,6 +68,10 @@
     jfieldID    data;
 } gSoundModelFields;
 
+static const char* const kGenericSoundModelClassPathName =
+                                     "android/hardware/soundtrigger/SoundTrigger$GenericSoundModel";
+static jclass gGenericSoundModelClass;
+
 static const char* const kKeyphraseClassPathName =
                                      "android/hardware/soundtrigger/SoundTrigger$Keyphrase";
 static jclass gKeyphraseClass;
@@ -105,6 +109,11 @@
 static jclass gKeyphraseRecognitionEventClass;
 static jmethodID   gKeyphraseRecognitionEventCstor;
 
+static const char* const kGenericRecognitionEventClassPathName =
+                             "android/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent";
+static jclass gGenericRecognitionEventClass;
+static jmethodID   gGenericRecognitionEventCstor;
+
 static const char* const kKeyphraseRecognitionExtraClassPathName =
                              "android/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra";
 static jclass gKeyphraseRecognitionExtraClass;
@@ -266,6 +275,12 @@
                                 event->capture_preamble_ms, event->trigger_in_data,
                                 jAudioFormat, jData, jExtras);
         env->DeleteLocalRef(jExtras);
+    } else if (event->type == SOUND_MODEL_TYPE_GENERIC) {
+        jEvent = env->NewObject(gGenericRecognitionEventClass, gGenericRecognitionEventCstor,
+                                event->status, event->model, event->capture_available,
+                                event->capture_session, event->capture_delay_ms,
+                                event->capture_preamble_ms, event->trigger_in_data,
+                                jAudioFormat, jData);
     } else {
         jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor,
                                 event->status, event->model, event->capture_available,
@@ -524,6 +539,9 @@
     if (env->IsInstanceOf(jSoundModel, gKeyphraseSoundModelClass)) {
         offset = sizeof(struct sound_trigger_phrase_sound_model);
         type = SOUND_MODEL_TYPE_KEYPHRASE;
+    } else if (env->IsInstanceOf(jSoundModel, gGenericSoundModelClass)) {
+        offset = sizeof(struct sound_trigger_generic_sound_model);
+        type = SOUND_MODEL_TYPE_GENERIC;
     } else {
         offset = sizeof(struct sound_trigger_sound_model);
         type = SOUND_MODEL_TYPE_UNKNOWN;
@@ -631,6 +649,8 @@
             env->DeleteLocalRef(jPhrase);
         }
         env->DeleteLocalRef(jPhrases);
+    } else if (type == SOUND_MODEL_TYPE_GENERIC) {
+        /* No initialization needed */
     }
     status = module->loadSoundModel(memory, &handle);
     ALOGV("loadSoundModel status %d handle %d", status, handle);
@@ -831,6 +851,9 @@
                                                    "Ljava/util/UUID;");
     gSoundModelFields.data = GetFieldIDOrDie(env, soundModelClass, "data", "[B");
 
+    jclass genericSoundModelClass = FindClassOrDie(env, kGenericSoundModelClassPathName);
+    gGenericSoundModelClass = MakeGlobalRefOrDie(env, genericSoundModelClass);
+
     jclass keyphraseClass = FindClassOrDie(env, kKeyphraseClassPathName);
     gKeyphraseClass = MakeGlobalRefOrDie(env, keyphraseClass);
     gKeyphraseFields.id = GetFieldIDOrDie(env, keyphraseClass, "id", "I");
@@ -857,6 +880,11 @@
     gKeyphraseRecognitionEventCstor = GetMethodIDOrDie(env, keyphraseRecognitionEventClass, "<init>",
               "(IIZIIIZLandroid/media/AudioFormat;[B[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V");
 
+    jclass genericRecognitionEventClass = FindClassOrDie(env,
+                                                           kGenericRecognitionEventClassPathName);
+    gGenericRecognitionEventClass = MakeGlobalRefOrDie(env, genericRecognitionEventClass);
+    gGenericRecognitionEventCstor = GetMethodIDOrDie(env, genericRecognitionEventClass, "<init>",
+                                              "(IIZIIIZLandroid/media/AudioFormat;[B)V");
 
     jclass keyRecognitionConfigClass = FindClassOrDie(env, kRecognitionConfigClassPathName);
     gRecognitionConfigClass = MakeGlobalRefOrDie(env, keyRecognitionConfigClass);
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index a6c61de..03c94a6 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -27,13 +27,8 @@
 #include <SkBitmap.h>
 #include <SkRegion.h>
 
-#if HWUI_NEW_OPS
-#include <RecordingCanvas.h>
-typedef android::uirenderer::RecordingCanvas canvas_t;
-#else
-#include <DisplayListCanvas.h>
-typedef android::uirenderer::DisplayListCanvas canvas_t;
-#endif
+
+#include <Canvas.h>
 #include <Rect.h>
 #include <RenderNode.h>
 #include <CanvasProperty.h>
@@ -52,7 +47,7 @@
 
 static void android_view_DisplayListCanvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jboolean reorderEnable) {
-    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
+    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
     canvas->insertReorderBarrier(reorderEnable);
 }
 
@@ -62,7 +57,7 @@
 
 static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jlong functorPtr) {
-    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
+    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
     canvas->callDrawGLFunction(functor);
 }
@@ -92,7 +87,7 @@
 static void android_view_DisplayListCanvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
         jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
-    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
+    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
     CanvasPropertyPrimitive* leftProp = reinterpret_cast<CanvasPropertyPrimitive*>(leftPropPtr);
     CanvasPropertyPrimitive* topProp = reinterpret_cast<CanvasPropertyPrimitive*>(topPropPtr);
     CanvasPropertyPrimitive* rightProp = reinterpret_cast<CanvasPropertyPrimitive*>(rightPropPtr);
@@ -105,7 +100,7 @@
 
 static void android_view_DisplayListCanvas_drawCircleProps(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
-    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
+    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
     CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
     CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
     CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
@@ -119,25 +114,25 @@
 
 static jlong android_view_DisplayListCanvas_finishRecording(JNIEnv* env,
         jobject clazz, jlong canvasPtr) {
-    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
+    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
     return reinterpret_cast<jlong>(canvas->finishRecording());
 }
 
 static jlong android_view_DisplayListCanvas_createDisplayListCanvas(JNIEnv* env, jobject clazz,
         jint width, jint height) {
-    return reinterpret_cast<jlong>(new canvas_t(width, height));
+    return reinterpret_cast<jlong>(Canvas::create_recording_canvas(width, height));
 }
 
 static void android_view_DisplayListCanvas_resetDisplayListCanvas(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jint width, jint height) {
-    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
-    canvas->reset(width, height);
+    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
+    canvas->resetRecording(width, height);
 }
 
 
 static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env,
         jobject clazz, jlong canvasPtr, jlong renderNodePtr) {
-    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
+    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     canvas->drawRenderNode(renderNode);
 }
@@ -148,7 +143,7 @@
 
 static void android_view_DisplayListCanvas_drawLayer(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jlong layerPtr) {
-    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
+    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
     canvas->drawLayer(layer);
 }
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index b1d4e26..a9003c1 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "OpenGLRenderer"
+#define ATRACE_TAG ATRACE_TAG_VIEW
 
 #include <EGL/egl.h>
 
@@ -24,7 +25,10 @@
 #include <android_runtime/AndroidRuntime.h>
 
 #include <Animator.h>
+#include <DamageAccumulator.h>
+#include <Matrix.h>
 #include <RenderNode.h>
+#include <TreeInfo.h>
 #include <Paint.h>
 
 #include "core_jni_helpers.h"
@@ -462,6 +466,69 @@
 }
 
 // ----------------------------------------------------------------------------
+// SurfaceView position callback
+// ----------------------------------------------------------------------------
+
+jmethodID gSurfaceViewPositionUpdateMethod;
+
+static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
+        jlong renderNodePtr, jobject surfaceview) {
+    class SurfaceViewPositionUpdater : public RenderNode::PositionListener {
+    public:
+        SurfaceViewPositionUpdater(JNIEnv* env, jobject surfaceview) {
+            env->GetJavaVM(&mVm);
+            mWeakRef = env->NewWeakGlobalRef(surfaceview);
+        }
+
+        virtual ~SurfaceViewPositionUpdater() {
+            jnienv()->DeleteWeakGlobalRef(mWeakRef);
+            mWeakRef = nullptr;
+        }
+
+        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
+            if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
+            ATRACE_NAME("Update SurfaceView position");
+
+            JNIEnv* env = jnienv();
+            jobject localref = env->NewLocalRef(mWeakRef);
+            if (CC_UNLIKELY(!localref)) {
+                jnienv()->DeleteWeakGlobalRef(mWeakRef);
+                mWeakRef = nullptr;
+                return;
+            }
+            Matrix4 transform;
+            info.damageAccumulator->computeCurrentTransform(&transform);
+            const RenderProperties& props = node.properties();
+            uirenderer::Rect bounds(props.getWidth(), props.getHeight());
+            transform.mapRect(bounds);
+            bounds.left -= info.windowInsetLeft;
+            bounds.right -= info.windowInsetLeft;
+            bounds.top -= info.windowInsetTop;
+            bounds.bottom -= info.windowInsetTop;
+            env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
+                    (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top,
+                    (jint) bounds.right, (jint) bounds.bottom);
+            env->DeleteLocalRef(localref);
+        }
+
+    private:
+        JNIEnv* jnienv() {
+            JNIEnv* env;
+            if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+                LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
+            }
+            return env;
+        }
+
+        JavaVM* mVm;
+        jobject mWeakRef;
+    };
+
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->setPositionListener(new SurfaceViewPositionUpdater(env, surfaceview));
+}
+
+// ----------------------------------------------------------------------------
 // JNI Glue
 // ----------------------------------------------------------------------------
 
@@ -539,9 +606,14 @@
 
     { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
     { "nEndAllAnimators",          "(J)V", (void*) android_view_RenderNode_endAllAnimators },
+
+    { "nRequestPositionUpdates",   "(JLandroid/view/SurfaceView;)V", (void*) android_view_RenderNode_requestPositionUpdates },
 };
 
 int register_android_view_RenderNode(JNIEnv* env) {
+    jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
+    gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
+            "updateWindowPositionRT", "(JIIII)V");
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
 }
 
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index edced56..acd0501 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -27,6 +27,7 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <EGL/egl_cache.h>
+#include <vulkan/vulkan_loader_data.h>
 
 #include <utils/Looper.h>
 #include <utils/RefBase.h>
@@ -133,7 +134,14 @@
 
     virtual void prepareTree(TreeInfo& info) {
         info.errorHandler = this;
+        // TODO: This is hacky
+        info.windowInsetLeft = -stagingProperties().getLeft();
+        info.windowInsetTop = -stagingProperties().getTop();
+        info.updateWindowPositions = true;
         RenderNode::prepareTree(info);
+        info.updateWindowPositions = false;
+        info.windowInsetLeft = 0;
+        info.windowInsetTop = 0;
         info.errorHandler = NULL;
     }
 
@@ -368,28 +376,28 @@
 static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface);
-    proxy->initialize(window);
+    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
+    proxy->initialize(surface);
 }
 
 static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<ANativeWindow> window;
+    sp<Surface> surface;
     if (jsurface) {
-        window = android_view_Surface_getNativeWindow(env, jsurface);
+        surface = android_view_Surface_getSurface(env, jsurface);
     }
-    proxy->updateSurface(window);
+    proxy->updateSurface(surface);
 }
 
 static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<ANativeWindow> window;
+    sp<Surface> surface;
     if (jsurface) {
-        window = android_view_Surface_getNativeWindow(env, jsurface);
+        surface = android_view_Surface_getSurface(env, jsurface);
     }
-    return proxy->pauseSurface(window);
+    return proxy->pauseSurface(surface);
 }
 
 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
@@ -618,6 +626,18 @@
 }
 
 // ----------------------------------------------------------------------------
+// Layers
+// ----------------------------------------------------------------------------
+
+static void android_view_ThreadedRenderer_setupVulkanLayerPath(JNIEnv* env, jobject clazz,
+        jstring layerPath) {
+
+    const char* layerArray = env->GetStringUTFChars(layerPath, NULL);
+    vulkan::LoaderData::GetInstance().layer_path = layerArray;
+    env->ReleaseStringUTFChars(layerPath, layerArray);
+}
+
+// ----------------------------------------------------------------------------
 // JNI Glue
 // ----------------------------------------------------------------------------
 
@@ -658,6 +678,8 @@
     { "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
                 (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
+    { "setupVulkanLayerPath", "(Ljava/lang/String;)V",
+                (void*) android_view_ThreadedRenderer_setupVulkanLayerPath },
     { "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
     { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
     { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3ef81ba..4cddb6c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -231,6 +231,7 @@
     <!-- @deprecated.  Only {@link android.net.ConnectivityManager.CONNECTIVITY_ACTION} is sent. -->
     <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" />
     <protected-broadcast android:name="android.net.conn.DATA_ACTIVITY_CHANGE" />
+    <protected-broadcast android:name="android.net.conn.RESTRICT_BACKGROUND_CHANGED" />
     <protected-broadcast android:name="android.net.conn.BACKGROUND_DATA_SETTING_CHANGED" />
     <protected-broadcast android:name="android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED" />
 
@@ -291,9 +292,12 @@
     <protected-broadcast android:name="android.intent.action.REMOTE_BUGREPORT_FINISHED" />
     <protected-broadcast android:name="android.intent.action.REMOTE_BUGREPORT_DISPATCH" />
 
+    <!-- Legacy -->
     <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
     <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_END" />
 
+    <protected-broadcast android:name="com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE" />
+
     <protected-broadcast android:name="android.intent.action.HDMI_PLUGGED" />
 
     <protected-broadcast android:name="android.intent.action.PHONE_STATE" />
@@ -1209,8 +1213,7 @@
     <eat-comment />
 
     <!-- Allows access to the list of accounts in the Accounts Service.
-         <p>Protection level: dangerous
-         @deprecated Not operative for apps apps with targetSdkVersion >= 24.
+        <p>Protection level: normal
     -->
     <permission android:name="android.permission.GET_ACCOUNTS"
         android:permissionGroup="android.permission-group.CONTACTS"
@@ -2736,6 +2739,7 @@
          android.service.notification.NotificationAssistantService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
+         @hide This is not a third-party API (intended for system apps). -->
     -->
     <permission android:name="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
         android:protectionLevel="signature" />
@@ -2874,6 +2878,12 @@
     <permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows trusted applications to dispatch managed provisioning message to Managed
+         Provisioning app. If requesting app does not have permission, it will be ignored.
+         @hide -->
+    <permission android:name="android.permission.DISPATCH_PROVISIONING_MESSAGE"
+                android:protectionLevel="signature|privileged" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
@@ -3143,6 +3153,10 @@
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
 
+        <service android:name="com.android.server.content.SyncJobService"
+                 android:permission="android.permission.BIND_JOB_SERVICE" >
+        </service>
+
         <service
             android:name="com.android.server.pm.BackgroundDexOptService"
             android:exported="true"
diff --git a/packages/PrintSpooler/res/color/item_text_color.xml b/core/res/res/color/decor_button_dark_color.xml
similarity index 79%
copy from packages/PrintSpooler/res/color/item_text_color.xml
copy to core/res/res/color/decor_button_dark_color.xml
index f580fbd..16cc797 100644
--- a/packages/PrintSpooler/res/color/item_text_color.xml
+++ b/core/res/res/color/decor_button_dark_color.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-   <item android:state_enabled="true" android:color="#333333" />
-   <item android:color="#888888"/>
-</selector>
\ No newline at end of file
+    <item android:state_window_focused="true" android:color="#FF000000" />
+    <item android:color="#33000000" />
+</selector>
diff --git a/packages/PrintSpooler/res/color/item_text_color.xml b/core/res/res/color/decor_button_light_color.xml
similarity index 79%
rename from packages/PrintSpooler/res/color/item_text_color.xml
rename to core/res/res/color/decor_button_light_color.xml
index f580fbd..13daac4 100644
--- a/packages/PrintSpooler/res/color/item_text_color.xml
+++ b/core/res/res/color/decor_button_light_color.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -15,6 +15,6 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-   <item android:state_enabled="true" android:color="#333333" />
-   <item android:color="#888888"/>
-</selector>
\ No newline at end of file
+    <item android:state_window_focused="true" android:color="#FFFFFFFF" />
+    <item android:color="#33FFFFFF" />
+</selector>
diff --git a/core/res/res/drawable-hdpi/ic_user_secure.png b/core/res/res/drawable-hdpi/ic_user_secure.png
new file mode 100644
index 0000000..60dcf2a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_user_secure.png b/core/res/res/drawable-mdpi/ic_user_secure.png
new file mode 100644
index 0000000..0dea77a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_user_secure.png b/core/res/res/drawable-xhdpi/ic_user_secure.png
new file mode 100644
index 0000000..a6ef51a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_user_secure.png b/core/res/res/drawable-xxhdpi/ic_user_secure.png
new file mode 100644
index 0000000..e6154e5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_user_secure.png b/core/res/res/drawable-xxxhdpi/ic_user_secure.png
new file mode 100644
index 0000000..9a3959b
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/ic_user_secure.png
Binary files differ
diff --git a/core/res/res/drawable/decor_close_button_dark.xml b/core/res/res/drawable/decor_close_button_dark.xml
index e5ea1f3..950e4fd 100644
--- a/core/res/res/drawable/decor_close_button_dark.xml
+++ b/core/res/res/drawable/decor_close_button_dark.xml
@@ -1,22 +1,31 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!--
+Copyright (C) 2015 The Android Open Source Project
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
 
-          http://www.apache.org/licenses/LICENSE-2.0
+         http://www.apache.org/licenses/LICENSE-2.0
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
 -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_window_focused="true"
-          android:drawable="@drawable/ic_decor_close_button_dark_focused" />
-    <item android:drawable="@drawable/ic_decor_close_button_dark_unfocused" />
-</selector>
-
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0"
+        android:tint="@color/decor_button_dark_color"
+        >
+    <group android:scaleX="0.5"
+            android:scaleY="0.5"
+            android:translateX="8.0"
+            android:translateY="8.0" >
+        <path
+            android:fillColor="@color/white"
+            android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/decor_close_button_light.xml b/core/res/res/drawable/decor_close_button_light.xml
index b77b2bd..d75cd25 100644
--- a/core/res/res/drawable/decor_close_button_light.xml
+++ b/core/res/res/drawable/decor_close_button_light.xml
@@ -1,22 +1,31 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!--
+Copyright (C) 2015 The Android Open Source Project
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
 
-          http://www.apache.org/licenses/LICENSE-2.0
+         http://www.apache.org/licenses/LICENSE-2.0
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
 -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_window_focused="true"
-          android:drawable="@drawable/ic_decor_close_button_light_focused" />
-    <item android:drawable="@drawable/ic_decor_close_button_light_unfocused" />
-</selector>
-
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0"
+        android:tint="@color/decor_button_light_color"
+        >
+    <group android:scaleX="0.5"
+            android:scaleY="0.5"
+            android:translateX="8.0"
+            android:translateY="8.0" >
+        <path
+                android:fillColor="@color/white"
+                android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/decor_maximize_button_dark.xml b/core/res/res/drawable/decor_maximize_button_dark.xml
index 5ea372b..619b460 100644
--- a/core/res/res/drawable/decor_maximize_button_dark.xml
+++ b/core/res/res/drawable/decor_maximize_button_dark.xml
@@ -14,9 +14,24 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_window_focused="true"
-          android:drawable="@drawable/ic_decor_maximize_button_dark_focused" />
-    <item android:drawable="@drawable/ic_decor_maximize_button_dark_unfocused" />
-</selector>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0"
+        android:tint="@color/decor_button_dark_color"
+        >
+    <group android:scaleX="0.5"
+            android:scaleY="0.5"
+            android:translateX="8.0"
+            android:translateY="8.0" >
+        <path
+            android:fillColor="@color/white"
+            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
+        <path
+            android:fillColor="@color/white"
+            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
+    </group>
+</vector>
+
 
diff --git a/core/res/res/drawable/decor_maximize_button_light.xml b/core/res/res/drawable/decor_maximize_button_light.xml
index 5bda131..5b55fd2 100644
--- a/core/res/res/drawable/decor_maximize_button_light.xml
+++ b/core/res/res/drawable/decor_maximize_button_light.xml
@@ -1,22 +1,35 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!--
+Copyright (C) 2015 The Android Open Source Project
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
 
-          http://www.apache.org/licenses/LICENSE-2.0
+         http://www.apache.org/licenses/LICENSE-2.0
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_window_focused="true"
-          android:drawable="@drawable/ic_decor_maximize_button_light_focused" />
-    <item android:drawable="@drawable/ic_decor_maximize_button_light_unfocused" />
-</selector>
-
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0"
+        android:tint="@color/decor_button_light_color"
+        >
+    <group android:scaleX="0.5"
+            android:scaleY="0.5"
+            android:translateX="8.0"
+            android:translateY="8.0" >
+        <path
+            android:fillColor="@color/white"
+            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
+        <path
+            android:fillColor="@color/white"
+            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_close.xml b/core/res/res/drawable/ic_close.xml
new file mode 100644
index 0000000..7086959
--- /dev/null
+++ b/core/res/res/drawable/ic_close.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
+        android:fillColor="#FF000000"/>
+</vector>
diff --git a/core/res/res/drawable/ic_decor_close_button_dark_focused.xml b/core/res/res/drawable/ic_decor_close_button_dark_focused.xml
deleted file mode 100644
index 0794ed3..0000000
--- a/core/res/res/drawable/ic_decor_close_button_dark_focused.xml
+++ /dev/null
@@ -1,29 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="32.0"
-        android:viewportHeight="32.0">
-    <group android:scaleX="0.5"
-           android:scaleY="0.5"
-           android:translateX="8.0"
-           android:translateY="8.0" >
-        <path
-            android:fillColor="#ff000000"
-            android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
-    </group>
-</vector>
diff --git a/core/res/res/drawable/ic_decor_close_button_dark_unfocused.xml b/core/res/res/drawable/ic_decor_close_button_dark_unfocused.xml
deleted file mode 100644
index bd1db51..0000000
--- a/core/res/res/drawable/ic_decor_close_button_dark_unfocused.xml
+++ /dev/null
@@ -1,29 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="32.0"
-        android:viewportHeight="32.0">
-    <group android:scaleX="0.5"
-           android:scaleY="0.5"
-           android:translateX="8.0"
-           android:translateY="8.0" >
-        <path
-            android:fillColor="#33000000"
-            android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
-    </group>
-</vector>
diff --git a/core/res/res/drawable/ic_decor_close_button_light_focused.xml b/core/res/res/drawable/ic_decor_close_button_light_focused.xml
deleted file mode 100644
index d7b167dd..0000000
--- a/core/res/res/drawable/ic_decor_close_button_light_focused.xml
+++ /dev/null
@@ -1,29 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="32.0"
-        android:viewportHeight="32.0">
-    <group android:scaleX="0.5"
-           android:scaleY="0.5"
-           android:translateX="8.0"
-           android:translateY="8.0" >
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
-    </group>
-</vector>
diff --git a/core/res/res/drawable/ic_decor_close_button_light_unfocused.xml b/core/res/res/drawable/ic_decor_close_button_light_unfocused.xml
deleted file mode 100644
index e2e81b9..0000000
--- a/core/res/res/drawable/ic_decor_close_button_light_unfocused.xml
+++ /dev/null
@@ -1,29 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="32.0"
-        android:viewportHeight="32.0">
-    <group android:scaleX="0.5"
-           android:scaleY="0.5"
-           android:translateX="8.0"
-           android:translateY="8.0" >
-        <path
-            android:fillColor="#33FFFFFF"
-            android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
-    </group>
-</vector>
diff --git a/core/res/res/drawable/ic_decor_maximize_button_dark_focused.xml b/core/res/res/drawable/ic_decor_maximize_button_dark_focused.xml
deleted file mode 100644
index c23390e..0000000
--- a/core/res/res/drawable/ic_decor_maximize_button_dark_focused.xml
+++ /dev/null
@@ -1,32 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="32.0"
-        android:viewportHeight="32.0">
-    <group android:scaleX="0.5"
-           android:scaleY="0.5"
-           android:translateX="8.0"
-           android:translateY="8.0" >
-        <path
-            android:fillColor="#FF000000"
-            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
-        <path
-            android:fillColor="#B2000000"
-            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
-    </group>
-</vector>
diff --git a/core/res/res/drawable/ic_decor_maximize_button_dark_unfocused.xml b/core/res/res/drawable/ic_decor_maximize_button_dark_unfocused.xml
deleted file mode 100644
index a194a39..0000000
--- a/core/res/res/drawable/ic_decor_maximize_button_dark_unfocused.xml
+++ /dev/null
@@ -1,32 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="32.0"
-        android:viewportHeight="32.0">
-    <group android:scaleX="0.5"
-           android:scaleY="0.5"
-           android:translateX="8.0"
-           android:translateY="8.0" >
-        <path
-            android:fillColor="#33000000"
-            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
-        <path
-            android:fillColor="#33000000"
-            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
-    </group>
-</vector>
diff --git a/core/res/res/drawable/ic_decor_maximize_button_light_focused.xml b/core/res/res/drawable/ic_decor_maximize_button_light_focused.xml
deleted file mode 100644
index 73d808b..0000000
--- a/core/res/res/drawable/ic_decor_maximize_button_light_focused.xml
+++ /dev/null
@@ -1,32 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="32.0"
-        android:viewportHeight="32.0">
-    <group android:scaleX="0.5"
-           android:scaleY="0.5"
-           android:translateX="8.0"
-           android:translateY="8.0" >
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
-        <path
-            android:fillColor="#B2FFFFFF"
-            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
-    </group>
-</vector>
diff --git a/core/res/res/drawable/ic_decor_maximize_button_light_unfocused.xml b/core/res/res/drawable/ic_decor_maximize_button_light_unfocused.xml
deleted file mode 100644
index dc79e10..0000000
--- a/core/res/res/drawable/ic_decor_maximize_button_light_unfocused.xml
+++ /dev/null
@@ -1,32 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="32.0"
-        android:viewportHeight="32.0">
-    <group android:scaleX="0.5"
-           android:scaleY="0.5"
-           android:translateX="8.0"
-           android:translateY="8.0" >
-        <path
-            android:fillColor="#33FFFFFF"
-            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
-        <path
-            android:fillColor="#33FFFFFF"
-            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
-    </group>
-</vector>
diff --git a/core/res/res/drawable/ic_feedback.xml b/core/res/res/drawable/ic_feedback.xml
new file mode 100644
index 0000000..b2d1cb8
--- /dev/null
+++ b/core/res/res/drawable/ic_feedback.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M0 0h24v24H0z"
+        android:fillColor="#00000000"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M20.0,2.0L4.0,2.0c-1.1,0.0 -1.9,0.9 -1.99,2.0L2.0,22.0l4.0,-4.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L22.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-7.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0l0.0,2.0zm0.0,-4.0l-2.0,0.0L11.0,6.0l2.0,0.0l0.0,4.0z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_refresh.xml b/core/res/res/drawable/ic_refresh.xml
new file mode 100644
index 0000000..1f67168
--- /dev/null
+++ b/core/res/res/drawable/ic_refresh.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M17.65,6.35C16.2,4.9 14.21,4.0 12.0,4.0c-4.42,0.0 -7.99,3.58 -7.99,8.0s3.57,8.0 7.99,8.0c3.73,0.0 6.84,-2.55 7.73,-6.0l-2.08,0.0c-0.82,2.33 -3.04,4.0 -5.65,4.0 -3.31,0.0 -6.0,-2.69 -6.0,-6.0s2.69,-6.0 6.0,-6.0c1.66,0.0 3.1,0.69 4.22,1.78L13.0,11.0l7.0,0.0L20.0,4.0l-2.35,2.35z"/>
+    <path
+        android:pathData="M0 0h24v24H0z"
+        android:fillColor="#00000000"/>
+</vector>
diff --git a/core/res/res/drawable/ic_schedule.xml b/core/res/res/drawable/ic_schedule.xml
new file mode 100644
index 0000000..899dc82
--- /dev/null
+++ b/core/res/res/drawable/ic_schedule.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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M11.99,2.0C6.47,2.0 2.0,6.48 2.0,12.0s4.47,10.0 9.99,10.0C17.52,22.0 22.0,17.52 22.0,12.0S17.52,2.0 11.99,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.58 -8.0,-8.0s3.58,-8.0 8.0,-8.0 8.0,3.58 8.0,8.0 -3.58,8.0 -8.0,8.0z"/>
+    <path
+        android:pathData="M0 0h24v24H0z"
+        android:fillColor="#00000000"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12.5,7.0L11.0,7.0l0.0,6.0l5.25,3.1 0.75,-1.23 -4.5,-2.67z"/>
+</vector>
diff --git a/core/res/res/layout/alert_dialog_button_bar_material.xml b/core/res/res/layout/alert_dialog_button_bar_material.xml
index f7974a5..e879d81 100644
--- a/core/res/res/layout/alert_dialog_button_bar_material.xml
+++ b/core/res/res/layout/alert_dialog_button_bar_material.xml
@@ -15,42 +15,48 @@
      limitations under the License.
 -->
 
-<com.android.internal.widget.ButtonBarLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/buttonPanel"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layoutDirection="locale"
-    android:orientation="horizontal"
-    android:paddingStart="12dp"
-    android:paddingEnd="12dp"
-    android:paddingTop="4dp"
-    android:paddingBottom="4dp"
-    android:gravity="bottom"
-    style="?attr/buttonBarStyle">
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:id="@+id/buttonPanel"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:scrollbarAlwaysDrawVerticalTrack="true"
+            android:scrollIndicators="top|bottom"
+            android:fillViewport="true"
+            style="?attr/buttonBarStyle">
+    <com.android.internal.widget.ButtonBarLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layoutDirection="locale"
+        android:orientation="horizontal"
+        android:paddingStart="12dp"
+        android:paddingEnd="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp"
+        android:gravity="bottom">
 
-    <Button
-        android:id="@+id/button3"
-        style="?attr/buttonBarNeutralButtonStyle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
+        <Button
+            android:id="@+id/button3"
+            style="?attr/buttonBarNeutralButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
 
-    <Space
-        android:id="@+id/spacer"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        android:visibility="invisible" />
+        <Space
+            android:id="@+id/spacer"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:visibility="invisible" />
 
-    <Button
-        android:id="@+id/button2"
-        style="?attr/buttonBarNegativeButtonStyle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
+        <Button
+            android:id="@+id/button2"
+            style="?attr/buttonBarNegativeButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
 
-    <Button
-        android:id="@+id/button1"
-        style="?attr/buttonBarPositiveButtonStyle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-</com.android.internal.widget.ButtonBarLayout>
+        <Button
+            android:id="@+id/button1"
+            style="?attr/buttonBarPositiveButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+    </com.android.internal.widget.ButtonBarLayout>
+</ScrollView>
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index 95c2459..9f50937 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -15,7 +15,7 @@
      limitations under the License.
 -->
 
-<LinearLayout
+<com.android.internal.widget.AlertDialogLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
@@ -28,7 +28,6 @@
         android:id="@+id/contentPanel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
         android:minHeight="48dp">
 
         <ScrollView
@@ -64,7 +63,6 @@
         android:id="@+id/customPanel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
         android:minHeight="48dp">
 
         <FrameLayout
@@ -73,5 +71,8 @@
             android:layout_height="wrap_content" />
     </FrameLayout>
 
-    <include layout="@layout/alert_dialog_button_bar_material" />
-</LinearLayout>
+    <include
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        layout="@layout/alert_dialog_button_bar_material" />
+</com.android.internal.widget.AlertDialogLayout>
diff --git a/core/res/res/layout/alert_dialog_title_material.xml b/core/res/res/layout/alert_dialog_title_material.xml
index f61b90b..738a637 100644
--- a/core/res/res/layout/alert_dialog_title_material.xml
+++ b/core/res/res/layout/alert_dialog_title_material.xml
@@ -41,13 +41,13 @@
 
         <com.android.internal.widget.DialogTitle
             android:id="@+id/alertTitle"
-            style="?attr/windowTitleStyle"
             android:singleLine="true"
             android:ellipsize="end"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:textAlignment="viewStart" />
+            android:textAlignment="viewStart"
+            style="?attr/windowTitleStyle" />
     </LinearLayout>
 
     <!-- If the client uses a customTitle, it will be added here. -->
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/core/res/res/layout/app_anr_dialog.xml b/core/res/res/layout/app_anr_dialog.xml
index e8169ee..8bef116 100644
--- a/core/res/res/layout/app_anr_dialog.xml
+++ b/core/res/res/layout/app_anr_dialog.xml
@@ -18,28 +18,31 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:paddingTop="@dimen/dialog_list_padding_vertical_material"
+        android:paddingTop="@dimen/aerr_padding_list_top"
         android:paddingBottom="@dimen/dialog_list_padding_vertical_material">
 
-    <TextView
+    <Button
             android:id="@+id/aerr_close"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/aerr_close_app"
+            android:drawableStart="@drawable/ic_close"
             style="@style/aerr_list_item" />
 
-    <TextView
+    <Button
             android:id="@+id/aerr_wait"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/aerr_wait"
+            android:drawableStart="@drawable/ic_schedule"
             style="@style/aerr_list_item" />
 
-    <TextView
+    <Button
             android:id="@+id/aerr_report"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/aerr_report"
+            android:drawableStart="@drawable/ic_feedback"
             style="@style/aerr_list_item" />
 
 </LinearLayout>
diff --git a/core/res/res/layout/app_error_dialog.xml b/core/res/res/layout/app_error_dialog.xml
index 46a2b2a..824f97f 100644
--- a/core/res/res/layout/app_error_dialog.xml
+++ b/core/res/res/layout/app_error_dialog.xml
@@ -21,9 +21,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:paddingTop="@dimen/dialog_list_padding_vertical_material"
-        android:paddingBottom="@dimen/dialog_list_padding_vertical_material"
->
+        android:paddingTop="@dimen/aerr_padding_list_top"
+        android:paddingBottom="@dimen/dialog_list_padding_vertical_material">
 
 
     <Button
@@ -31,6 +30,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/aerr_restart"
+            android:drawableStart="@drawable/ic_refresh"
             style="@style/aerr_list_item"
     />
 
@@ -39,6 +39,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/aerr_reset"
+            android:drawableStart="@drawable/ic_refresh"
             style="@style/aerr_list_item"
     />
 
@@ -47,6 +48,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/aerr_report"
+            android:drawableStart="@drawable/ic_feedback"
             style="@style/aerr_list_item"
     />
 
@@ -55,6 +57,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/aerr_close"
+            android:drawableStart="@drawable/ic_close"
             style="@style/aerr_list_item"
     />
 
@@ -63,6 +66,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/aerr_mute"
+            android:drawableStart="@drawable/ic_close"
             style="@style/aerr_list_item"
     />
 
diff --git a/core/res/res/layout/date_picker_header_material.xml b/core/res/res/layout/date_picker_header_material.xml
index cfc6d0d..a0e2b1d 100644
--- a/core/res/res/layout/date_picker_header_material.xml
+++ b/core/res/res/layout/date_picker_header_material.xml
@@ -21,12 +21,6 @@
               android:layout_height="wrap_content"
               android:orientation="vertical">
 
-    <ViewStub
-        android:id="@id/topPanel"
-        android:layout="@layout/alert_dialog_title_material"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -43,6 +37,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:focusable="true"
+            android:includeFontPadding="false"
             android:layout_marginStart="-8dp"
             android:layout_marginEnd="-8dp"
             android:layout_marginTop="-8dp"
@@ -57,6 +52,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textAppearance="@style/TextAppearance.Material.DatePicker.DateLabel"
+            android:includeFontPadding="false"
             android:gravity="start"
             android:maxLines="2"
             android:ellipsize="none" />
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 163db30..6669bae 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -22,8 +22,6 @@
     android:layout_width="wrap_content"
     android:layout_height="48dp"
     android:clipChildren="false"
-    android:layout_gravity="start|top"
-    android:gravity="center_vertical"
     android:paddingTop="5dp"
     android:paddingBottom="16dp"
     android:paddingStart="@dimen/notification_content_margin_start"
@@ -89,7 +87,6 @@
         android:layout_marginStart="2dp"
         android:layout_marginEnd="2dp"
         android:visibility="gone"
-        android:maxWidth="72dp"
         android:singleLine="true"/>
     <TextView
         android:id="@+id/time_divider"
diff --git a/core/res/res/layout/resolve_grid_item.xml b/core/res/res/layout/resolve_grid_item.xml
index 0a7ac77..305c8b0 100644
--- a/core/res/res/layout/resolve_grid_item.xml
+++ b/core/res/res/layout/resolve_grid_item.xml
@@ -25,6 +25,7 @@
               android:gravity="center"
               android:paddingTop="8dp"
               android:paddingBottom="8dp"
+              android:focusable="true"
               android:background="?attr/selectableItemBackgroundBorderless">
 
     <FrameLayout android:layout_width="wrap_content"
diff --git a/core/res/res/menu/language_selection_list.xml b/core/res/res/menu/language_selection_list.xml
index 63b9627..377c4fa 100644
--- a/core/res/res/menu/language_selection_list.xml
+++ b/core/res/res/menu/language_selection_list.xml
@@ -14,12 +14,12 @@
      limitations under the License.
 -->
 
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
-      xmlns:app="http://schemas.android.com/apk/res-auto">
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item
         android:id="@+id/locale_search_menu"
         android:title="@string/locale_search_menu"
-        app:showAsAction="always"
-        app:actionViewClass="android.widget.SearchView" />
+        android:icon="@*android:drawable/ic_search_api_material"
+        android:showAsAction="always|collapseActionView"
+        android:actionViewClass="android.widget.SearchView" />
 
 </menu>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index eae2c44..c8ab295 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiewe verslag"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Gebruik dit in die meeste omstandighede. Maak dit vir jou moontlik om die vordering van die verslag na te spoor en meer besonderhede oor die probleem in te voer. Dit sal dalk sommige afdelings weglaat wat minder gebruik word en waarvoor verslagdoening lank duur."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Volle verslag"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Gebruik hierdie opsie vir minimale stelselinmenging wanneer jou toestel nie reageer nie of te stadig is, of wanneer jy alle afdelings benodig. Neem nie \'n skermkiekie nie en laat jou nie toe om meer besonderhede in te voer nie."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Neem skermkiekie vir foutverslag oor <xliff:g id="NUMBER_1">%d</xliff:g> sekondes.</item>
       <item quantity="one">Neem skermkiekie vir foutverslag oor <xliff:g id="NUMBER_0">%d</xliff:g> sekonde.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Inhoud versteek"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Inhoud word versteek volgens beleid"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Persoonlik"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Kies \'n handeling"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Kies \'n program vir die USB-toestel"</string>
     <string name="noApplications" msgid="2991814273936504689">"Geen programme kan hierdie handeling uitvoer nie."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Ongelukkig het <xliff:g id="APPLICATION">%1$s</xliff:g> gestop."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Ongelukkig het die proses <xliff:g id="PROCESS">%1$s</xliff:g> gestop."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Maak omvalle van <xliff:g id="PROCESS">%1$s</xliff:g> af stil tot herselflaai."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> het gestop"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> het gestop"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> stop aanhoudend"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> stop aanhoudend"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Herbegin program"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Stel terug en herbegin program"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Stuur terugvoer"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Maak toe"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Demp"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Wag"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Maak program toe"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> reageer nie.\n\nWil jy dit sluit?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktiwiteit <xliff:g id="ACTIVITY">%1$s</xliff:g> reageer nie.\n\nWil jy dit afsluit?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> reageer nie. Wil jy dit sluit?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> reageer nie.\n\nWil jy dit afsluit?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> reageer nie"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> reageer nie"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> reageer nie"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> reageer nie"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Verslag"</string>
     <string name="wait" msgid="7147118217226317732">"Wag"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-kaart bygevoeg"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Herbegin jou toestel om toegang tot die sellulêre netwerk te verkry."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Herbegin"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Jy sal \'n program van jou diensverskaffer af moet installeer en oopmaak om jou nuwe SIM behoorlik te laat werk."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"KRY DIE PROGRAM"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NIE NOU NIE"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Nuwe SIM is ingesit"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Tik om dit op te stel"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Stel tyd"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Stel datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Stel"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Vra PIN voordat jy ontspeld"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Vra ontsluitpatroon voordat jy ontspeld"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vra wagwoord voordat jy ontspeld"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Program se grootte kan nie verander word nie; rollees dit met twee vingers."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Program se grootte kan nie verander word nie; rollees dit met twee vingers."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Program steun nie verdeelde skerm nie."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Deur jou administrateur geïnstalleer"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Opgedateer deur jou administrateur"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Deur jou administrateur uitgevee"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Jy stel die belangrikheid van hierdie kennisgewings."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Dit is belangrik as gevolg van die mense wat betrokke is."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" probeer om \'n nuwe gebruiker by te voeg, maar word tans verbied."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" probeer tans om \'n nuwe gebruiker by te voeg, maar die gebruikerlimiet is bereik."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" probeer tans om \'n nuwe gebruiker by te voeg, maar die rekening "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" bestaan reeds op hierdie toestel. Gaan in elk geval voort?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" probeer tans om \'n nuwe gebruiker vir die rekening "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" by te voeg. Gaan voort?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Laat <xliff:g id="APP">%1$s</xliff:g> toe om \'n nuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> te skep?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Laat <xliff:g id="APP">%1$s</xliff:g> toe om \'n nuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> te skep (\'n gebruiker met hierdie rekening bestaan reeds)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Taalvoorkeur"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Streekvoorkeur"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Voer taalnaam in"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Voorgestel"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Alle tale"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Soek"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Werkmodus is AF"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Stel werkprofiel in staat om te werk, insluitend programme, agtergrondsinkronisering en verwante kenmerke."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Skakel aan"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Deur %1$s gedeaktiveer"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Deur %1$s-administrateur gedeaktiveer. Kontak hulle om meer uit te vind."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Jy het nuwe boodskappe"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Maak SMS-program oop om te bekyk"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Party funksies dalk nie beskikbaar nie"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Raak om voort te gaan"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Gebruikerprofiel is gesluit"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Gekoppel aan <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Tik om lêers te bekyk"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Speld vas"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Ontspeld"</string>
+    <string name="app_info" msgid="6856026610594615344">"Programinligting"</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 85ef3c5..461c78a 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"መስተጋብራዊ ሪፖርት"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"በአብዛኛዎቹ ሁኔታዎች ይህን ይጠቀሙ። የሪፖርቱን ሂደት እንዲከታተሉ እና ስለችግሩ ተጨማሪ ዝርዝሮችን እንዲያስገቡ ያስችልዎታል። ሪፖርት ለማድረግ በጣም ረዥም ጊዜ የሚወስዱ አንዳንድ ብዙም ጥቅም ላይ የማይውሉ ክፍሎችን ሊያልፋቸው ይችላል።"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"ሙሉ ሪፖርት"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"የእርስዎ መሣሪያ ምላሽ የማይሰጥ ወይም ቀርፋፋ ሲሆን ለአነስተኛ የስርዓት ጣልቃ ገብነት፣ ወይም በሁሉም የሪፖርት ክፍሎች ላይ ካስፈለገዎት ይህን አማራጭ ይጠቀሙ። ቅጽበታዊ ገጽ ዕይታ አያነሳም ወይም ተጨማሪ ዝርዝሮችን እንዲያስገቡ አይፈቅድልዎትም።"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">በ<xliff:g id="NUMBER_1">%d</xliff:g> ሰከንዶች ውስጥ ለሳንካ ሪፖርት ቅጽበታዊ ገጽ ዕይታን በማንሳት ላይ።</item>
       <item quantity="other">በ<xliff:g id="NUMBER_1">%d</xliff:g> ሰከንዶች ውስጥ ለሳንካ ሪፖርት ቅጽበታዊ ገጽ ዕይታን በማንሳት ላይ።</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ይዘቶች ተደብቀዋል"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ይዘቶች በመመሪያ ተደብቀዋል"</string>
     <string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"የግል"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"ድርጊት ምረጥ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"ለUSB መሳሪያ መተግበሪያ ምረጥ"</string>
     <string name="noApplications" msgid="2991814273936504689">"ምንም መተግበሪያዎች ይህን ድርጊት ማከናወን አይችሉም።"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"መጥፎ ዕድል ሆኖ፣ <xliff:g id="APPLICATION">%1$s</xliff:g> አቁሞዋል፡፡"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"መጥፎ ዕድል ሆኖ፣ ይሄ ሂደት <xliff:g id="PROCESS">%1$s</xliff:g> ቆሞዋል፡፡"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"ዝምታ ብልሽቶች ከ<xliff:g id="PROCESS">%1$s</xliff:g> እስከ ዳግም ማስነሳት።"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> አቁሟል"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ቆሟል"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> አሁንም እያቆመ ነው"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> አሁንም እያቆመ ነው"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"መተግበሪያውን ዳግም አስጀምር"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"ዳግም ያቀናብሩ እና መተግበሪያ ዳግም ያስጀምሩት"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"ግብረመልስ ይላኩ"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"ዝጋ"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"ድምጽ-ከል አድርግ"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"ጠብቅ"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"መተግበሪያን ዝጋ"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ምላሽ እየሰጠ አይደለም።\n\n መዝጋት ይፈልጋሉ?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"እንቅስቃሴ <xliff:g id="ACTIVITY">%1$s</xliff:g> ምላሽ እየሰጠ አይደለም።\n\n መዝጋት ይፈልጋሉ?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ምላሽ እየሰጠ አይደለም። መዝጋት ይፈልጋሉ?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"ሂደት <xliff:g id="PROCESS">%1$s</xliff:g> ምላሽ እየሰጠ አይደለም።\n\n መዝጋት ይፈልጋሉ?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ምላሽ እየሰጠ አይደለም"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ምላሽ እየሰጠ አይደለም"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ምላሽ እየሰጠ አይደለም"</string>
+    <string name="anr_process" msgid="6156880875555921105">"ሂደት <xliff:g id="PROCESS">%1$s</xliff:g> ምላሽ እየሰጠ አይደለም"</string>
     <string name="force_close" msgid="8346072094521265605">"ይሁን"</string>
     <string name="report" msgid="4060218260984795706">"ሪፖርት"</string>
     <string name="wait" msgid="7147118217226317732">"ቆይ"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM ካርድ አክል"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"የተንቀሳቃሽ ስልክ አውታረ መረብ ለመድረስ መሣሪያዎን ዳግም ያስጀምሩት።"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"ዳግም ጀምር"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ጊዜ አዘጋጅ"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ውሂብ አዘጋጅ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"አዘጋጅ"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ከመንቀል በፊት ፒን ጠይቅ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ከመንቀል በፊት የማስከፈቻ ስርዓተ-ጥለት ጠይቅ"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ከመንቀል በፊት የይለፍ ቃል ጠይቅ"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"የመተግበሪያው መጠን ሊቀየር የሚችል አይደለም፣ በሁለት ጣቶች ያሸብልሉት።"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"የመተግበሪያው መጠን ሊቀየር የሚችል አይደለም፣ በሁለት ጣቶች ያሸብልሉት።"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"መተግበሪያው የተከፈለ ማያ ገጽን አይደግፍም።"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"በእርስዎ አስተዳዳሪ ተጭኗል"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"በአስተዳዳሪዎ ተዘምኗል"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"በእርስዎ አስተዳዳሪ ተሰርዟል"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"የተለያዩ"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"የእነዚህን ማሳወቂያዎች አስፈላጊነት አዘጋጅተዋል።"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ይሄ በሚሳተፉ ሰዎች ምክንያት አስፈላጊ ነው።"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" አዲስ ተጠቃሚ ለማከል እየሞከረ ነው፣ ነገር ግን አሁን ላይ ተከልክሏል።"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" አዲስ ተጠቃሚ ለማከል እየሞከረ ነው፣ ሆኖም ግን የተጠቃሚ ብዛት ገደብ ላይ ተደርሷል።"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" አዲስ ተጠቃሚ ለማከል እየሞከረ ነው፣ ነገር ግን መለያ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" አስቀድሞ በዚህ መሣሪያ ላይ አለ። የሆነው ሆኖ ይቀጥል?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ለ"<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" መለያ አዲስ ተጠቃሚ ለማከል እየሞከረ ነው። ይቀጥል?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> በ<xliff:g id="ACCOUNT">%2$s</xliff:g> አዲስ ተጠቃሚ እንዲፈጥር ይፈቀድለት?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> በ<xliff:g id="ACCOUNT">%2$s</xliff:g> አዲስ ተጠቃሚ እንዲፈጥር ይፈቀድለት (ይህ መለያ ያለው ተጠቃሚ አስቀድሞ አለ)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"የቋንቋ ምርጫ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"የክልል ምርጫ"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"የቋንቋ ስም ይተይቡ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"የተጠቆሙ"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ሁሉም ቋንቋዎች"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"ፈልግ"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"የሥራ ሁነታ ጠፍቷል"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"መተግበሪያዎችን፣ የበስተጀርባ ሥምረት እና ተዛማጅ ባሕሪዎችን ጨምሮ የሥራ መገለጫ እንዲሰራ ይፍቀዱ።"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"አብራ"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ተሰናክሏል"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"በ%1$s አስተዳዳሪ ተሰናክሏል። የበለጠ ለመረዳት ያነጋግሯቸው።"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"አዲስ መልእክቶች አለዎት"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"ለመመልከት የኤስኤምኤስ መተግበሪያ ይክፈቱ"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"አንዳንድ ተግባሮች ላይገኙ ይችላሉ"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"ለመቀጠል ይንኩ"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"የተጠቃሚ መገለጫ ተቆልፏል"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"ከ<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ጋር ተገናኝቷል"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ፋይሎችን ለመመልከት መታ ያድርጉ"</string>
+    <string name="pin_target" msgid="3052256031352291362">"ፒን"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"ንቀል"</string>
+    <string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index bcab357..e927d54 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -218,8 +218,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"تقرير تفاعلي"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"يمكنك استخدام هذا الخيار في معظم الأحيان، حيث يتيح لك إمكانية تتبع مستوى تقدم التقرير والحصول على مزيد من المعلومات حول المشكلة. وقد يتم إسقاط بعض الأقسام الأقل استخدامًا والتي تستغرق وقتًا طويلاً أثناء إعداد التقرير."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"تقرير كامل"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"يمكنك استخدام هذا الخيار للحصول على حد أدنى من تدخل النظام عند توقف استجابة الجهاز أو حدوث بطئ شديد أو عند الحاجة إلى جميع أقسام التقرير. لا يؤدي ذلك إلى التقاط لقطة شاشة أو السماح لك بالحصول على مزيد من التفاصيل."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="zero">سيتم التقاط لقطة شاشة لتقرير الخطأ خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية.</item>
       <item quantity="two">سيتم التقاط لقطة شاشة لتقرير الخطأ خلال ثانيتين (<xliff:g id="NUMBER_1">%d</xliff:g>).</item>
@@ -241,6 +240,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"المحتويات مخفية"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"تم إخفاء المحتويات بواسطة السياسة"</string>
     <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏نظام Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"شخصي"</string>
@@ -933,15 +933,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"اختيار إجراء"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"‏اختيار أحد التطبيقات لجهاز USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"ليست هناك تطبيقات يمكنها تنفيذ هذا الإجراء."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"للأسف، توقف <xliff:g id="APPLICATION">%1$s</xliff:g>."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"للأسف، توقفت العملية <xliff:g id="PROCESS">%1$s</xliff:g>."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"‏يتعطل تطبيق \"Silence\" عند إجراء <xliff:g id="PROCESS">%1$s</xliff:g>، وذلك حتى إعادة التشغيل."</string>
+    <string name="aerr_application" msgid="250320989337856518">"توقف <xliff:g id="APPLICATION">%1$s</xliff:g> عن العمل"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"توقفت <xliff:g id="PROCESS">%1$s</xliff:g>"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"يستمر التطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> في التوقف."</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"تستمر عملية <xliff:g id="PROCESS">%1$s</xliff:g> في التوقف."</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"إعادة تشغيل التطبيق"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"إعادة ضبط التطبيق وإعادة تشغيله"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"إرسال تعليقات"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"إغلاق"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"تجاهل"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"انتظار"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"إغلاق التطبيق"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> لا يستجيب.\n\nهل تريد إغلاقه؟"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"النشاط <xliff:g id="ACTIVITY">%1$s</xliff:g> لا يستجيب.\n\nهل تريد إغلاقه؟"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"تطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> لا يستجيب. هل تريد إغلاقه؟"</string>
-    <string name="anr_process" msgid="6513209874880517125">"العملية <xliff:g id="PROCESS">%1$s</xliff:g> لا تستجيب.\n\nهل تريد إغلاقها؟"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> لا يستجيب"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> لا يستجيب"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> لا يستجيب"</string>
+    <string name="anr_process" msgid="6156880875555921105">"العملية <xliff:g id="PROCESS">%1$s</xliff:g> لا تستجيب"</string>
     <string name="force_close" msgid="8346072094521265605">"موافق"</string>
     <string name="report" msgid="4060218260984795706">"إرسال تقرير"</string>
     <string name="wait" msgid="7147118217226317732">"انتظار"</string>
@@ -1056,6 +1063,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"‏تمت إضافة شريحة SIM"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"أعد تشغيل جهازك للدخول إلى شبكة الجوّال."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"إعادة التشغيل"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"‏لتشغيل شريحة SIM الجديدة بشكل سليم، يجب تثبيت تطبيق من مشغّل شبكة الجوّال وفتحه."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"الحصول على التطبيق"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"ليس الآن"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"‏تم إدخال شريحة SIM جديدة."</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"انقر لإعداده."</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"تعيين الوقت"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تعيين التاريخ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"تعيين"</string>
@@ -1495,7 +1507,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"المطالبة برقم التعريف الشخصي قبل إزالة التثبيت"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"المطالبة بنقش إلغاء القفل قبل إزالة التثبيت"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"المطالبة بكلمة المرور قبل إزالة التثبيت"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"التطبيق غير قابل لتغيير الحجم، يمكنك تمريره بإصبعين."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"التطبيق غير قابل لتغيير الحجم، يمكنك تمريره بإصبعين."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"التطبيق لا يتيح تقسيم الشاشة."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"تم تثبيت الحزمة عن طريق المشرف"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"تم التحديث بواسطة المشرف"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"تم حذف الحزمة عن طريق المشرف"</string>
@@ -1603,14 +1616,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"متنوعة"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"لقد عيَّنت أهمية هذه الإشعارات."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"هذه الرسالة مهمة نظرًا لأهمية الأشخاص المعنيين."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"هناك محاولة من "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" لإضافة مستخدم جديد لكنه محظور حاليًا."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"هناك محاولة من "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" لإضافة مستخدم جديد إلا أنه قد تم الوصول إلى الحد الأقصى للمستخدمين."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"هناك محاولة من "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" لإضافة مستخدم جديد إلا أن الحساب "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" موجود مسبقًا على هذا الجهاز، فهل تريد المتابعة على أي حال؟"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392">"هناك محاولة من "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" لإضافة مستخدم جديد إلى الحساب "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>"، فهل تريد المتابعة؟"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"هل تسمح لـ <xliff:g id="APP">%1$s</xliff:g> بإنشاء مستخدم جديد باستخدام <xliff:g id="ACCOUNT">%2$s</xliff:g>؟"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"هل تسمح لـ <xliff:g id="APP">%1$s</xliff:g> بإنشاء مستخدم جديد باستخدام <xliff:g id="ACCOUNT">%2$s</xliff:g> (يوجد مستخدم بهذا الحساب مسبقًا)؟"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"تفضيل اللغة"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"تفضيل المنطقة"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"اكتب اسم اللغة"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"المقترحة"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"جميع اللغات"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"البحث"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"وضع العمل معطَّل"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"السماح باستخدام الملف الشخصي للعمل، بما في ذلك التطبيقات ومزامنة الخلفية والميزات ذات الصلة."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"تشغيل"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"‏تم تعطيل %1$s"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"‏تم التعطيل بواسطة مشرف %1$s. يمكنك الاتصال به لمعرفة المزيد."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"لديك رسائل جديدة"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"‏فتح تطبيق الرسائل القصيرة SMS للعرض"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"قد لا تكون بعض الوظائف متاحة"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"المس للمتابعة"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"تم قفل الملف الشخصي للمستخدم"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"تم الاتصال بـ <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"انقر لعرض الملفات"</string>
+    <string name="pin_target" msgid="3052256031352291362">"تثبيت"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"إزالة تثبيت"</string>
+    <string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string>
 </resources>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 05ce1c0..211346f 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"İnteraktiv hesabat"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Bir çox hallarda bundan istifadə edin. Bu hesabatın gedişatını izləməyə və problem haqqında daha ətraflı məlumat daxil etməyə imkan verir. Bu, çox vaxt tələb edən bəzi az istifadə olunan bölmələri ixtisar edə bilər."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Tam hesabat"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Cihazınız cavab verməyəndə və ya zəif işləyəndə və ya bütün hesabat bölmələri lazım olanda minimum sistem müdaxiləsi üçün bu seçimdən istifadə edin. Ani şəkil çəkmir və ya ətraflı məlumat daxil etməyə imkan vermir."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Baq hesabatı üçün <xliff:g id="NUMBER_1">%d</xliff:g> saniyədə sktinşot çəkilir.</item>
       <item quantity="one">Baq hesabatı üçün <xliff:g id="NUMBER_0">%d</xliff:g> saniyədə skrinşot çəkilir.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Məzmun gizlidir"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Məzmun siyasət tərəfindən gizlədilib"</string>
     <string name="safeMode" msgid="2788228061547930246">"Təhlükəsiz rejim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistemi"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Şəxsi"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Fəaliyyət seçin"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB cihaz üçün tətbiq seçin"</string>
     <string name="noApplications" msgid="2991814273936504689">"Heç bir tətbiq bu əməliyyatı apara bilmir."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Təəssüf ki, <xliff:g id="APPLICATION">%1$s</xliff:g> dayandı."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Təəssüf ki, <xliff:g id="PROCESS">%1$s</xliff:g> prosesi dayandı."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"<xliff:g id="PROCESS">%1$s</xliff:g> prosesindən yenidən başlatmaya kimi səssiz xətalar."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> dayandı"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> dayandı"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> dayandırılması davam edir"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> dayandırılması davam edir"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Tətbiqi yenidən başladın"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Tətbiqi sıfırlayın və yenidən başladın"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Geri əlaqə göndərin"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Bağla"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Susdur"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Gözləyin"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Tətbiqi qapadın"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> cavab vermir.\n\nOnu bağlamaq istəyirsiniz?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> aktivitisi cavab vermir. \n\nOnu bağlamaq istəyirsiniz?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> cavab vermir. Onu bağlamaq istəyirsiniz?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> cavab vermir. \n \n Onu bağlamaq istəyirsiniz?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> cavab vermir"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> cavab vermir"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> cavab vermir"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> prosesi cavab vermir"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Şikayət edin"</string>
     <string name="wait" msgid="7147118217226317732">"Gözlə"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SİM kart əlavə edildi"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Mobil şəbəkəyə giriş üçün cihazınızı sıfırlayın."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Yenidən başlat"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Yeni SIM kartınızın düzgün işləməsi üçün, operatorunuzdan tətbiq yükləməli və açmalısınız."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"TƏTBİQİ ƏLDƏ EDİN"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"İNDİ YOX"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Yeni SIM kart taxılıb"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Quraşdırmaq üçün tıklayın"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Vaxt ayarlayın"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarixi quraşdır"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ayarlayın"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ayırmadan öncə PIN istənilsin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ayırmadan öncə kilid modeli istənilsin"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ayırmadan öncə parol istənilsin"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Tətbiq ölçüləndirilmədi, iki barmağınızla sürüşdürün."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Tətbiq ölçüləndirilmədi, iki barmağınızla sürüşdürün."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Tətbiq ekran bölünməsini dəstəkləmir."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Administratorunuz tərəfindən quraşdırılıb"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Sizin administrator tərəfindən yeniləndi"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratorunuz tərəfindən silinib"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Müxtəlif"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Bildirişlərin əhəmiyyətini Siz ayarlaryırsınız."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"İnsanlar cəlb olunduğu üçün bu vacibdir."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" yeni istifadəçi əlavə etməyə çalışır, lakin hal-hazırda qadağandır."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" yeni istifadəçi əlavə etməyə çalışır, lakin istifadəçi limitinə çatılıb."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" yeni istifadəçi əlavə etməyə çalışır, lakin "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" hesabı bu cihazda artıq mövcuddur. Hər bir halda davam edilsin?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" hesabı üçün yeni istifadəçi əlavə etməyə çalışır. Davam edilsin?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> tətbiqinə <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabı ilə yeni İstifadəçi yaratmağa icazə verilsin?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> tətbiqinə<xliff:g id="ACCOUNT">%2$s</xliff:g> (bu hesab ilə İstifadəçi artıq mövcuddur) hesabı ilə yeni İstifadəçi yaratmağa icazə verilsin?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Dil seçimi"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region seçimi"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Dil adını daxil edin"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Təklif edilmiş"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Bütün dillər"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Axtarın"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"İş rejimi DEAKTİVDİR"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Tətbiq, arxa fon sinxronizasiyası və digər əlaqədar xüsusiyyətlər daxil olmaqla iş profilinin fəaliyyətinə icazə verin."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivləşdirin"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s dekativ edildi"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s administratoru tərəfindən deaktiv edildi. Ətraflı məlumat üçün onlarla əlaqə saxlayın."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Yeni mesajlarınız var"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Baxmaq üçün SMS tətbiqini açın"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Bəzi funksiyalar əlçatan olmaya bilər"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Davam etmək üçün toxunun"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"İstifadəçi profili kilidlidir"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> məhsuluna bağlandı"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Faylları görmək üçün basın"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Pin kod"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Çıxarın"</string>
+    <string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string>
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 7e5106a..7e27050 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -215,8 +215,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv. izveštaj"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Koristite ovo u većini slučajeva. To vam omogućava da pratite napredak izveštaja i da unosite dodatne detalje o problemu. Verovatno će izostaviti neke manje korišćene odeljke za koje pravljenje izveštaja dugo traje."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Kompletan izveštaj"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Koristite ovu opciju radi minimalnih sistemskih smetnji kada uređaj ne reaguje, prespor je ili su vam potrebni svi odeljci izveštaja. Ne pravi snimak ekrana niti vam dozvoljava unos dodatnih detalja."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Napravićemo snimak ekrana radi izveštaja o grešci za <xliff:g id="NUMBER_1">%d</xliff:g> sekundu.</item>
       <item quantity="few">Napravićemo snimak ekrana radi izveštaja o grešci za <xliff:g id="NUMBER_1">%d</xliff:g> sekunde.</item>
@@ -235,6 +234,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sadržaj je sakriven"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj je sakriven smernicama"</string>
     <string name="safeMode" msgid="2788228061547930246">"Bezbedni režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistem"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Lično"</string>
@@ -915,15 +915,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Izaberite radnju"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Izbor aplikacije za USB uređaj"</string>
     <string name="noApplications" msgid="2991814273936504689">"Nijedna aplikacija ne može da obavlja ovu radnju."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Nažalost, aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> je prestala s radom."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Nažalost, proces <xliff:g id="PROCESS">%1$s</xliff:g> je zaustavljen."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Nečujna otkazivanja od procesa <xliff:g id="PROCESS">%1$s</xliff:g> do restartovanja."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> je zaustavljena"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> je zaustavljen"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> se stalno zaustavlja"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> se stalno zaustavlja"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Ponovo pokreni aplikaciju"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Resetuj i ponovo pokreni aplikaciju"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Pošaljite povratne informacije"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Zatvori"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignoriši"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Čekaj"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Zatvori aplikaciju"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ne reaguje.\n\nDa li želite da je zatvorite?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktivnost <xliff:g id="ACTIVITY">%1$s</xliff:g> ne reaguje.\n\nDa li želite da je zatvorite?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ne reaguje. Da li želite da je zatvorite?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> ne raeguje.\n\nDa li želite da ga zatvorite?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ne reaguje"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ne reaguje"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ne reaguje"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> ne reaguje"</string>
     <string name="force_close" msgid="8346072094521265605">"Potvrdi"</string>
     <string name="report" msgid="4060218260984795706">"Prijavi"</string>
     <string name="wait" msgid="7147118217226317732">"Sačekaj"</string>
@@ -1032,6 +1039,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM kartica je dodata"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Ponovo pokrenite uređaj da biste pristupili mobilnoj mreži."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Ponovo pokreni"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Podešavanje vremena"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Podešavanje datuma"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Podesi"</string>
@@ -1465,7 +1482,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Traži PIN pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Traži šablon za otključavanje pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži lozinku pre otkačinjanja"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Veličina aplikacije ne može da se menja, pomerajte je pomoću dva prsta."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veličina aplikacije ne može da se menja. Pomerajte je pomoću dva prsta."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podržava podeljeni ekran."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalirao je vaš administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurirao je administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisao je vaš admiistrator"</string>
@@ -1546,14 +1564,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Razno"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Vi podešavate važnost ovih obaveštenja."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Ovo je važno zbog ljudi koji učestvuju."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" pokušava da doda novog korisnika, ali to je trenutno zabranjeno."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" pokušava da doda novog korisnika, ali je ograničenje za broj korisnika dostignuto."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" pokušava da doda novog korisnika, ali nalog "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" već postoji na ovom uređaju. Želite li ipak da nastavite?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" pokušava da doda novog korisnika za nalog "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Želite li da nastavite?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Želite li da dozvolite aplikaciji <xliff:g id="APP">%1$s</xliff:g> da napravi novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Želite li da dozvolite aplikaciji <xliff:g id="APP">%1$s</xliff:g> da napravi novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g> (korisnik sa ovim nalogom već postoji)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Podešavanje jezika"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Podešavanje regiona"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Unesite naziv jezika"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženi"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Pretraži"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Režim za Work je ISKLJUČEN"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Dozvoljava profilu za Work da funkcioniše, uključujući aplikacije, sinhronizaciju u pozadini i srodne funkcije."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Paket %1$s je onemogućen"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Onemogućio je administrator kompanije %1$s. Kontaktirajte ga da biste saznali više."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite aplikaciju za SMS da biste pregledali"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Neke funkcije nisu dostupne"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Dodirnite da biste nastavili"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil korisnika je zaključan"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Povezano je sa proizvodom <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Dodirnite za pregled datoteka"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Zakači"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Otkači"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 297d50b..84834ee 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивен сигнал"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Използвайте тази опция в повечето случаи. Тя ви позволява да проследявате напредъка на сигнала и да въвеждате още данни за проблема. Възможно е някои по-малко използвани секции, за които подаването на сигнал отнема дълго време, да бъдат пропуснати."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Пълен сигнал"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Използвайте тази опция, за да възпрепятствате минимално работата на системата, ако устройството не реагира, функционира твърде бавно или са ви нужни всички секции за подаване на сигнал. Не можете да направите екранна снимка, нито да въведете допълнителни подробности."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Екранната снимка за сигнала за програмна грешка ще бъде направена след <xliff:g id="NUMBER_1">%d</xliff:g> секунди.</item>
       <item quantity="one">Екранната снимка за сигнала за програмна грешка ще бъде направена след <xliff:g id="NUMBER_0">%d</xliff:g> секунда.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Скрито съдържание"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Съдържанието е скрито чрез правило"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Личен"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Избиране на действие"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Избор на приложение за USB устройството"</string>
     <string name="noApplications" msgid="2991814273936504689">"Това действие не може да се изпълни от нито едно приложение."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"За съжаление <xliff:g id="APPLICATION">%1$s</xliff:g> спря."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"За съжаление процесът <xliff:g id="PROCESS">%1$s</xliff:g> спря."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Заглушаване на сривовете от <xliff:g id="PROCESS">%1$s</xliff:g> до следващото рестартиране."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> спря"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> спря"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> спира многократно"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> спира многократно"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Рестартиране на приложението"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Нулиране и рестартиране на приложението"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Изпращане на отзиви"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Затваряне"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Спиране"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Изчакване"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Затваряне на приложението"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Приложението „<xliff:g id="APPLICATION">%2$s</xliff:g>“ не отговаря.\n\nИскате ли да го затворите?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Дейността „<xliff:g id="ACTIVITY">%1$s</xliff:g>“ не отговаря.\n\nИскате ли да я затворите?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Приложението „<xliff:g id="APPLICATION">%1$s</xliff:g>“ не отговаря. Искате ли да го затворите?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Процесът „<xliff:g id="PROCESS">%1$s</xliff:g>“ не отговаря.\n\nИскате ли да го затворите?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> не реагира"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> не реагира"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> не реагира"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Процесът <xliff:g id="PROCESS">%1$s</xliff:g> не реагира"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Подаване на сигнал"</string>
     <string name="wait" msgid="7147118217226317732">"Изчакване"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM картата е добавена"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Рестартирайте устройството си, за да осъществите достъп до клетъчната мрежа."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Рестартиране"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Задаване на часа"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Задаване на дата"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Задаване"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Запитване за ПИН код преди освобождаване"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запитване за фигура за отключване преди освобождаване"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитване за парола преди освобождаване"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Приложението не може да се преоразмерява. Превъртете го с два пръста."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Приложението не може да се преоразмерява. Превъртете го с два пръста."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Приложението не поддържа разделен екран."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирано от администратора ви"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Актуализирано от администратора ви"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Изтрито от администратора ви"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Други"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Зададохте важността на тези известия."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Това е важно заради участващите хора."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" опитва да добави нов потребител, но понастоящем това е забранено."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" опитва да добави нов потребител, но ограничението за брой потребители е достигнато."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" опитва да добави нов потребител, но профилът "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" вече съществува на устройството. Да се продължи ли въпреки това?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" опитва да добави нов потребител за профила "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Да се продължи ли?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Да се разреши ли на <xliff:g id="APP">%1$s</xliff:g> да създаде нов потребител с профила <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Да се разреши ли на <xliff:g id="APP">%1$s</xliff:g> да създаде нов потребител с профила <xliff:g id="ACCOUNT">%2$s</xliff:g> (вече съществува потребител с този профил)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Езиково предпочитание"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Предпочитание за региона"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Въведете име на език"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Всички езици"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Търсене"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Работният режим е ИЗКЛЮЧЕН"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Разрешаване на функционирането на служебния потребителски профил, включително приложенията, синхронизирането на заден план и свързаните функции."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Включване"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Пакетът „%1$s“ е деактивиран"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Деактивирано от администратора на %1$s. Свържете се с него, за да научите повече."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Имате нови съобщения"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Преглед в приложението за SMS"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Някои функции може да не са налице"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Докоснете, за да продължите"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Потр. профил е заключен"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Установена е връзка с <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Докоснете, за да прегледате файловете"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Фиксиране"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Освобождаване"</string>
+    <string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string>
 </resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index b9a1cd8..db2df41 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ইন্টারেক্টিভ প্রতিবেদন"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"বেশিভাগ পরিস্থিতিতে এটিকে ব্যবহার করুন৷ এটি আপনাকে প্রতিবেদনের কাজ কতটা হয়েছে তার উপর নজর রাখতে দেয় এবং সমস্যাটির সম্পর্কে আরো অনেক কিছু লিখতে দেয়৷ এটি হয়ত প্রতিবেদন করতে খুব বেশি সময় নেয় এমন কম-ব্যবহৃত বিভাগগুলি সরিয়ে দিতে পারে৷"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"সম্পূর্ণ প্রতিবেদন"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"যখন আপনার ডিভাইসটি প্রতিক্রিয়াবিহীন থাকে বা খুবই ধীর চলে বা যখন আপনার সমস্ত প্রতিবেদন বিভাগগুলির প্রয়োজন হয় তখন ন্যূনতম সিস্টেম হস্তক্ষেপের জন্য এই বিকল্পটি ব্যবহার করুন৷ কোনো স্ক্রীনশট নেয় না বা আপনাকে আরো বিবরণ লিখতে দেয় না৷"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one"><xliff:g id="NUMBER_1">%d</xliff:g> সেকেন্ডের মধ্যে ত্রুটির প্রতিবেদনের জন্য স্ক্রীনশট নেওয়া হচ্ছে৷</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> সেকেন্ডের মধ্যে ত্রুটির প্রতিবেদনের জন্য স্ক্রীনশট নেওয়া হচ্ছে৷</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"৯৯৯+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>টি)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"লুকানো বিষয়বস্তু"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"নীতির কারণে সামগ্রী লুকানো আছে"</string>
     <string name="safeMode" msgid="2788228061547930246">"নিরাপদ মোড"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android সিস্টেম"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ব্যক্তিগত"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"একটি ক্রিয়া চয়ন করুন"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ডিভাইসটির জন্য একটি অ্যাপ্লিকেশান চয়ন করুন"</string>
     <string name="noApplications" msgid="2991814273936504689">"কোনো অ্যাপ্লিকেশানই এই ক্রিয়া সঞ্চালন করতে পারবে না৷"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"দুর্ভাগ্যবশত, <xliff:g id="APPLICATION">%1$s</xliff:g> বন্ধ হয়েছে৷"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"দুর্ভাগ্যবশত, <xliff:g id="PROCESS">%1$s</xliff:g> প্রক্রিয়াটি বন্ধ হয়েছে৷"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"পুনরায় চালু করা না পর্যন্ত, <xliff:g id="PROCESS">%1$s</xliff:g> এর থেকে নীরব ক্র্যাশগুলি৷"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> বন্ধ হয়েছে"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> বন্ধ হয়েছে"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> বারবার বন্ধ হচ্ছে"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> বারবার বন্ধ হচ্ছে"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"অ্যাপ্লিকেশান পুনরায় আরম্ভ করুন"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"পুনরায় সেট করুন এবং অ্যাপ্লিকেশান পুনরায় আরম্ভ করুন"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"প্রতিক্রিয়া পাঠান"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"বন্ধ করুন"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"নিঃশব্দ করুন"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"অপেক্ষা করুন"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"অ্যাপ্লিকেশান বন্ধ করুন"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> সাড়া দিচ্ছে না৷\n\nআপনি কি এটি বন্ধ করতে চান?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> কার্যকলাপ সাড়া দিচ্ছে না৷\n\nআপনি কি এটি বন্ধ করতে চান?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> সাড়া দিচ্ছে না৷ আপনি কি এটি বন্ধ করতে চান?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> প্রক্রিয়া সাড়া দিচ্ছে না৷\n\nআপনি কি এটি বন্ধ করতে চান?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> সাড়া দিচ্ছে না"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> সাড়া দিচ্ছে না"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> সাড়া দিচ্ছে না"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> প্রক্রিয়া সাড়া দিচ্ছে না"</string>
     <string name="force_close" msgid="8346072094521265605">"ঠিক আছে"</string>
     <string name="report" msgid="4060218260984795706">"প্রতিবেদন করুন"</string>
     <string name="wait" msgid="7147118217226317732">"অপেক্ষা করুন"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"সিম কার্ড যোগ করা হয়েছে"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"সেলুলার নেটওয়ার্ক অ্যাক্সেস করতে আপনার ডিভাইস পুনর্সূচনা করুন"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"পুনর্সূচনা"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"যাতে আপনার নতুন SIM সঠিকভাবে কাজ করে, তার জন্য আপনাকে আপনার পরিষেবা প্রদানকারীর থেকে একটি অ্যাপ্লিকেশান ইনস্টল করতে এবং খুলতে হবে৷"</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"অ্যাপ্লিকেশানটি পান"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"এখনই নয়"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"নতুন SIM ঢোকানো হয়েছে"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"এটিকে সেট আপ করতে আলতো চাপুন"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"সময় সেট করুন"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"তারিখ সেট করুন"</string>
     <string name="date_time_set" msgid="5777075614321087758">"সেট করুন"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"আনপিন করার আগে পিন চান"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"আনপিন করার আগে আনলক প্যাটার্ন চান"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"আনপিন করার আগে পাসওয়ার্ড চান"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"অ্যাপ্লিকেশানকে পুনরায় আকার দেওয়া যাবে না, দুটি আঙ্গুল ব্যবহার করে স্ক্রোল করুন৷"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"অ্যাপ্লিকেশানকে পুনরায় আকার দেওয়া যাবে না, দুটি আঙ্গুল ব্যবহার করে স্ক্রোল করুন৷"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"অ্যাপ্লিকেশান বিভক্ত-স্ক্রীন সমর্থন করে না৷"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"আপনার প্রশাসক দ্বারা ইনস্টল করা হয়েছে"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"আপনার প্রশাসক দ্বারা আপডেট করা হয়েছে"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"আপনার প্রশাসক দ্বারা মুছে ফেলা হয়েছে"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"বিবিধ"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"আপনি এই বিজ্ঞপ্তিগুলির গুরুত্ব সেট করেছেন।"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"লোকজন জড়িত থাকার কারণে এটি গুরুত্বপূর্ণ।"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" একজন নতুন ব্যবহারকারীকে যোগ করার চেষ্টা করছে, তবে বর্তমানে তা নিষিদ্ধ।"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" একজন নতুন ব্যবহারকারী যোগ করার চেষ্টা করছে, তবে ব্যবহারকারীর সীমা অতিক্রান্ত হয়েছে।"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" একজন নতুন ব্যবহারকারীকে যোগ করার চেষ্টা করছে, তবে "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" অ্যাকাউন্ট আগে থেকেই এই ডিভাইসটিতে বিদ্যমান আছে। তবুও এগোতে চান?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" অ্যাকাউন্টের জন্য একজন নতুন ব্যবহারকারীকে যোগ করার চেষ্টা করছে। এগোতে চান?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> কে <xliff:g id="ACCOUNT">%2$s</xliff:g> এর সাথে একজন নতুন ব্যবহারকারী তৈরি করার অনুমতি দেবেন কি?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> কে <xliff:g id="ACCOUNT">%2$s</xliff:g> (একজন ব্যবহারকারী এই অ্যাকাউন্টে ইতিমধ্যেই বিদ্যমান আছেন) এর সাথে একজন নতুন ব্যবহারকারী তৈরি করার অনুমতি দেবেন কি?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"পছন্দের ভাষা"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"পছন্দের অঞ্চল"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ভাষার নাম লিখুন"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"প্রস্তাবিত"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"সকল ভাষা"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"অনুসন্ধান করুন"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"কাজের মোড বন্ধ আছে"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"অ্যাপ্লিকেশান, পটভূমি সিঙ্ক এবং সম্পর্কিত বৈশিষ্ট্যগুলি সহ কর্মস্থলের প্রোফাইলটিকে কাজ করার মঞ্জুরি দিন।"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"চালু করুন"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s অক্ষম করা আছে"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s প্রশাসক অক্ষম করেছেন। আরো জানতে তাদের সাথে যোগাযোগ করুন।"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"আপনার নতুন বার্তা আছে"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"দেখার জন্য SMS অ্যাপ্লিকেশান খুলুন"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"কিছু ক্রিয়াকলাপ উপলব্ধ নাও হতে পারে"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"অবিরত রাখতে স্পর্শ করুন"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"ব্যবহারকারীর প্রোফাইল লক করা আছে"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> এর সাথে সংযুক্ত হয়েছে"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ফাইলগুলি দেখতে আলতো চাপ দিন"</string>
+    <string name="pin_target" msgid="3052256031352291362">"পিন করুন"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"আনপিন করুন"</string>
+    <string name="app_info" msgid="6856026610594615344">"অ্যাপ্লিকেশানের তথ্য"</string>
 </resources>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index 6a5ef12..7a1c9880 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -397,8 +397,7 @@
     <skip />
     <!-- no translation found for bugreport_option_full_title (6354382025840076439) -->
     <skip />
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Ta opcija vam omogućava minimalno ometanje sustava kad uređaj ne reagira ili je prespor ili kada su vam potrebni svi odjeljci izvještaja. Ne izrađuje se snimka ekrana i ne možete unijeti više detalja."</string>
     <!-- no translation found for bugreport_countdown (6878900193900090368) -->
     <!-- no translation found for global_action_toggle_silent_mode (8219525344246810925) -->
     <skip />
@@ -426,6 +425,7 @@
     <skip />
     <!-- no translation found for notification_hidden_text (1135169301897151909) -->
     <skip />
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj skriven u skladu sa pravilima"</string>
     <!-- no translation found for safeMode (2788228061547930246) -->
     <skip />
     <!-- no translation found for android_system_label (6577375335728551336) -->
@@ -1693,22 +1693,22 @@
     <skip />
     <!-- no translation found for noApplications (2991814273936504689) -->
     <skip />
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <!-- no translation found for aerr_application (932628488013092776) -->
-    <skip />
-    <!-- no translation found for aerr_process (4507058997035697579) -->
-    <skip />
-    <!-- no translation found for aerr_process_silence (4226685530196000222) -->
-    <skip />
+    <string name="aerr_application" msgid="250320989337856518">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> je zaustavljena"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Aplikacija <xliff:g id="PROCESS">%1$s</xliff:g> je zaustavljena"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> se stalno zaustavlja"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> se stalno zaustavlja"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Ponovo pokreni aplikaciju"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Vrati aplikaciju na zadano i pokreni ponovo"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Pošalji povratne informacije"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Zatvori"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Zanemari"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Sačekaj"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Zatvori aplikaciju"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <!-- no translation found for anr_activity_application (1904477189057199066) -->
-    <skip />
-    <!-- no translation found for anr_activity_process (5776209883299089767) -->
-    <skip />
-    <!-- no translation found for anr_application_process (8941757607340481057) -->
-    <skip />
-    <!-- no translation found for anr_process (6513209874880517125) -->
-    <skip />
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ne reaguje"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ne reaguje"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ne reaguje"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> ne reaguje"</string>
     <!-- no translation found for force_close (8346072094521265605) -->
     <skip />
     <!-- no translation found for report (4060218260984795706) -->
@@ -1905,6 +1905,16 @@
     <skip />
     <!-- no translation found for sim_restart_button (4722407842815232347) -->
     <skip />
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <!-- no translation found for time_picker_dialog_title (8349362623068819295) -->
     <skip />
     <!-- no translation found for date_picker_dialog_title (5879450659453782278) -->
@@ -2754,8 +2764,8 @@
     <skip />
     <!-- no translation found for lock_to_app_unlock_password (6380979775916974414) -->
     <skip />
-    <!-- no translation found for dock_non_resizeble_text (9156251681042762723) -->
-    <skip />
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veličina aplikacije nije promjenjiva, pomičite je s dva prsta."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podržava dijeljenje ekrana."</string>
     <!-- no translation found for package_installed_device_owner (8420696545959087545) -->
     <skip />
     <!-- no translation found for package_updated_device_owner (8856631322440187071) -->
@@ -2835,14 +2845,8 @@
     <skip />
     <!-- no translation found for importance_from_person (9160133597262938296) -->
     <skip />
-    <!-- no translation found for user_creation_cannot_add (7740333663230045315) -->
-    <skip />
-    <!-- no translation found for user_creation_cannot_add_any_more (6244197709981359266) -->
-    <skip />
-    <!-- no translation found for user_creation_account_exists (4880171855014489789) -->
-    <skip />
-    <!-- no translation found for user_creation_adding (3206420861363021392) -->
-    <skip />
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Da li dozvoljate da <xliff:g id="APP">%1$s</xliff:g> kreira novog korisnika za nalog <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Da li dozvoljavate da <xliff:g id="APP">%1$s</xliff:g> kreira novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g> (Korisnik sa ovim nalogom već postoji)?"</string>
     <!-- no translation found for language_selection_title (7181332986330337171) -->
     <skip />
     <!-- no translation found for country_selection_title (2954859441620215513) -->
@@ -2855,4 +2859,19 @@
     <skip />
     <!-- no translation found for locale_search_menu (2560710726687249178) -->
     <skip />
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Radni način je ISKLJUČEN"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Omogućava radnom profilu da funkcioniše, uključujući aplikacije, sinhronizaciju u pozadini i povezane funkcije."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s – onemogućeno"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Onemogućio administrator (%1$s). Obratite mu se za više informacija."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite SMS aplikaciju da biste pregledali poruke"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Neke funkcije možda neće biti dostupne"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Dodirnite da biste nastavili"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil korisnika je zaključan"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Povezan na <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Dodirnite za prikaz datoteka"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Zakači"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Otkači"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 602532c..0f971b2 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -212,10 +212,9 @@
     <string name="bugreport_title" msgid="2667494803742548533">"Crea informe d\'errors"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Es recopilarà informació sobre l\'estat actual del dispositiu i se t\'enviarà per correu electrònic. Passaran uns quants minuts des de l\'inici de l\'informe d\'errors fins al seu enviament, per la qual cosa et recomanem que tinguis paciència."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactiu"</string>
-    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Utilitza aquesta opció en la majoria de circumstàncies. Et permet fer un seguiment del progrés de l\'informe i introduir més dades sobre el problema. És possible que ometi seccions menys utilitzades que requereixen molt de temps i que no n\'informi."</string>
+    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Utilitza aquesta opció en la majoria de circumstàncies. Et permet fer un seguiment del progrés de l\'informe i introduir més dades sobre el problema. És possible que ometi seccions poc utilitzades que requereixen molt de temps."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Informe complet"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Utilitza aquesta opció perquè la interferència en el sistema sigui mínima si el dispositiu no respon o va massa lent, o bé si necessites totes les seccions de l\'informe. No fa cap captura de pantalla ni et permet introduir més detalls."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Es farà una captura de pantalla de l\'informe d\'errors d\'aquí a <xliff:g id="NUMBER_1">%d</xliff:g> segons.</item>
       <item quantity="one">Es farà una captura de pantalla de l\'informe d\'errors d\'aquí a <xliff:g id="NUMBER_0">%d</xliff:g> segon.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contingut amagat"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contingut amagat de conformitat amb la política"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Tria una acció"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Tria una aplicació per al dispositiu USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"No hi ha cap aplicació que pugui dur a terme aquesta acció."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"<xliff:g id="APPLICATION">%1$s</xliff:g> s\'ha aturat."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"El procés <xliff:g id="PROCESS">%1$s</xliff:g> s\'ha aturat."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silencia la informació de bloqueig de l\'aplicació <xliff:g id="PROCESS">%1$s</xliff:g> fins que es reiniciï."</string>
+    <string name="aerr_application" msgid="250320989337856518">"S\'ha aturat l\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> s\'ha aturat"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"L\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> s\'atura contínuament"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"El procés <xliff:g id="PROCESS">%1$s</xliff:g> s\'atura contínuament"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Reinicia l\'aplicació"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Restableix i reinicia l\'aplicació"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Envia suggeriments"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Tanca"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Silencia"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Espera"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Tanca l\'aplicació"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> no respon.\n\nVols tancar-la?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"L\'activitat <xliff:g id="ACTIVITY">%1$s</xliff:g> no respon.\n\nVols tancar-la?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> no respon. Vols tancar-la?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"El procés <xliff:g id="PROCESS">%1$s</xliff:g> no respon.\n\nVols tancar-lo?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"L\'aplicació <xliff:g id="APPLICATION">%2$s</xliff:g> no respon"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"L\'activitat <xliff:g id="ACTIVITY">%1$s</xliff:g> no respon"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"L\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> no respon"</string>
+    <string name="anr_process" msgid="6156880875555921105">"El procés <xliff:g id="PROCESS">%1$s</xliff:g> no respon"</string>
     <string name="force_close" msgid="8346072094521265605">"D\'acord"</string>
     <string name="report" msgid="4060218260984795706">"Informe"</string>
     <string name="wait" msgid="7147118217226317732">"Espera"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Addició de la targeta SIM"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Reinicia el dispositiu per accedir a la xarxa mòbil."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reinicia"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Defineix l\'hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Establiment de data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Defineix"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Sol·licita el codi PIN per anul·lar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sol·licita el patró de desbloqueig per anul·lar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demana la contrasenya per anul·lar"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"No es pot canviar la mida de l\'aplicació. Desplaça-la amb dos dits."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"No es pot canviar la mida de l\'aplicació. Desplaça-la amb dos dits."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'aplicació no admet la pantalla dividida."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"L\'administrador ho ha instal·lat"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"L\'administrador l\'ha actualitzat"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"L\'administrador ho ha suprimit"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Altres"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Tu has definit la importància d\'aquestes notificacions."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Aquest missatge és important per les persones implicades."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" està provant d\'afegir un usuari, però actualment aquesta acció no està permesa."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" està provant d\'afegir un usuari, però s\'ha assolit el límit d\'usuaris."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" està provant d\'afegir un usuari, però el compte "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ja existeix en aquest dispositiu. Vols continuar igualment?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" està provant d\'afegir un usuari per al compte "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Vols continuar?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Concedeixes permís a <xliff:g id="APP">%1$s</xliff:g> per crear un usuari amb el compte <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Concedeixes permís a <xliff:g id="APP">%1$s</xliff:g> per crear un usuari amb el compte <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Ja hi ha un usuari amb aquest compte.)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferència d\'idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferència de regió"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Nom de l\'idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggerits"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Tots els idiomes"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Cerca"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Mode de feina desactivat"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Permet que el perfil professional funcioni, incloses les aplicacions, la sincronització en segon pla i les funcions relacionades."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Activa"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Aplicació %1$s desactivada"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"L\'administrador de l\'empresa %1$s ha desactivat el paquet. Contacta-hi per obtenir-ne més informació."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Tens missatges nous"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Obre l\'aplicació de SMS per veure\'ls"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Hi pot haver funcions no disponibles"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Toca per continuar"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Perfil d\'usuari bloquejat"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"S\'ha connectat a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Toca per veure els fitxers"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fixa"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"No fixis"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 4c830f9..d071646 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -216,8 +216,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivní přehled"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Tato možnost se používá ve většině případů. Umožňuje sledovat průběh přehledu a zadat další podrobnosti o problému. Mohou být vynechány některé méně používané sekce, jejichž kontrola trvá dlouho."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Úplný přehled"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Tato možnost slouží k rychlému nahlášení, když zařízení neodpovídá, je příliš pomalé nebo pokud potřebujete zahrnout všechny sekce. Tímto způsobem nelze pořídit snímek obrazovky ani zadat další podrobnosti."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="few">Snímek obrazovky pro zprávu o chybě bude pořízen za <xliff:g id="NUMBER_1">%d</xliff:g> sekundy.</item>
       <item quantity="many">Snímek obrazovky pro zprávu o chybě bude pořízen za <xliff:g id="NUMBER_1">%d</xliff:g> sekundy.</item>
@@ -237,6 +236,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Skrytý obsah"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Obsah skrytý zásadami"</string>
     <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osobní"</string>
@@ -921,15 +921,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Vyberte akci"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Vyberte aplikaci pro zařízení USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Tuto činnost nemohou provádět žádné aplikace."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> bohužel přestala pracovat."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> byl bohužel ukončen."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Selhání aplikace Silence kvůli procesu <xliff:g id="PROCESS">%1$s</xliff:g> potrvá do restartování."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> přestala fungovat"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> přestal fungovat"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> pravidelně přestává fungovat"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Aplikace <xliff:g id="PROCESS">%1$s</xliff:g> pravidelně přestává fungovat"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Restartovat aplikaci"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Obnovit a restartovat aplikaci"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Odeslat zpětnou vazbu"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Zavřít"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorovat"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Počkat"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Zavřít aplikaci"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Aplikace <xliff:g id="APPLICATION">%2$s</xliff:g> nereaguje.\n\nChcete ji ukončit?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktivita <xliff:g id="ACTIVITY">%1$s</xliff:g> nereaguje.\n\nChcete ji ukončit?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> nereaguje. Chcete ji ukončit?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> nereaguje.\n\nChcete jej ukončit?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"Aplikace <xliff:g id="APPLICATION">%2$s</xliff:g> nereaguje"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"Aktivita <xliff:g id="ACTIVITY">%1$s</xliff:g> nereaguje"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> nereaguje"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> nereaguje"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Hlášení"</string>
     <string name="wait" msgid="7147118217226317732">"Počkat"</string>
@@ -1040,6 +1047,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM karta přidána."</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Mobilní síť bude přístupná po restartu zařízení."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Restartovat"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastavit čas"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavení data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nastavit"</string>
@@ -1475,7 +1492,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Před uvolněním požádat o PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Před uvolněním požádat o bezpečnostní gesto"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Před uvolněním požádat o heslo"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Velikost aplikace nelze změnit. Zobrazení můžete posouvat dvěma prsty."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Velikost aplikace nelze změnit. Zobrazení můžete posouvat dvěma prsty."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikace nepodporuje režim rozdělené obrazovky."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Nainstalováno administrátorem"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Aktualizováno administrátorem"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Smazáno administrátorem"</string>
@@ -1565,14 +1583,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Různé"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Důležitost oznámení určujete vy."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Tato zpráva je důležitá kvůli lidem zapojeným do konverzace."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"Aplikace "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" se pokouší přidat nového uživatele, avšak v tuto chvíli je zakázána."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"Aplikace "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" se pokouší přidat nového uživatele, avšak byl dosažen maximální počet uživatelů."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"Aplikace "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" se pokouší přidat nového uživatele, avšak účet "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" již v zařízení existuje. Chcete přesto pokračovat?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392">"Aplikace "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" se pro účet "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" pokouší přidat nového uživatele. Pokračovat?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Povolit aplikaci <xliff:g id="APP">%1$s</xliff:g> vytvořit nového uživatele s účtem <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Povolit aplikaci <xliff:g id="APP">%1$s</xliff:g> vytvořit nového uživatele s účtem <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Uživatel s tímto účtem již existuje.)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferovaný jazyk"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferovaná oblast"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Zadejte název jazyka"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Navrhované"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Všechny jazyky"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Vyhledávání"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Pracovní režim je VYPNUTÝ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Povolí fungování pracovního profilu, včetně aplikací, synchronizace na pozadí a souvisejících funkcí."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Zapnout"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Balíček %1$s byl zakázán"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Zakázáno administrátorem zařízení %1$s. Chcete-li získat další informace, kontaktujte jej."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Máte nové zprávy"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Zobrazíte je v aplikaci pro SMS"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Některé funkce nemusí být k dispozici"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Pokračujte klepnutím"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Uživatelský profil je uzamčen"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Připojeno k zařízení <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Klepnutím zobrazíte soubory"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Připnout"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Odepnout"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informace o aplikaci"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 164ae6b..4a3780c 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv rapport"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Brug dette workflow under de fleste omstændigheder. Det giver dig mulighed for at se status på rapporten og angive flere oplysninger om problemet. Nogle mindre brugte sektioner, der tager lang tid at rapportere, udelades muligvis."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Fuld rapport"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Brug denne mulighed for at gribe mindst muligt ind, når enheden ikke reagerer eller er for langsom, eller når du har brug for alle rapportsektioner. Der tages ikke et skærmbillede, og du kan ikke angive flere oplysninger."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Der tages et skærmbillede til fejlrapporten om <xliff:g id="NUMBER_1">%d</xliff:g> sekund.</item>
       <item quantity="other">Der tages et skærmbillede til fejlrapporten om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Indholdet er skjult"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Indholdet er skjult af politikken"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personlig"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Vælg en handling"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Vælg en app til USB-enheden"</string>
     <string name="noApplications" msgid="2991814273936504689">"Der er ingen apps, der kan foretage denne handling."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Applikationen <xliff:g id="APPLICATION">%1$s</xliff:g> er desværre stoppet."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> er desværre stoppet."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Appen Silence går ned som følge af <xliff:g id="PROCESS">%1$s</xliff:g>, indtil der genstartes."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> er stoppet"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> er stoppet"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> bliver ved med at stoppe"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> bliver ved med at stoppe"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Genstart appen"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Nulstil og genstart appen"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Send feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Luk"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorer"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Vent"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Luk app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> svarer ikke.\n\nVil du lukke den?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktiviteten <xliff:g id="ACTIVITY">%1$s</xliff:g> svarer ikke.\n\nVil du at lukke den?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> svarer ikke. Vil du lukke den?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> svarer ikke.\n\nVil du lukke den?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> svarer ikke"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> svarer ikke"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> svarer ikke"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> svarer ikke"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Rapportér"</string>
     <string name="wait" msgid="7147118217226317732">"Vent"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-kort blev tilføjet"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Genstart din enhed for at få adgang til mobilnetværket."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Genstart"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Du skal installere og åbne en app fra dit mobilselskab for at få dit nye SIM-kort til at fungere korrekt."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"HENT APPEN"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"IKKE NU"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Nyt SIM-kort er indsat"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Tryk for at konfigurere"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Angiv tidspunkt"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angiv dato"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Angiv"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Bed om pinkode inden frigørelse"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bed om oplåsningsmønster ved deaktivering"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bed om adgangskode inden frigørelse"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Appens størrelse kan ikke ændres. Gennemgå den ved at rulle med to fingre."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Appens størrelse kan ikke ændres. Gennemgå den ved at rulle med to fingre."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen understøtter ikke delt skærm."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installeret af din administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Opdateret af administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Slettet af din administrator"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Du angiver, hvor vigtige disse underretninger er."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Dette er vigtigt på grund af de personer, det handler om."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" forsøger at tilføje en ny bruger, men det er i øjeblikket forbudt."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" forsøger at tilføje en ny bruger, men grænsen for antal brugere er nået."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" forsøger at tilføje en ny bruger, men kontoen "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" findes allerede på denne enhed. Vil du fortsætte?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" forsøger at føje en ny bruger til kontoen "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Vil du fortsætte?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Vil du give <xliff:g id="APP">%1$s</xliff:g> tilladelse til at oprette en ny bruger med <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Vil du give <xliff:g id="APP">%1$s</xliff:g> tilladelse til at oprette en ny bruger med <xliff:g id="ACCOUNT">%2$s</xliff:g> (der findes allerede en bruger med denne konto)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Sprogindstilling"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Områdeindstilling"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Angiv sprogets navn"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Foreslået"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Alle sprog"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Søg"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Arbejdstilstand er slået FRA"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Tillad, at arbejdsprofilen aktiveres, bl.a. i forbindelse med apps, baggrundssynkronisering og relaterede funktioner."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Slå til"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s er deaktiveret"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Deaktiveret af %1$s administrator. Kontakt vedkommende for at få flere oplysninger."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nye beskeder"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Åbn sms-appen for at se beskeden"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Nogle funktioner er muligvis ikke tilgængelige"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Tryk for at fortsætte"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Brugerprofilen er låst"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Tilsluttet <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Tryk for at se filer"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fastgør"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Frigør"</string>
+    <string name="app_info" msgid="6856026610594615344">"Oplysninger om appen"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 4f43c2a..f04521f 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -191,7 +191,7 @@
     <string name="reboot_to_update_prepare" msgid="6305853831955310890">"Aktualisierung wird vorbereitet…"</string>
     <string name="reboot_to_update_package" msgid="3871302324500927291">"Updatepaket wird verarbeitet…"</string>
     <string name="reboot_to_update_reboot" msgid="6428441000951565185">"Neustart…"</string>
-    <string name="reboot_to_reset_title" msgid="4142355915340627490">"Auf Werkszustand zurück"</string>
+    <string name="reboot_to_reset_title" msgid="4142355915340627490">"Auf Werkszustand zurücksetzen"</string>
     <string name="reboot_to_reset_message" msgid="2432077491101416345">"Neustart…"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Wird heruntergefahren..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Dein Tablet wird heruntergefahren."</string>
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiver Bericht"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Diese Option kann in den meisten Fällen verwendet werden. Du kannst darüber den aktuellen Stand der Berichterstellung verfolgen und genauere Angaben zu dem Problem machen. Einige selten genutzte Bereiche, deren Berichterstellung längere Zeit in Anspruch nimmt, werden unter Umständen ausgelassen."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Vollständiger Bericht"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Du kannst diese Option für minimale Störungen des Systems nutzen, wenn dein Gerät beispielsweise nicht reagiert oder zu langsam ist oder wenn du alle Bereiche für Berichte benötigst. Es wird kein Screenshot aufgenommen und du kannst keine weiteren Angaben machen."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Screenshot für den Fehlerbericht wird in <xliff:g id="NUMBER_1">%d</xliff:g> Sekunden aufgenommen.</item>
       <item quantity="one">Screenshot für den Fehlerbericht wird in <xliff:g id="NUMBER_0">%d</xliff:g> Sekunde aufgenommen.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Inhalte ausgeblendet"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Inhalte aufgrund der Richtlinien ausgeblendet"</string>
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Privat"</string>
@@ -909,17 +909,24 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Aktion auswählen"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"App für USB-Gerät auswählen"</string>
     <string name="noApplications" msgid="2991814273936504689">"Diese Aktion kann von keiner App ausgeführt werden."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"\"<xliff:g id="APPLICATION">%1$s</xliff:g>\" wurde beendet."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Der Prozess \"<xliff:g id="PROCESS">%1$s</xliff:g>\" wurde beendet."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silence stürzt bei <xliff:g id="PROCESS">%1$s</xliff:g> bis zum Neustart ab."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> wurde beendet"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> wurde beendet"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> wird wiederholt beendet"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> wird wiederholt beendet"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"App neu starten"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"App zurücksetzen und neu starten"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Feedback geben"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Schließen"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorieren"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Warten"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"App schließen"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> reagiert nicht.\n\nMöchtest du die App schließen?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktivität \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\" reagiert nicht.\n\nMöchtest du sie beenden?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> reagiert nicht. Möchtest du die App schließen?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Prozess \"<xliff:g id="PROCESS">%1$s</xliff:g>\" reagiert nicht.\n\nMöchtest du ihn beenden?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> reagiert nicht"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> reagiert nicht"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> reagiert nicht"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Der Prozess <xliff:g id="PROCESS">%1$s</xliff:g> reagiert nicht"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
-    <string name="report" msgid="4060218260984795706">"Bericht"</string>
+    <string name="report" msgid="4060218260984795706">"Melden"</string>
     <string name="wait" msgid="7147118217226317732">"Warten"</string>
     <string name="webpage_unresponsive" msgid="3272758351138122503">"Die Seite reagiert nicht mehr.\n\nMöchtest du die Seite schließen?"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"App umgeleitet"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-Karte hinzugefügt"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Starte zur Nutzung des Mobilfunknetzes dein Gerät neu."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Neu starten"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Damit deine neue SIM-Karte ordnungsgemäß funktioniert, musst du zuerst eine App deines Mobilfunkanbieters installieren und öffnen."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"APP HERUNTERLADEN"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"JETZT NICHT"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Neue SIM-Karte eingelegt"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Zum Einrichten tippen"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Uhrzeit festlegen"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum festlegen"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Speichern"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Vor dem Beenden nach PIN fragen"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Vor dem Beenden nach Entsperrungsmuster fragen"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vor dem Beenden nach Passwort fragen"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Die Größe der App kann nicht angepasst werden. Scrolle sie mit zwei Fingern."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Die Größe der App kann nicht angepasst werden. Scrolle sie mit zwei Fingern."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Das Teilen des Bildschirms wird in dieser App nicht unterstützt."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Von deinem Administrator installiert"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Von deinem Administrator aktualisiert"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Von deinem Administrator gelöscht"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Sonstige"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Du legst die Wichtigkeit dieser Benachrichtigungen fest."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Diese Benachrichtigung ist aufgrund der beteiligten Personen wichtig."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" versucht, einen neuen Nutzer hinzuzufügen. Dieser Vorgang ist momentan nicht zulässig."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" versucht, einen neuen Nutzer hinzuzufügen. Die maximal zulässige Anzahl an Nutzern ist aber schon erreicht."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" versucht, einen neuen Nutzer hinzuzufügen, aber das Konto "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" besteht bereits auf diesem Gerät. Trotzdem fortfahren?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" versucht, einen neuen Nutzer für das Konto "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" hinzuzufügen. Fortfahren?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Möchtest du zulassen, dass <xliff:g id="APP">%1$s</xliff:g> einen neuen Nutzer mit <xliff:g id="ACCOUNT">%2$s</xliff:g> erstellt?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Möchtest du zulassen, dass <xliff:g id="APP">%1$s</xliff:g> einen neuen Nutzer mit <xliff:g id="ACCOUNT">%2$s</xliff:g> erstellt? Dieses Konto wird jedoch bereits von einem anderen Nutzer verwendet."</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Spracheinstellung"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region auswählen"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Sprache eingeben"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Vorschläge"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Alle Sprachen"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Suche"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Arbeitsmodus ist AUS"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Arbeitsprofil aktivieren, einschließlich Apps, Synchronisierung im Hintergrund und verknüpfter Funktionen."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivieren"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s deaktiviert"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Durch den Administrator von %1$s deaktiviert. Setze dich für weitere Informationen mit ihm in Verbindung."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Du hast neue Nachrichten"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Zum Ansehen SMS-App öffnen"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Einige Funktionen sind evtl. nicht verfügbar"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Zum Fortfahren tippen"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Nutzerprofil gesperrt"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Verbunden mit <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Zum Ansehen der Dateien tippen"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Markieren"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Markierung entfernen"</string>
+    <string name="app_info" msgid="6856026610594615344">"App-Informationen"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index d572e22..c557c73 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Διαδραστική αναφορά"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Χρησιμοποιήστε αυτήν την επιλογή στις περισσότερες περιπτώσεις. Σας επιτρέπει να παρακολουθείτε την πρόοδο της αναφοράς και να εισάγετε περισσότερες λεπτομέρειες σχετικά με το πρόβλημα που αντιμετωπίζετε. Ενδέχεται να παραλείψει ορισμένες ενότητες που δεν χρησιμοποιούνται συχνά και για τις οποίες απαιτείται μεγάλο χρονικό διάστημα για τη δημιουργία αναφορών."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Πλήρης αναφορά"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Χρησιμοποιήστε αυτήν την επιλογή για την ελάχιστη δυνατή παρέμβαση συστήματος, όταν η συσκευή σας δεν ανταποκρίνεται ή παρουσιάζει μεγάλη καθυστέρηση στη λειτουργία ή όταν χρειάζεστε όλες τις ενότητες αναφοράς. Δεν λαμβάνει στιγμιότυπο οθόνης και δεν σας επιτρέπει να προσθέσετε περισσότερες λεπτομέρειες."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Λήψη στιγμιότυπου οθόνης για αναφορά σφαλμάτων σε <xliff:g id="NUMBER_1">%d</xliff:g> δευτερόλεπτα.</item>
       <item quantity="one">Λήψη στιγμιότυπου οθόνης για αναφορά σφαλμάτων σε <xliff:g id="NUMBER_0">%d</xliff:g> δευτερόλεπτο.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Κρυφό περιεχόμενο"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Το περιεχόμενο είναι κρυφό βάσει πολιτικής"</string>
     <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Προσωπικό"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Επιλέξτε μια ενέργεια"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Επιλέξτε μια εφαρμογή για τη συσκευή USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Δεν υπάρχουν εφαρμογές, οι οποίες μπορούν να εκτελέσουν αυτήν την ενέργεια."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Δυστυχώς, η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> έχει σταματήσει."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Δυστυχώς, η διαδικασία <xliff:g id="PROCESS">%1$s</xliff:g> έχει σταματήσει."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Η σίγαση διακόπτεται από <xliff:g id="PROCESS">%1$s</xliff:g> μέχρι την επανεκκίνηση."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Η λειτουργία της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> διακόπηκε"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Η διαδικασία <xliff:g id="PROCESS">%1$s</xliff:g> έχει διακοπεί"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"Η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> διακόπτεται επανειλημμένα"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Η διαδικασία <xliff:g id="PROCESS">%1$s</xliff:g> διακόπτεται επανειλημμένα"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Επανεκκίνηση εφαρμογής"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Επαναφορά και επανεκκίνηση εφαρμογής"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Αποστολή σχολίων"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Κλείσιμο"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Σίγαση"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Αναμονή"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Κλείσιμο εφαρμογής"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Η εφαρμογή <xliff:g id="APPLICATION">%2$s</xliff:g> δεν ανταποκρίνεται.\n\nΘέλετε να την κλείσετε;"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Η δραστηριότητα <xliff:g id="ACTIVITY">%1$s</xliff:g> δεν ανταποκρίνεται.\n\nΘέλετε να την κλείσετε;"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> δεν ανταποκρίνεται. Θέλετε να την κλείσετε;"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Η διεργασία <xliff:g id="PROCESS">%1$s</xliff:g> δεν ανταποκρίνεται.\n\nΘέλετε να την κλείσετε;"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"Η εφαρμογή <xliff:g id="APPLICATION">%2$s</xliff:g> δεν ανταποκρίνεται"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"Η δραστηριότητα <xliff:g id="ACTIVITY">%1$s</xliff:g> δεν ανταποκρίνεται"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"Η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> δεν ανταποκρίνεται"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Η διαδικασία <xliff:g id="PROCESS">%1$s</xliff:g> δεν ανταποκρίνεται"</string>
     <string name="force_close" msgid="8346072094521265605">"ΟΚ"</string>
     <string name="report" msgid="4060218260984795706">"Αναφορά"</string>
     <string name="wait" msgid="7147118217226317732">"Αναμονή"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Προστέθηκε κάρτα SIM"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Επανεκκινήστε τη συσκευή σας, για να αποκτήσετε πρόσβαση στο δίκτυο κινητής τηλεφωνίας."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Επανεκκίνηση"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Για να λειτουργεί σωστά η νέα κάρτα SIM, θα πρέπει να εγκαταστήσετε και να ανοίξετε μια εφαρμογή από την εταιρεία κινητής τηλεφωνίας που χρησιμοποιείτε."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ΛΗΨΗ ΤΗΣ ΕΦΑΡΜΟΓΗΣ"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"ΟΧΙ ΤΩΡΑ"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Τοποθετήθηκε νέα SIM"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Πατήστε για ρύθμιση"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ρύθμιση ώρας"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ορισμός ημερομηνίας"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ορισμός"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Να γίνεται ερώτηση για το PIN, πριν από το ξεκαρφίτσωμα"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Να γίνεται ερώτηση για το μοτίβο ξεκλειδώματος, πριν από το ξεκαρφίτσωμα"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Το μέγεθος της εφαρμογής δεν είναι προσαρμόσιμο. Σύρετε προς τα κάτω με δύο δάχτυλα."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Το μέγεθος της εφαρμογής δεν είναι προσαρμόσιμο. Σύρετε προς τα κάτω με δύο δάχτυλα."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Η εφαρμογή δεν υποστηρίζει διαχωρισμό οθόνης."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Εγκαταστάθηκε από το διαχειριστή σας"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ενημερώθηκε από το διαχειριστή σας"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Διαγράφηκε από το διαχειριστή σας"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Διάφορα"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Μπορείτε να ρυθμίσετε τη βαρύτητα αυτών των ειδοποιήσεων."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Αυτό είναι σημαντικό λόγω των ατόμων που συμμετέχουν."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"Το "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" προσπαθεί να προσθέσει έναν νέο χρήστη, αλλά προς το παρόν αυτό απαγορεύεται."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"Το "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" προσπαθεί να προσθέσει έναν νέο χρήστη, αλλά έχετε φτάσει το όριο χρηστών."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"Το "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" προσπαθεί να προσθέσει έναν νέο χρήστη, αλλά ο λογαριασμός "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" υπάρχει ήδη σε αυτήν τη συσκευή. Θέλετε να συνεχίσετε ούτως ή άλλως;"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392">"Το "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" προσπαθεί να προσθέσει έναν νέο χρήστη για το λογαριασμό "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Θέλετε να συνεχίσετε;"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Να επιτραπεί στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> να δημιουργήσει έναν νέο χρήστη με το λογαριασμό <xliff:g id="ACCOUNT">%2$s</xliff:g>;"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Να επιτραπεί στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g> να δημιουργήσει έναν νέο χρήστη με το λογαριασμό <xliff:g id="ACCOUNT">%2$s</xliff:g> (υπάρχει ήδη χρήστης με αυτόν το λογαριασμό);"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Προτίμηση γλώσσας"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Προτίμηση περιοχής"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Εισαγ. όνομα γλώσσας"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Προτεινόμενες"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Όλες οι γλώσσες"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Αναζήτηση"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Λειτουργία εργασίας ΑΠΕΝΕΡΓ/ΝΗ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Να επιτρέπεται η λειτουργία του προφίλ εργασίας σας, συμπεριλαμβανομένων των εφαρμογών, του συγχρονισμού στο παρασκήνιο και των σχετικών λειτουργιών."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Ενεργοποίηση"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Το %1$s απενεργοποιήθηκε"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Απενεργοποιήθηκε από το διαχειριστή της συσκευής %1$s. Επικοινωνήστε με το διαχειριστή για να μάθετε περισσότερα."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Έχετε νέα μηνύματα"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Άνοιγμα της εφαρμογής SMS για προβολή"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Ενδεχόμενο μη διαθέσιμων λειτουργιών"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Αγγίξτε για συνέχεια"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Το προφίλ χρήστη κλειδώθηκε"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Συνδέθηκε με το <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Πατήστε για να δείτε τα αρχεία"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Καρφίτσωμα"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Ξεκαρφίτσωμα"</string>
+    <string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string>
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index ee7dd71..a0a5493 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactive report"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Use this under most circumstances. It allows you to track progress of the report and enter more details about the problem. It might omit some less-used sections that take a long time to report."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Full report"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Use this option for minimal system interference when your device is unresponsive or too slow or when you need all report sections. Does not take a screenshot or allow you to enter more details."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
       <item quantity="one">Taking screenshot for bug report in <xliff:g id="NUMBER_0">%d</xliff:g> second.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contents hidden"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Choose an action"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Choose an app for the USB device"</string>
     <string name="noApplications" msgid="2991814273936504689">"No apps can perform this action."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Unfortunately, <xliff:g id="APPLICATION">%1$s</xliff:g> has stopped."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Unfortunately, the process <xliff:g id="PROCESS">%1$s</xliff:g> has stopped."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silence crashes from <xliff:g id="PROCESS">%1$s</xliff:g> until reboot."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> has stopped"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> has stopped"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> keeps stopping"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> keeps stopping"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Restart app"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Reset and restart app"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Sending feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Close"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Mute"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Wait"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Close app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> isn\'t responding.\n\nDo you want to close it?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Activity <xliff:g id="ACTIVITY">%1$s</xliff:g> isn\'t responding.\n\nDo you want to close it?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> isn\'t responding. Do you want to close it?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Process <xliff:g id="PROCESS">%1$s</xliff:g> isn\'t responding.\n\nDo you want to close it?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> isn\'t responding"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> isn\'t responding"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> isn\'t responding"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Process <xliff:g id="PROCESS">%1$s</xliff:g> isn\'t responding"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Report"</string>
     <string name="wait" msgid="7147118217226317732">"Wait"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM card added"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Restart your device to access the mobile network."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Restart"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"To get your new SIM working properly, you\'ll need to install and open an app from your operator."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"GET THE APP"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NOT NOW"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"New SIM inserted"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Tap to set it up"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Set time"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Set"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"App is not resizeable, scroll it with two fingers."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"App is not resizeable, scroll it with two fingers."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App does not support split-screen."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installed by your administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Deleted by your administrator"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Miscellaneous"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"You set the importance of these notifications."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user, but is currently prohibited."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user, but the user limit has been reached."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user, but the account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" already exists on this device. Proceed anyway?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user for the account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Proceed?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> (a User with this account already exists) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Language preference"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region preference"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disabled"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Disabled by %1$s administrator. Contact them to find out more."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"You have new messages"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Some functions might not be available"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Touch to continue"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"User profile locked"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Connected to <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Tap to view files"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Pin"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
+    <string name="app_info" msgid="6856026610594615344">"App info"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index ee7dd71..a0a5493 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactive report"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Use this under most circumstances. It allows you to track progress of the report and enter more details about the problem. It might omit some less-used sections that take a long time to report."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Full report"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Use this option for minimal system interference when your device is unresponsive or too slow or when you need all report sections. Does not take a screenshot or allow you to enter more details."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
       <item quantity="one">Taking screenshot for bug report in <xliff:g id="NUMBER_0">%d</xliff:g> second.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contents hidden"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Choose an action"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Choose an app for the USB device"</string>
     <string name="noApplications" msgid="2991814273936504689">"No apps can perform this action."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Unfortunately, <xliff:g id="APPLICATION">%1$s</xliff:g> has stopped."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Unfortunately, the process <xliff:g id="PROCESS">%1$s</xliff:g> has stopped."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silence crashes from <xliff:g id="PROCESS">%1$s</xliff:g> until reboot."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> has stopped"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> has stopped"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> keeps stopping"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> keeps stopping"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Restart app"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Reset and restart app"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Sending feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Close"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Mute"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Wait"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Close app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> isn\'t responding.\n\nDo you want to close it?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Activity <xliff:g id="ACTIVITY">%1$s</xliff:g> isn\'t responding.\n\nDo you want to close it?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> isn\'t responding. Do you want to close it?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Process <xliff:g id="PROCESS">%1$s</xliff:g> isn\'t responding.\n\nDo you want to close it?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> isn\'t responding"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> isn\'t responding"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> isn\'t responding"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Process <xliff:g id="PROCESS">%1$s</xliff:g> isn\'t responding"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Report"</string>
     <string name="wait" msgid="7147118217226317732">"Wait"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM card added"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Restart your device to access the mobile network."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Restart"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"To get your new SIM working properly, you\'ll need to install and open an app from your operator."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"GET THE APP"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NOT NOW"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"New SIM inserted"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Tap to set it up"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Set time"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Set"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"App is not resizeable, scroll it with two fingers."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"App is not resizeable, scroll it with two fingers."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App does not support split-screen."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installed by your administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Deleted by your administrator"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Miscellaneous"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"You set the importance of these notifications."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user, but is currently prohibited."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user, but the user limit has been reached."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user, but the account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" already exists on this device. Proceed anyway?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user for the account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Proceed?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> (a User with this account already exists) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Language preference"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region preference"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disabled"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Disabled by %1$s administrator. Contact them to find out more."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"You have new messages"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Some functions might not be available"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Touch to continue"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"User profile locked"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Connected to <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Tap to view files"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Pin"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
+    <string name="app_info" msgid="6856026610594615344">"App info"</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index ee7dd71..a0a5493 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactive report"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Use this under most circumstances. It allows you to track progress of the report and enter more details about the problem. It might omit some less-used sections that take a long time to report."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Full report"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Use this option for minimal system interference when your device is unresponsive or too slow or when you need all report sections. Does not take a screenshot or allow you to enter more details."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
       <item quantity="one">Taking screenshot for bug report in <xliff:g id="NUMBER_0">%d</xliff:g> second.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contents hidden"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contents hidden by policy"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Choose an action"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Choose an app for the USB device"</string>
     <string name="noApplications" msgid="2991814273936504689">"No apps can perform this action."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Unfortunately, <xliff:g id="APPLICATION">%1$s</xliff:g> has stopped."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Unfortunately, the process <xliff:g id="PROCESS">%1$s</xliff:g> has stopped."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silence crashes from <xliff:g id="PROCESS">%1$s</xliff:g> until reboot."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> has stopped"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> has stopped"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> keeps stopping"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> keeps stopping"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Restart app"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Reset and restart app"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Sending feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Close"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Mute"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Wait"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Close app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> isn\'t responding.\n\nDo you want to close it?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Activity <xliff:g id="ACTIVITY">%1$s</xliff:g> isn\'t responding.\n\nDo you want to close it?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> isn\'t responding. Do you want to close it?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Process <xliff:g id="PROCESS">%1$s</xliff:g> isn\'t responding.\n\nDo you want to close it?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> isn\'t responding"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> isn\'t responding"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> isn\'t responding"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Process <xliff:g id="PROCESS">%1$s</xliff:g> isn\'t responding"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Report"</string>
     <string name="wait" msgid="7147118217226317732">"Wait"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM card added"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Restart your device to access the mobile network."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Restart"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"To get your new SIM working properly, you\'ll need to install and open an app from your operator."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"GET THE APP"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NOT NOW"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"New SIM inserted"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Tap to set it up"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Set time"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Set"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ask for PIN before unpinning"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ask for unlock pattern before unpinning"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"App is not resizeable, scroll it with two fingers."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"App is not resizeable, scroll it with two fingers."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App does not support split-screen."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installed by your administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Deleted by your administrator"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Miscellaneous"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"You set the importance of these notifications."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user, but is currently prohibited."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user, but the user limit has been reached."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user, but the account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" already exists on this device. Proceed anyway?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" is trying to add a new user for the account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Proceed?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Allow <xliff:g id="APP">%1$s</xliff:g> to create a new User with <xliff:g id="ACCOUNT">%2$s</xliff:g> (a User with this account already exists) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Language preference"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Region preference"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disabled"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Disabled by %1$s administrator. Contact them to find out more."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"You have new messages"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Some functions might not be available"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Touch to continue"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"User profile locked"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Connected to <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Tap to view files"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Pin"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
+    <string name="app_info" msgid="6856026610594615344">"App info"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 45a0e02..f07745b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactivo"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Usa esta opción en la mayoría de los casos. Te permite ingresar más detalles acerca del problema y realizar un seguimiento del progreso del informe. Es posible que se omitan secciones menos usadas cuyos informes demoran más en completarse."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Informe completo"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Usa esta opción para reducir al mínimo la interferencia cuando tu dispositivo no responde o funciona muy lento, o cuando necesitas todas las secciones. No permite tomar una captura de pantalla ni ingresar más detalles."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Se tomará una captura de pantalla para el informe de errores en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
       <item quantity="one">Se tomará una captura de pantalla para el informe de errores en <xliff:g id="NUMBER_0">%d</xliff:g> segundo.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenidos ocultos"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenido oculto debido a la política"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Seleccionar una acción"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Selecciona una aplicación para el dispositivo USB."</string>
     <string name="noApplications" msgid="2991814273936504689">"Ninguna aplicación puede realizar esta acción."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Lamentablemente, la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> se detuvo."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Lamentablemente, el proceso <xliff:g id="PROCESS">%1$s</xliff:g> se detuvo."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> produce fallos en la aplicación de silencio hasta que se reinicie."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> se detuvo"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> se detuvo"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> continúa fallando"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> continúa fallando"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Reiniciar app"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Restablecer y reiniciar la app"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Enviar comentarios"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Cerrar"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Silenciar"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Esperar"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Cerrar app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> no responde.\n\n¿Deseas cerrarla?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"La actividad <xliff:g id="ACTIVITY">%1$s</xliff:g> no responde.\n\n¿Deseas cerrarla?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> no responde. ¿Deseas cerrarla?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> no responde.\n\n¿Deseas cerrarlo?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> no responde"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no responde"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> no responde"</string>
+    <string name="anr_process" msgid="6156880875555921105">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> no responde"</string>
     <string name="force_close" msgid="8346072094521265605">"Aceptar"</string>
     <string name="report" msgid="4060218260984795706">"Notificar"</string>
     <string name="wait" msgid="7147118217226317732">"Esperar"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Tarjeta SIM agregada"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Reinicia el dispositivo para acceder a la red móvil."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Para que tu SIM nueva funcione correctamente, debes instalar y abrir la app de tu proveedor."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"OBTENER LA APP"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"AHORA NO"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Nueva SIM insertada"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Presiona para configurar"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Configurar hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Configurar fecha"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Establecer"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar PIN para quitar fijación"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar patrón de desbloqueo para quitar fijación"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para quitar fijación"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"No se puede modificar el tamaño de la app, desplázala con dos dedos."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"No se puede modificar el tamaño de la app. Desplázala con dos dedos."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"La app no es compatible con la función de pantalla dividida."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Lo instaló el administrador."</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por el administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Lo eliminó el administrador."</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Varios"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Estableciste la importancia de estas notificaciones."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Es importante debido a las personas involucradas."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está intentando agregar un usuario nuevo, pero esta app no está permitida."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está intentado agregar un usuario nuevo, pero ya se alcanzó el límite máximo de usuarios."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está intentado agregar un usuario nuevo, pero la cuenta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ya existe en este dispositivo. ¿Deseas continuar de todas formas?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está intentando agregar un usuario nuevo a la cuenta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". ¿Deseas continuar?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"¿Quieres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario nuevo con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"¿Quieres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario nuevo con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Ya existe un usuario con esta cuenta)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferencia de idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferencia de región"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Nombre del idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Todos los idiomas"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Búsqueda"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabajo DESACTIVADO"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Permite que se active el perfil de trabajo, incluidas las apps, la sincronización en segundo plano y las funciones relacionadas."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Se inhabilitó %1$s"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"El administrador de %1$s lo inhabilitó. Comunícate con él para obtener más información."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Tienes mensajes nuevos"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Abrir app de SMS para ver el mensaje"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Funciones no disponibles"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Tocar para continuar"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Perfil de usuario bloqueado"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Presiona para ver archivos"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fijar"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
+    <string name="app_info" msgid="6856026610594615344">"Información de la app"</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 2f1c4a8..518b157 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactivo"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Usa esta opción en la mayoría de los casos. Te permite realizar un seguimiento del progreso de la notificación e introducir más información sobre el problema. Es posible que se omitan algunas secciones menos utilizadas y que requieran más tiempo."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Informe completo"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Utiliza esta opción para que la interferencia del sistema sea mínima cuando el dispositivo no responda o funcione demasiado lento, o bien cuando necesites todas las secciones del informe. No realiza una captura de pantalla ni permite introducir más detalles."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">La captura de pantalla para el informe de errores se realizará en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
       <item quantity="one">La captura de pantalla para el informe de errores se realizará en <xliff:g id="NUMBER_0">%d</xliff:g> segundo.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt; 999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenidos ocultos"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenidos ocultos por política"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Selecciona una acción"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Elegir una aplicación para el dispositivo USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Ninguna aplicación puede realizar esta acción."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Se ha detenido la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g>."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Se ha detenido el proceso <xliff:g id="PROCESS">%1$s</xliff:g>."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Aplicación bloqueada desde el proceso <xliff:g id="PROCESS">%1$s</xliff:g> hasta que se reinicie."</string>
+    <string name="aerr_application" msgid="250320989337856518">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> ha dejado de funcionar"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha dejado de funcionar"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> sigue dejando de funcionar"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> sigue dejando de funcionar"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Reiniciar aplicación"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Restablecer y reiniciar aplicación"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Enviar sugerencias"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Cerrar"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Silenciar"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Esperar"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Cerrar aplicación"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"La aplicación <xliff:g id="APPLICATION">%2$s</xliff:g> no responde.\n\n¿Quieres cerrarla?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"La actividad <xliff:g id="ACTIVITY">%1$s</xliff:g> no responde.\n\n¿Quieres cerrarla?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> no responde. ¿Quieres cerrarla?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> no responde.\n\n¿Quieres cerrarlo?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> no responde"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no responde"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> no responde"</string>
+    <string name="anr_process" msgid="6156880875555921105">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> no responde"</string>
     <string name="force_close" msgid="8346072094521265605">"Aceptar"</string>
     <string name="report" msgid="4060218260984795706">"Informar"</string>
     <string name="wait" msgid="7147118217226317732">"Esperar"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Tarjeta SIM añadida"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Reinicia el dispositivo para acceder a la red móvil."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Para que tu nueva SIM funcione correctamente, debes instalar y abrir una aplicación de tu operador."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"DESCARGAR LA APLICACIÓN"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"AHORA NO"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Nueva SIM insertada"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Toca para configurar"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Establecer hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Establecer fecha"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Establecer"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar PIN para desactivar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar patrón de desbloqueo para desactivar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para desactivar"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"No se puede cambiar el tamaño de la aplicación: desplázala con dos dedos."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"No se puede cambiar el tamaño de la aplicación, desplázala con dos dedos."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"La aplicación no admite la pantalla dividida."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado por tu administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por tu administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado por tu administrador"</string>
@@ -1527,14 +1540,31 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Varios"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Tú determinas la importancia de estas notificaciones."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Esto es importante por los usuarios implicados."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" quiere añadir un usuario nuevo, pero no está permitido."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" quiere añadir un usuario nuevo, pero se ha alcanzado el límite de usuarios."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" quiere añadir un usuario nuevo, pero la cuenta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ya existe en este dispositivo. ¿Quieres continuar de todas formas?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" quiere añadir un usuario nuevo a la cuenta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". ¿Quieres continuar?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"¿Permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario con la cuenta <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"¿Permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario con la cuenta <xliff:g id="ACCOUNT">%2$s</xliff:g> (ya existe un usuario con esta cuenta)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferencia de idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferencia de región"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Nombre de idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Todos los idiomas"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Buscar"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabajo desactivado"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Permite que se utilice el perfil de trabajo, incluidas las aplicaciones, la sincronización en segundo plano y las funciones relacionadas."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for suspended_package_title (3408150347778524435) -->
+    <skip />
+    <!-- String.format failed for translation -->
+    <!-- no translation found for suspended_package_message (6341091587106868601) -->
+    <skip />
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Tienes mensajes nuevos"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Abre la aplicación de SMS para ver el mensaje"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Algunas funciones no disponibles"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Toca para continuar"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Perfil de usuario bloqueado"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Toca para ver archivos"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fijar"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
+    <string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string>
 </resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 3a4f2af..2348929 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interakt. aruanne"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Kasutage seda enamikul juhtudel. See võimaldab jälgida aruande edenemist ja sisestada probleemi kohta täpsemat teavet. Vahele võivad jääda mõned vähem kasutatud jaotised, millest teavitamine võtab rohkem aega."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Täielik aruanne"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Kasutage seda valikut süsteemihäirete minimeerimiseks, kui seade ei reageeri, on liiga aeglane või vajate aruande kõiki jaotisi. Ekraanipilti ei jäädvustata ega lubata sisestada lisateavet."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Veaaruande jaoks ekraanipildi jäädvustamine <xliff:g id="NUMBER_1">%d</xliff:g> sekundi pärast.</item>
       <item quantity="one">Veaaruande jaoks ekraanipildi jäädvustamine <xliff:g id="NUMBER_0">%d</xliff:g> sekundi pärast.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sisu on peidetud"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sisu on eeskirjadega peidetud"</string>
     <string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Isiklik"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Toimingu valimine"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB-seadme jaoks rakenduse valimine"</string>
     <string name="noApplications" msgid="2991814273936504689">"Ükski rakendus ei saa seda toimingut teostada."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Kahjuks on rakendus <xliff:g id="APPLICATION">%1$s</xliff:g> peatunud."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Kahjuks on protsess <xliff:g id="PROCESS">%1$s</xliff:g> peatunud."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Protsessi <xliff:g id="PROCESS">%1$s</xliff:g> krahhid vaigistatakse taaskäivitamiseni."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Rakendus <xliff:g id="APPLICATION">%1$s</xliff:g> on seiskunud"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Rakendus <xliff:g id="PROCESS">%1$s</xliff:g> on seiskunud"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"Rakendus <xliff:g id="APPLICATION">%1$s</xliff:g> lõpetab pidevalt töö"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Rakendus <xliff:g id="PROCESS">%1$s</xliff:g> lõpetab pidevalt töö"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Taaskäivita rakendus"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Lähtesta ja taaskäivita rakendus"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Saada tagasiside"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Sule"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Vaigista"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Oota"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Sule rakendus"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ei vasta.\n\nKas soovite selle sulgeda?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Tegevus <xliff:g id="ACTIVITY">%1$s</xliff:g> ei vasta.\n\nKas soovite selle sulgeda?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ei vasta. Kas soovite selle sulgeda?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Protsess <xliff:g id="PROCESS">%1$s</xliff:g> ei vasta.\n\nKas soovite selle sulgeda?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"Rakendus <xliff:g id="APPLICATION">%2$s</xliff:g> ei reageeri"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"Rakendus <xliff:g id="ACTIVITY">%1$s</xliff:g> ei reageeri"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"Rakendus <xliff:g id="APPLICATION">%1$s</xliff:g> ei reageeri"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Protsess <xliff:g id="PROCESS">%1$s</xliff:g> ei reageeri"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Teata"</string>
     <string name="wait" msgid="7147118217226317732">"Oodake"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-kaart lisatud"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Mobiilsidevõrku pääsemiseks taaskäivitage seade."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Taaskäivita"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Kellaaja määramine"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Kuupäeva määramine"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Määra"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Enne vabastamist küsi PIN-koodi"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Enne vabastamist küsi avamismustrit"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Enne vabastamist küsi parooli"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Rakenduse suurust ei saa muuta. Kerige kahe sõrmega."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Rakenduse suurust ei saa muuta. Kerige kahe sõrmega."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Rakendus ei toeta jagatud ekraani."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installis teie administraator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Värskendas administraator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Kustutas teie administraator"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Mitmesugust"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Teie määrasite nende märguannete tähtsuse."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"See on tähtis osalevate inimeste tõttu."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" üritab lisada uut kasutajat, kuid see on praegu keelatud."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" üritab lisada uut kasutajat, ent olete jõudnud kasutajate maksimumarvuni."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" üritab lisada uut kasutajat, ent konto "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" on juba seadmes olemas. Kas soovite siiski jätkata?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" üritab lisada uut kasutajat kontole "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Kas soovite jätkata?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Kas lubada rakendusel <xliff:g id="APP">%1$s</xliff:g> luua uus kasutaja kontoga <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Kas lubada rakendusel <xliff:g id="APP">%1$s</xliff:g> luua uus kasutaja kontoga <xliff:g id="ACCOUNT">%2$s</xliff:g> (selle kontoga kasutaja on juba olemas)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Keele-eelistus"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Piirkonnaeelistus"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Sisestage keele nimi"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Soovitatud"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Kõik keeled"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Otsing"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Töörežiim on VÄLJA LÜLITATUD"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Lubatakse tööprofiili toimingud, sh rakendused, taustal sünkroonimine ja seotud funktsioonid."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Lülita sisse"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Üksus %1$s on keelatud"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Keelas seadme %1$s administraator. Lisateabe saamiseks võtke temaga ühendust."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Teile on uusi sõnumeid"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Avage vaatamiseks SMS-rakendus"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Mõni funktsioon pole võib-olla saadaval"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Puudutage jätkamiseks"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Kasutajaprofiil on lukustatud"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Ühendatud seadmega <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Failide vaatamiseks puudutage"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Kinnita"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Vabasta"</string>
+    <string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string>
 </resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 35d67e9..a595603 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Txosten dinamikoa"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Aukera hau erabili beharko zenuke ia beti. Txostenaren jarraipena egin ahal izango duzu eta arazoari buruzko xehetasunak eman ahal izango dituzu. Baliteke gutxitan erabili behar izaten diren atalak ez agertzea, denbora aurrezteko."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Txosten osoa"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Erabili aukera hau sisteman ahalik eta traba gutxien eragiteko gailuak erantzuten ez duenean, mantsoegi dabilenean edo txosteneko atal guztiak behar dituzunean. Ez du ateratzen argazkirik eta ez du uzten beste xehetasunik ematen."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Akatsen txostenaren argazkia aterako da <xliff:g id="NUMBER_1">%d</xliff:g> segundo barru.</item>
       <item quantity="one">Akatsen txostenaren argazkia aterako da <xliff:g id="NUMBER_0">%d</xliff:g> segundo barru.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Edukiak ezkutatuta daude"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Gidalerro batzuk ezkutatu dira, gidalerroei jarraiki"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modu segurua"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistema"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pertsonalak"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Aukeratu ekintza bat"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Aukeratu USB gailurako aplikazioa"</string>
     <string name="noApplications" msgid="2991814273936504689">"Ez dago ekintza hori egin dezakeen aplikaziorik."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Zoritxarrez, <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioa gelditu egin da."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Zoritxarrez, <xliff:g id="PROCESS">%1$s</xliff:g> prozesua gelditu egin da."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Blokeatu egin da aplikazioa <xliff:g id="PROCESS">%1$s</xliff:g> prozesutik berrabiarazten den arte."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Gelditu egin da <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Gelditu egin da <xliff:g id="PROCESS">%1$s</xliff:g>"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"Behin eta berriz gelditzen ari da <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Behin eta berriz gelditzen ari da <xliff:g id="PROCESS">%1$s</xliff:g>"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Berrabiarazi aplikazioa"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Berrezarri eta berrabiarazi aplikazioa"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Bidali iritzia"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Itxi"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ezkutatu"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Itxaron"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Itxi aplikazioa"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> aplikazioak ez du erantzuten.\n\nItxi egin nahi duzu?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> jarduerak ez du erantzuten.\n\nItxi egin nahi duzu?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioak ez du erantzuten. Itxi egin nahi duzu?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> prozesuak ez du erantzuten.\n\nItxi egin nahi duzu?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> aplikazioak ez du erantzuten"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> aplikazioak ez du erantzuten"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioak ez du erantzuten"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> prozesuak ez du erantzuten"</string>
     <string name="force_close" msgid="8346072094521265605">"Ados"</string>
     <string name="report" msgid="4060218260984795706">"Salatu"</string>
     <string name="wait" msgid="7147118217226317732">"Itxaron"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM txartela gehitu da"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Sare mugikorra atzitzeko, berrabiarazi gailua."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Berrabiarazi"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"SIM berriak behar bezala funtziona dezan, operadorearen aplikazio bat instalatu eta ireki behar duzu."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ESKURATU APLIKAZIOA"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"ORAIN EZ"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"SIM berria sartu da"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Sakatu konfiguratzeko"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ezarri ordua"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ezarri data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ezarri"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Eskatu PIN kodea aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Eskatu desblokeatzeko eredua aingura kendu aurretik"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Eskatu pasahitza aingura kendu aurretik"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Ezin da aldatu aplikazioaren tamaina. Erabili bi hatz aplikazioan gora eta behera egiteko."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Ezin da aldatu aplikazioaren tamaina. Erabili bi hatz aplikazioan gora eta behera egiteko."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikazioak ez du onartzen pantaila banatua"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Administratzaileak instalatu du"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Administratzaileak eguneratu du"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratzaileak ezabatu du"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Askotarikoak"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Zuk ezarri zenuen jakinarazpen hauen garrantzia."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Garrantzitsua da eragiten dien pertsonengatik."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" beste erabiltzaile bat gehitzen saiatzen ari da, baina unean debekatuta dago."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" beste erabiltzaile bat gehitzen saiatzen ari da, baina erabiltzaileen mugara irisi da."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" beste erabiltzaile bat gehitzen saiatzen ari da, baina "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" badago gailuan. Jarraitu nahi duzu halere?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" beste erabiltzaile bat gehitzen saiatzen ari da "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" kontuan. Jarraitu nahi duzu?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzea baimendu nahi diozu?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzea baimendu nahi diozu? (Badago kontu hori duen erabiltzaile bat)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Hizkuntza-hobespena"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Lurralde-hobespena"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Adierazi hizkuntza"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Iradokitakoak"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Hizkuntza guztiak"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Bilaketa"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Desaktibatuta dago laneko modua"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Baimendu laneko profilak funtzionatzea, besteak beste, aplikazioak, atzeko planoko sinkronizazioa eta erlazionatutako eginbideak."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktibatu"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Desgaituta dago %1$s"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Desgaitu egin du %1$s gailuaren administratzaileak. Informazio gehiago lortu nahi baduzu, jarri harekin harremanetan."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Mezu berriak dituzu"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Mezuak ikusteko, ireki SMS mezuen aplikazioa"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Baliteke funtzio batzuk ez egotea"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Ukitu jarraitzeko"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Blokeatuta dago profila"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> zerbitzura konektatuta"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Sakatu fitxategiak ikusteko"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Ainguratu"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Kendu aingura"</string>
+    <string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index e1adfb9..14b87e8 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"گزارش تعاملی"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"در بیشتر شرایط از این گزینه استفاده کنید. به شما امکان ردیابی پیشرفت گزارش و وارد کردن جزئیات بیشتری درباره مشکل را می‌دهد. ممکن است برخی از بخش‌هایی را که کمتر استفاده شده و باعث افزایش طول زمان گزارش می‌شود حذف کند."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"گزارش کامل"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"از این گزینه برای به‌حداقل رساندن تداخل سیستم هنگام پاسخ‌گو نبودن یا کند بودن دستگاه یا هنگام نیازداشتن به همه بخش‌های گزارش استفاده کنید. عکس صفحه‌نمایش نمی‌گیرد یا امکان وارد کردن جزئیات بیشتری به شما نمی‌دهد."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">تا <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دیگر عکس صفحه‌نمایش برای گزارش اشکال گرفته می‌شود.</item>
       <item quantity="other">تا <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دیگر عکس صفحه‌نمایش برای گزارش اشکال گرفته می‌شود.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"بیشتر از 999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"محتواها پنهان هستند"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"محتوا بر اساس خط‌مشی پنهان شده است"</string>
     <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏سیستم Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"شخصی"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"انتخاب عملکرد"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"‏انتخاب برنامه برای دستگاه USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"‏هیچ برنامه‌ای نمی‌‎تواند این کار را انجام دهد."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"متأسفانه، <xliff:g id="APPLICATION">%1$s</xliff:g> متوقف شده است."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"متأسفانه، پردازش <xliff:g id="PROCESS">%1$s</xliff:g> متوقف شده است."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"تا را‌ه‌اندازی مجدد، خرابی‌ها از <xliff:g id="PROCESS">%1$s</xliff:g> نادیده گرفته شوند."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> متوقف شده است"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> متوقف شده است"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> مرتب متوقف می‌شود"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> مرتب متوقف می‌شود"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"راه‌اندازی مجدد برنامه"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"بازنشانی و راه‌اندازی مجدد برنامه"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"ارسال بازخورد"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"بستن"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"بی‌صدا کردن"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"انتظار"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"بستن برنامه"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"‏<xliff:g id="APPLICATION">%2$s</xliff:g> پاسخ نمی‌‎دهد.\n\nآیا می‎خواهید آنرا ببندید؟"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"‏فعالیت <xliff:g id="ACTIVITY">%1$s</xliff:g> پاسخ نمی‌‎دهد.\n\nآیا می‎خواهید آن را ببندید؟"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"‏<xliff:g id="APPLICATION">%1$s</xliff:g> پاسخ نمی‌‎دهد. آیا می‎خواهید آن را ببندید؟"</string>
-    <string name="anr_process" msgid="6513209874880517125">"‏روند <xliff:g id="PROCESS">%1$s</xliff:g> پاسخ نمی‌‎دهد. \n\nآیا می‎خواهید آن را ببندید؟"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> پاسخ نمی‌دهد"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> پاسخ نمی‌دهد"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> پاسخ نمی‌دهد"</string>
+    <string name="anr_process" msgid="6156880875555921105">"فرآیند <xliff:g id="PROCESS">%1$s</xliff:g> پاسخ نمی‌دهد"</string>
     <string name="force_close" msgid="8346072094521265605">"تأیید"</string>
     <string name="report" msgid="4060218260984795706">"گزارش"</string>
     <string name="wait" msgid="7147118217226317732">"منتظر بمانید"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"سیم کارت اضافه شد"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"برای دسترسی به شبکه تلفن همراه، دستگاهتان را مجدداً راه‌اندازی کنید."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"راه‌اندازی مجدد"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"برای اینکه سیم‌کارت جدیدتان عملکرد درستی داشته باشد باید برنامه‌ای را از شرکت مخابراتی‌تان نصب و باز کنید."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"دریافت برنامه"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"اکنون نه"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"سیم‌کارت جدید جاگذاری شد"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"برای تنظیم آن ضربه بزنید"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"تنظیم زمان"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تاریخ تنظیم"</string>
     <string name="date_time_set" msgid="5777075614321087758">"تنظیم"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"درخواست کد پین قبل از برداشتن پین"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"درخواست الگوی باز کردن قفل قبل از برداشتن پین"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"درخواست گذرواژه قبل از برداشتن پین"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"اندازه برنامه قابل تغییر نیست، با دو انگشت آن را پیمایش کنید."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"اندازه برنامه قابل تغییر نیست، با دو انگشت آن را پیمایش کنید."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"برنامه از تقسیم صفحه پشتیبانی نمی‌کند."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"توسط سرپرستتان نصب شد"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"توسط سرپرست شما به‌روزرسانی شد"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"توسط سرپرستتان حذف شد"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"متفرقه"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"شما اهمیت این اعلان‌ها را تنظیم می‌کنید."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"به دلیل افراد درگیر مهم است."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" در تلاش است کاربر جدیدی اضافه کند، اما در حال حاضر این اقدام ممنوع است."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" در تلاش است کاربر جدیدی اضافه کند، اما تعداد کاربران به حداکثر مجاز رسیده است."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" در تلاش است کاربر جدیدی اضافه کند، اما حساب "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" از قبل در این دستگاه وجود دارد. در هر صورت ادامه داده شود؟"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" در تلاش است کاربر جدیدی برای حساب "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" اضافه کند. ادامه می‌دهید؟"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"به <xliff:g id="APP">%1$s</xliff:g> امکان داده شود کاربر جدیدی با <xliff:g id="ACCOUNT">%2$s</xliff:g> اضافه کند؟"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"به <xliff:g id="APP">%1$s</xliff:g> امکان داده شود کاربر جدیدی با <xliff:g id="ACCOUNT">%2$s</xliff:g> ایجاد کند (کاربری با این حساب از قبل وجود دارد)؟"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"اولویت‌های زبان"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"اولویت‌های منطقه"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"نام زبان را تایپ کنید"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"پیشنهادشده"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"همه زبان‌ها"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"جستجو"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"حالت کاری خاموش است"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"به نمایه کاری اجازه فعالیت ( شامل استفاده از برنامه‌ها، همگام‌سازی در پس‌زمینه و قابلیت‌های مرتبط) داده شود."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"روشن کردن"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"‏%1$s غیرفعال است"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"‏سرپرست %1$s آن را غیرفعال کرده است. برای اطلاعات بیشتر با او تماس بگیرید."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"پیام‌های جدیدی دارید"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"برای مشاهده، برنامه پیامک را باز کنید"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"شاید برخی عملکردها دردسترس نباشند"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"برای ادامه لمس کنید"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"نمایه کاربر قفل است"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"به <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> متصل شد"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"برای دیدن فایل‌ها، ضربه بزنید"</string>
+    <string name="pin_target" msgid="3052256031352291362">"پین کردن"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"برداشتن پین"</string>
+    <string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 9274b87..ff78c91 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiivinen"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Valitse tämä vaihtoehto useimmissa tapauksissa. Voit seurata raportin etenemistä ja antaa lisätietoja ongelmasta. Tämä vaihtoehto saattaa ohittaa joitakin harvoin käytettyjä osioita, joiden käsittely raportissa kestää kauan."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Koko raportti"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Valitse tämä, jos laitteesi ei ota komentoja vastaan tai toimii hitaasti, tai tarvitset kaikkia raportin osioita. Raporttiin ei tallenneta kuvakaappausta, etkä voi kirjoittaa siihen lisätietoja."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Virheraporttiin otetaan kuvakaappaus <xliff:g id="NUMBER_1">%d</xliff:g> sekunnin kuluttua.</item>
       <item quantity="one">Virheraporttiin otetaan kuvakaappaus <xliff:g id="NUMBER_0">%d</xliff:g> sekunnin kuluttua.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sisältö piilotettu"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sisältö on piilotettu käytännön perusteella."</string>
     <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Henkilökoht."</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Valitse toiminto"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Valitse USB-laitetta käyttävä sovellus"</string>
     <string name="noApplications" msgid="2991814273936504689">"Yksikään sovellus ei voi suorittaa tätä toimintoa."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"<xliff:g id="APPLICATION">%1$s</xliff:g> on pysähtynyt."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Prosessi <xliff:g id="PROCESS">%1$s</xliff:g> on pysähtynyt."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silencen kaatumiset prosessista <xliff:g id="PROCESS">%1$s</xliff:g> uudelleenkäynnistykseen asti."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> pysähtyi."</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> pysähtyi."</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> pysähtyy toistuvasti."</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> pysähtyy toistuvasti."</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Käynnistä sovellus uudelleen"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Nollaa sovellus ja käynnistä uudelleen"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Lähetä palautetta"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Sulje"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ohita"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Odota"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Sulje sovellus"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ei vastaa.\n\nHaluatko sulkea sen?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Toiminto <xliff:g id="ACTIVITY">%1$s</xliff:g> ei vastaa.\n\nHaluatko sulkea sen?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ei vastaa. Haluatko sulkea sen?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Prosessi <xliff:g id="PROCESS">%1$s</xliff:g> ei vastaa.\n\nHaluatko sulkea sen?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ei vastaa."</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ei vastaa."</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ei vastaa."</string>
+    <string name="anr_process" msgid="6156880875555921105">"Prosessi <xliff:g id="PROCESS">%1$s</xliff:g> ei vastaa."</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Ilmoita"</string>
     <string name="wait" msgid="7147118217226317732">"Odota"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-kortti lisätty"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Käynnistä laite uudelleen, niin pääset käyttämään matkapuhelinverkkoa."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Käynnistä uudelleen"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Aseta aika"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Aseta päivämäärä"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Aseta"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pyydä PIN ennen irrotusta"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pyydä lukituksenpoistokuvio ennen irrotusta"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pyydä salasana ennen irrotusta"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Sovelluksen koko ei muutu. Vieritä näkymää kahdella sormella."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Sovelluksen kokoa ei voi muuttaa. Vieritä näkymää kahdella sormella."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Sovellus ei tue jaetun näytön tilaa."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Järjestelmänvalvoja on asentanut paketin."</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Järjestelmänvalvojasi on päivittänyt paketin."</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Järjestelmänvalvoja on poistanut paketin."</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Muut"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Voit valita näiden ilmoitusten tärkeyden."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Tämä on tärkeää siihen liittyvien ihmisten perusteella."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" yrittää lisätä uutta käyttäjää, mutta se on tällä hetkellä estetty."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" yrittää lisätä uutta käyttäjää, mutta käyttäjiä on jo enimmäismäärä."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" yrittää lisätä uutta käyttäjää, mutta tili "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" on jo tässä laitteessa. Jatketaanko silti?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" yrittää lisätä uutta käyttäjää tilille "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Jatketaanko?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Myönnetäänkö sovellukselle <xliff:g id="APP">%1$s</xliff:g> oikeus luoda käyttäjä tilille <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Myönnetäänkö sovellukselle <xliff:g id="APP">%1$s</xliff:g> oikeus luoda käyttäjä tilille <xliff:g id="ACCOUNT">%2$s</xliff:g> (tilillä on jo käyttäjä)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Kieliasetus"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Alueasetus"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Anna kielen nimi"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Ehdotukset"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Kaikki kielet"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Haku"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Työtila on pois käytöstä"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Sallii työprofiiliin toiminnan, esimerkiksi sovellukset ja taustasynkronoinnin."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Ota käyttöön"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s poisti tämän käytöstä"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Organisaation %1$s järjestelmänvalvojan käytöstä poistama. Kysy häneltä lisätietoja."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Sinulle on uusia viestejä"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Katso avaamalla tekstiviestisovellus."</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Osaa toiminnoista ei ehkä voi käyttää"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Jatka koskettamalla."</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Käyttäjäprofiili on lukittu."</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> yhdistetty"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Näytä tiedostot koskettamalla"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Kiinnitä"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Irrota"</string>
+    <string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 965a83c..1cef50a 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -212,10 +212,9 @@
     <string name="bugreport_title" msgid="2667494803742548533">"Créer un rapport de bogue"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Cela permet de recueillir des informations concernant l\'état actuel de votre appareil. Ces informations sont ensuite envoyées sous forme de courriel. Merci de patienter pendant la préparation du rapport de bogue. Cette opération peut prendre quelques instants."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Rapport interactif"</string>
-    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Utilisez cette option dans la plupart des circonstances. Elle vous permet de suivre la progression du rapport et d\'entrer plus de données sur le problème. Certaines sections moins utilisées et dont le remplissage demande beaucoup de temps peuvent être omises."</string>
+    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Utilisez cette option dans la plupart des circonstances. Elle vous permet de suivre la progression du rapport et d\'entrer plus de données sur le problème. Certaines sections moins utilisées, et dont le remplissage demande beaucoup de temps, peuvent être omises."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Rapport complet"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Utilisez cette option pour un minimum d\'interférences système lorsque votre appareil ne répond pas ou est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport. Aucune saisie d\'écran ne sera prise, et vous ne pourrez pas entrer d\'autres données."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Saisie d\'écran pour le rapport de bogue dans <xliff:g id="NUMBER_1">%d</xliff:g> seconde.</item>
       <item quantity="other">Saisie d\'écran pour le rapport de bogue dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenus masqués"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenu masqué conformément aux politiques"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personnel"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Sélectionnez une action"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Sélectionnez une application pour le périphérique de stockage USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Aucune application ne peut effectuer cette action."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"L\'application \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" s\'est arrêtée."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> s\'est interrompu."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Plantage de Silence lors du processus « <xliff:g id="PROCESS">%1$s</xliff:g> » avant le redémarrage"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> a cessé de fonctionner"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> a cessé de fonctionner"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> plante continuellement"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> plante continuellement"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Redémarrer l\'application"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Réinitialiser et redémarrer l\'application"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Envoyer des commentaires"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Fermer"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Désactiver les notifications"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Attendre"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Fermer l\'application"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"L\'application <xliff:g id="APPLICATION">%2$s</xliff:g> ne répond pas.\n\nVoulez-vous quitter?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"L\'activité <xliff:g id="ACTIVITY">%1$s</xliff:g> ne répond pas.\n\nVoulez-vous quitter?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"L\'application <xliff:g id="APPLICATION">%1$s</xliff:g> ne répond pas. Voulez-vous quitter?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> ne répond pas.\n\nVoulez-vous quitter?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ne répond pas"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ne répond pas"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ne répond pas"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> ne répond pas"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Signaler"</string>
     <string name="wait" msgid="7147118217226317732">"Attendre"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Carte SIM ajoutée."</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Redémarrez votre appareil pour accéder au réseau cellulaire."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Recommencer"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Définir l\'heure"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Définir la date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Paramètres"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Demander le NIP avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'application n\'est pas compatible avec l\'écran partagé."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installé par votre administrateur"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Supprimé par votre administrateur"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Divers"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Vous définissez l\'importance de ces notifications."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Ces notifications sont importantes en raison des participants."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" essaie d\'ajouter un utilisateur, mais n\'y est pas autorisé."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" essaie d\'ajouter un utilisateur, mais le nombre maximal d\'utilisateurs a été atteint."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" essaie d\'ajouter un utilisateur, mais le compte "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" existe déjà sur cet appareil. Continuer?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" essaie d\'ajouter un utilisateur, mais le compte "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Continuer?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil d\'utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil d\'utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Un utilisateur associé à ce compte existe déjà.)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Préférences linguistiques"</string>
-    <string name="country_selection_title" msgid="2954859441620215513">"Préférence régionales"</string>
+    <string name="country_selection_title" msgid="2954859441620215513">"Préférences régionales"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Entrez la langue"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggestions"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Toutes les langues"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Rechercher"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Le mode Travail est désactivé"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Autoriser le fonctionnement du profil professionnel, y compris les applications, la synchronisation en arrière-plan et les fonctionnalités associées."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Activer"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s est désactivé"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Cette option a été désactivée par l\'administrateur de %1$s. Communiquez avec lui pour en savoir plus."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Vous avez de nouveaux messages"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Ouvrez l\'application de messagerie texte pour l\'afficher"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Certaines fonct. p-ê non dispo."</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Touchez pour continuer"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil d\'utilisateur verrouillé"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Connecté à <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Touchez ici pour afficher les fichiers"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Épingler"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Annuler l\'épinglage"</string>
+    <string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index b0260ef..662076d 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Rapport interactif"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Utilisez cette option dans la plupart des circonstances. Elle vous permet de suivre la progression du rapport et de saisir plus d\'informations sur le problème. Certaines sections moins utilisées et dont le remplissage demande beaucoup de temps peuvent être omises."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Rapport complet"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Utilisez cette option pour qu\'il y ait le moins d\'interférences système possible lorsque votre appareil ne répond pas ou qu\'il est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport de bug. Aucune capture d\'écran ne sera prise, et vous ne pourrez saisir aucune autre information."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Capture d\'écran pour le rapport de bug dans <xliff:g id="NUMBER_1">%d</xliff:g> seconde</item>
       <item quantity="other">Capture d\'écran pour le rapport de bug dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenus masqués"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenu masqué conformément aux règles"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personnel"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Sélectionnez une action"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Sélectionnez une application pour le périphérique de stockage USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Aucune application ne peut effectuer cette action."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"\"<xliff:g id="APPLICATION">%1$s</xliff:g>\" s\'est arrêté."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> s\'est interrompu."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Suspendre l\'affichage des informations de plantage de <xliff:g id="PROCESS">%1$s</xliff:g> jusqu\'au redémarrage"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> a cessé de fonctionner."</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> a cessé de fonctionner."</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ne cesse de s\'arrêter."</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Le processus \"<xliff:g id="PROCESS">%1$s</xliff:g>\" ne cesse de s\'arrêter."</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Redémarrer l\'application"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Réinitialiser et redémarrer l\'application"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Envoyer des commentaires"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Fermer"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorer"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Attendre"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Fermer l\'application"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"L\'application <xliff:g id="APPLICATION">%2$s</xliff:g> ne répond pas.\n\nVoulez-vous quitter ?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"L\'activité <xliff:g id="ACTIVITY">%1$s</xliff:g> ne répond pas.\n\nVoulez-vous quitter ?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"L\'application <xliff:g id="APPLICATION">%1$s</xliff:g> ne répond pas. Voulez-vous quitter ?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> ne répond pas.\n\nVoulez-vous quitter ?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ne répond pas."</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"L\'activité \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\" ne répond pas."</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ne répond pas."</string>
+    <string name="anr_process" msgid="6156880875555921105">"Le processus \"<xliff:g id="PROCESS">%1$s</xliff:g>\" ne répond pas."</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Rapport"</string>
     <string name="wait" msgid="7147118217226317732">"Attendre"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Carte SIM ajoutée."</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Redémarrez votre appareil pour accéder au réseau mobile."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Redémarrer"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Pour que la nouvelle carte SIM fonctionne correctement, vous devez installer et ouvrir une application fournie par votre opérateur."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"TÉLÉCHARGER L\'APPLICATION"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"PLUS TARD"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Nouvelle carte SIM insérée"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Appuyez ici pour effectuer la configuration."</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Définir l\'heure"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Définir la date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Définir"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Demander le code PIN avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Demander le schéma de déverrouillage avant d\'annuler l\'épinglage"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Il est impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Il est impossible de redimensionner l\'application. Faites-la défiler avec deux doigts."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Application incompatible avec l\'écran partagé."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installé par votre administrateur"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Supprimé par votre administrateur"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Divers"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Vous définissez l\'importance de ces notifications."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Ces notifications sont importantes en raison des participants."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" essaie d\'ajouter un utilisateur, mais n\'y est pas autorisé."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" essaie d\'ajouter un utilisateur, mais le nombre maximal d\'utilisateurs a été atteint."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" essaie d\'ajouter un utilisateur, mais le compte "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" existe déjà sur cet appareil. Continuer ?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" essaie d\'ajouter un utilisateur au compte "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Continuer ?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Autoriser <xliff:g id="APP">%1$s</xliff:g> à créer un profil utilisateur avec le compte <xliff:g id="ACCOUNT">%2$s</xliff:g> (un utilisateur associé à ce compte existe déjà) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Préférences linguistiques"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Préférences régionales"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Saisissez la langue"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Recommandations"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Toutes les langues"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Rechercher"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Mode professionnel DÉSACTIVÉ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Autoriser le fonctionnement du profil professionnel, y compris les applications, la synchronisation en arrière-plan et les fonctionnalités associées."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Activer"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s désactivé"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Désactivé par l\'administrateur %1$s. Contactez-le pour en savoir plus."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Vous avez de nouveaux messages"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Ouvrir l\'application de SMS pour afficher le message"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Certaines fonctions potentiellement non dispos"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Appuyer pour continuer"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil utilisateur verrouillé"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Connecté à <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Appuyez ici pour voir les fichiers."</string>
+    <string name="pin_target" msgid="3052256031352291362">"Épingler"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Retirer"</string>
+    <string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string>
 </resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index b2a69fc..f2e1850 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -214,11 +214,10 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactivo"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Usa esta opción na maioría das circunstancias. Permíteche realizar un seguimento do progreso do informe e introducir máis detalles sobre o problema. Pode que omita algunhas seccións menos usadas para as que se tarda máis en facer o informe."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Informe completo"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Usa esta opción para que a interferencia sexa mínima cando o teu dispositivo non responda ou funcione demasiado lento, ou ben cando precises todas as seccións do informe. Non se fará ningunha captura de pantalla e non poderás introducir máis detalles."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
-      <item quantity="other">Facendo captura de pantalla para informe de erros en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
-      <item quantity="one">Facendo captura de pantalla para informe de erros en <xliff:g id="NUMBER_0">%d</xliff:g> segundo.</item>
+      <item quantity="other">Vaise facer unha captura de pantalla para o informe de erros en <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
+      <item quantity="one">Vaise facer unha captura de pantalla para o informe de erros en <xliff:g id="NUMBER_0">%d</xliff:g> segundo.</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo de silencio"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"O son está desactivado"</string>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contido oculto"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Ocultouse contido por causa da política"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Persoal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Escoller unha acción"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Selecciona unha aplicación para o dispositivo USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Ningunha aplicación pode realizar esta acción."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Detívose a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g>."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Detívose o proceso <xliff:g id="PROCESS">%1$s</xliff:g>."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"O proceso <xliff:g id="PROCESS">%1$s</xliff:g> producirá fallos na aplicación Silence ata que se reinicie."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Detívose <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Detívose <xliff:g id="PROCESS">%1$s</xliff:g>"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> segue deténdose"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> segue deténdose"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Reiniciar aplicación"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Restablecer e reiniciar aplicación"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Dános a túa opinión"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Pechar"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorar"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Esperar"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Pechar aplicación"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> non responde.\n\nQueres pechala?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"A actividade <xliff:g id="ACTIVITY">%1$s</xliff:g> non responde.\n\nQueres pechala?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> non responde. Queres pechala?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"O proceso <xliff:g id="PROCESS">%1$s</xliff:g> non responde.\n\nQueres pechalo?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> non responde"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non responde"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> non responde"</string>
+    <string name="anr_process" msgid="6156880875555921105">"O proceso <xliff:g id="PROCESS">%1$s</xliff:g> non responde"</string>
     <string name="force_close" msgid="8346072094521265605">"Aceptar"</string>
     <string name="report" msgid="4060218260984795706">"Enviar informe"</string>
     <string name="wait" msgid="7147118217226317732">"Esperar"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Engadiuse unha tarxeta SIM"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Reinicia o teu dispositivo para acceder á rede móbil."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Para conseguir que a túa SIM nova funcione correctamente, deberás instalar e abrir unha aplicación do teu operador."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"DESCARGAR A APLICACIÓN"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"AGORA NON"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Introduciuse unha nova SIM"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Tocar para configurar"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Configurar hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Establecer data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Configurar"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicitar un PIN antes de soltar a pantalla"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicitar un padrón de desbloqueo antes de soltar a pantalla"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar un contrasinal antes de soltar a pantalla"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Non se pode cambiar o tamaño da aplicación. Desprázate por ela con dous dedos."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Non se pode cambiar o tamaño da aplicación. Desprázate por ela con dous dedos."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"A aplicación non é compatible coa función de pantalla dividida."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado polo administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado polo administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado polo administrador"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Varios"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Ti defines a importancia destas notificacións."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"É importante polas persoas involucradas."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando engadir un usuario novo, pero está prohibido."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando engadir un usuario novo, pero alcanzouse o límite de usuarios."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando engadir un usuario novo, pero a conta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" xa existe neste dispositivo. Queres continuar igualmente?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando engadir un usuario novo á conta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Queres continuar?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Queres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario novo con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Queres permitir que <xliff:g id="APP">%1$s</xliff:g> cree un usuario novo con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Xa existe un usuario con esta conta)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferencia de idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferencia de rexión"</string>
-    <string name="search_language_hint" msgid="7042102592055108574">"Escribe o nome"</string>
+    <string name="search_language_hint" msgid="7042102592055108574">"Nome do idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suxeridos"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Buscar"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de traballo DESACTIVADO"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Permite que funcione o perfil de traballo, incluídas as aplicacións, a sincronización en segundo plano e as funcións relacionadas."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Desactivouse %1$s"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"O administrador de %1$s desactivou este paquete. Contacta con el para obter máis información."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Tes mensaxes novas"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Abre a aplicación de SMS para ver as mensaxes"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Quizais haxa funcións non dispoñibles"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Toca para continuar"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Bloqueouse o perfil do usuario"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Toca para ver os ficheiros"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fixar"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
+    <string name="app_info" msgid="6856026610594615344">"Información da aplicación"</string>
 </resources>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 9848cfb..ec613b0 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ક્રિયાપ્રતિક્રિયાત્મક રિપોર્ટ"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"મોટાભાગના સંજોગોમાં આનો ઉપયોગ કરો. તે રિપોર્ટની પ્રગતિને ટ્રૅક કરવા અમે સમસ્યા વિશે વધુ વિગતો દાખલ કરવાની મંજૂરી આપે છે. તે કેટલાંક ઓછા ઉપયોગમાં આવતા વિભાગો કે જે જાણ કરવામાં વધુ સમય લેતા હોય તેને છોડી દઈ શકે છે."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"પૂર્ણ રિપોર્ટ"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"જ્યારે તમારું ઉપકરણ પ્રતિભાવવિહીન અથવા ખૂબ ધીમું હોય અથવા જ્યારે તમને બધા રિપોર્ટ વિભાગોની જરૂર પડે ત્યારે ન્યૂનતમ સિસ્ટમ હસ્તક્ષેપ માટે આ વિકલ્પનો ઉપયોગ કરો. સ્ક્રીનશોટ લેવાની અથવા વધુ વિગતો દાખલ કરવાની તમને મંજૂરી આપતું નથી."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">બગ રિપોર્ટ માટે <xliff:g id="NUMBER_1">%d</xliff:g> સેકન્ડમાં સ્ક્રીનશોટ લઈ રહ્યાં છે.</item>
       <item quantity="other">બગ રિપોર્ટ માટે <xliff:g id="NUMBER_1">%d</xliff:g> સેકન્ડમાં સ્ક્રીનશોટ લઈ રહ્યાં છે.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"સામગ્રીઓ છુપાવેલ છે"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"નીતિ દ્વારા સામગ્રી છુપાવાઈ"</string>
     <string name="safeMode" msgid="2788228061547930246">"સુરક્ષિત મોડ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android સિસ્ટમ"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"વ્યક્તિગત"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"એક ક્રિયા પસંદ કરો"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ઉપકરણ માટે એપ્લિકેશન પસંદ કરો"</string>
     <string name="noApplications" msgid="2991814273936504689">"કોઈ એપ્લિકેશન આ ક્રિયા કરી શકતી નથી."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"કમનસીબે, <xliff:g id="APPLICATION">%1$s</xliff:g> બંધ થઈ ગયું છે."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"કમનસીબે, <xliff:g id="PROCESS">%1$s</xliff:g> પ્રક્રિયા રોકાઈ ગઈ છે."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"રીબૂટ ન કરવામાં આવે ત્યાં સુધી <xliff:g id="PROCESS">%1$s</xliff:g> માંથી મૌન ક્રેશ થાય છે."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> બંધ થઈ ગઈ છે"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> બંધ થઈ ગઈ છે"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> રોકાઈ રહી છે"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> રોકાઈ રહી છે"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"ઍપ્લિકેશનને ફરીથી પ્રારંભ કરો"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"ફરીથી સેટ કરો અને ઍપ્લિકેશનને ફરીથી પ્રારંભ કરો"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"પ્રતિસાદ મોકલો"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"બંધ કરો"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"મ્યૂટ કરો"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"રાહ જુઓ"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"ઍપ્લિકેશન બંધ કરો"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> જવાબ આપતી નથી.\n\nશું તમે તેને બંધ કરવા માંગો છો?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> પ્રવૃત્તિ પ્રતિસાદ આપતી નથી.\n\nશું તમે તેને બંધ કરવા માંગો છો?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> પ્રતિસાદ આપતું નથી. શું તમે તેને બંધ કરવા માંગો છો?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> પ્રક્રિયા જવાબ આપતી નથી.\n\nશું તમે તેને બંધ કરવા માગો છો?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> પ્રતિસાદ આપી રહી નથી"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> પ્રતિસાદ આપી રહી નથી"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> પ્રતિસાદ આપી રહી નથી"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> પ્રક્રિયા પ્રતિસાદ આપી રહી નથી"</string>
     <string name="force_close" msgid="8346072094521265605">"ઑકે"</string>
     <string name="report" msgid="4060218260984795706">"જાણ કરો"</string>
     <string name="wait" msgid="7147118217226317732">"રાહ જુઓ"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM કાર્ડ ઉમેર્યું"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"સેલ્યુલર નેટવર્કને ઍક્સેસ કરવામાં તમારા ઉપકરણને પુનઃપ્રારંભ કરો."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"પુનઃપ્રારંભ કરો"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"તમારું નવું SIM ઠીકથી કામ કરે તે માટે, તમને તમારા કેરીઅર પરથી ઍપ્લિકેશન ઇન્સ્ટૉલ કરીને ખોલવી પડશે."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ઍપ્લિકેશન મેળવો"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"હમણાં નહીં"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"નવું SIM દાખલ કર્યું"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"તેને સેટ કરવા માટે ટૅપ કરો"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"સમય સેટ કરો"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"તારીખ સેટ કરો"</string>
     <string name="date_time_set" msgid="5777075614321087758">"સેટ કરો"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"અનપિન કરતાં પહેલાં PIN માટે પૂછો"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"અનપિન કરતા પહેલાં અનલૉક પેટર્ન માટે પૂછો"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"અનપિન કરતાં પહેલાં પાસવર્ડ માટે પૂછો"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ઍપ્લિકેશનનું કદ બદલવા યોગ્ય નથી, બે આંગળીઓ વડે તેને સ્ક્રોલ કરો."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ઍપ્લિકેશનનું કદ બદલવા યોગ્ય નથી, બે આંગળીઓ વડે તેને સ્ક્રોલ કરો."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ઍપ્લિકેશન સ્ક્રીન-વિભાજનનું સમર્થન કરતી નથી."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"તમારા વ્યવસ્થાપક દ્વારા ઇન્સ્ટોલ કરેલ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"તમારા વ્યવસ્થાપક દ્વારા અપડેટ થયેલ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"તમારા વ્યવસ્થાપક દ્વારા કાઢી નાખેલ"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"વિવિધ"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"તમે આ સૂચનાઓનું મહત્વ સેટ કર્યું છે."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"શામેલ થયેલ લોકોને કારણે આ મહત્વપૂર્ણ છે."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>", નવા વપરાશકર્તાને ઉમેરવાનો પ્રયાસ કરી રહી છે, પરંતુ હાલમાં પ્રતિબંધિત છે."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>", નવા વપરાશકર્તાને ઉમેરવાનો પ્રયાસ કરી રહી છે, પરંતુ વપરાશકર્તા મર્યાદા સુધી પહોંચી ગયા છો."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>", નવા વપરાશકર્તાને ઉમેરવાનો પ્રયાસ કરી રહી છે, પરંતુ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" એકાઉન્ટ પહેલાંથી જ આ ઉપકરણ પર અસ્તિત્વમાં છે. કોઇપણ રીતે આગળ વધીએ?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>", "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" એકાઉન્ટ માટે એક નવા વપરાશકર્તાને ઉમેરવાનો પ્રયાસ કરી રહી છે. આગળ વધીએ?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ને <xliff:g id="ACCOUNT">%2$s</xliff:g> સાથે એક નવા વપરાશકર્તાને બનાવવાની મંજૂરી આપીએ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> સાથે <xliff:g id="APP">%1$s</xliff:g> ને એક નવા વપરાશકર્તાને બનાવવાની મંજૂરી આપીએ (આ એકાઉન્ટ સાથેના એક વપરાશકર્તા પહેલાંથી અસ્તિત્વમાં છે)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"ભાષા પસંદગી"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"પ્રદેશ પસંદગી"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ભાષાનું નામ ટાઇપ કરો"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"સૂચવેલા"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"બધી ભાષાઓ"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"શોધ"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"કાર્ય મોડ બંધ છે"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"કાર્ય પ્રોફાઇલને ઍપ્લિકેશનો, પૃષ્ઠભૂમિ સમન્વયન અને સંબંધિત સુવિધાઓ સહિતનું કાર્ય કરવાની મંજૂરી આપો."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ચાલુ કરો"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s અક્ષમ કરેલ"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ. વધુ જાણવા માટે તેમનો સંપર્ક કરો."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"તમારી પાસે નવા સંદેશા છે"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"જોવા માટે SMS ઍપ્લિકેશન ખોલો"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"કેટલાક કાર્યો કદાચ ઉપલબ્ધ ન હોય"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"ચાલુ રાખવા માટે ટચ કરો"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"વપરાશકર્તા પ્રોફાઇલ લૉક કરી"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> થી કનેક્ટ કરેલું છે"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ફાઇલો જોવા માટે ટૅપ કરો"</string>
+    <string name="pin_target" msgid="3052256031352291362">"પિન કરો"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"અનપિન કરો"</string>
+    <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 39608cb..4c944c30 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"सहभागी रिपोर्ट"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"अधिकांश परिस्‍थितियों में इसका उपयोग करें. यह आपको रिपोर्ट की प्रगति ट्रैक करने देता है और समस्‍या के बारे में अधिक विवरण डालने देता है. यह आपको ऐसे कम उपयोग किए गए अनुभाग मिटाने दे सकता है जिनकी रिपोर्ट करने में अधिक समय लगता है."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"पूर्ण रिपोर्ट"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"जब आपका डिवाइस प्रतिसाद नहीं दे रहा हो या बहुत ही धीमा हो, या जब आपको सभी रिपोर्ट अनुभागों की आवश्‍यकता हो, तो न्‍यूनतम सिस्‍टम हस्‍तक्षेप के लिए इस विकल्‍प का उपयोग करें. यह स्‍क्रीनशॉट नहीं लेता या आपको अधिक विवरण नहीं डालने देता."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">बग रिपोर्ट के लिए <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में स्‍क्रीनशॉट लिया जा रहा है.</item>
       <item quantity="other">बग रिपोर्ट के लिए <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में स्‍क्रीनशॉट लिया जा रहा है.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"छिपी हुई सामग्री"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"सामग्री पॉलिसी के द्वारा छिपी हुई है"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"व्यक्तिगत"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"कोई क्रिया चुनें"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB डिवाइस के लिए कोई ऐप्स  चुनें"</string>
     <string name="noApplications" msgid="2991814273936504689">"कोई भी ऐप्स यह कार्यवाही नहीं कर सकता."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"दुर्भाग्‍यवश, <xliff:g id="APPLICATION">%1$s</xliff:g> रुक गया है."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"दुर्भाग्‍यवश, <xliff:g id="PROCESS">%1$s</xliff:g> प्रक्रिया रुक गई है."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"रीबूट होने तक <xliff:g id="PROCESS">%1$s</xliff:g> से ऐसे क्रैश जिनका पता नहीं चलता."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> रुक गया है"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> रुक गई है"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> रुक रहा है"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> रुक रही है"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"ऐप पुनः प्रारंभ करें"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"ऐप रीसेट करें और पुन: प्रारंभ करें"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"फ़ीडबैक भेजें"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"बंद करें"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"म्यूट करें"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"प्रतीक्षा करें"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"ऐप बंद करें"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> प्रतिसाद नहीं दे रहा है.\n\nक्‍या आप इसे बंद करना चाहते हैं?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"गतिविधि <xliff:g id="ACTIVITY">%1$s</xliff:g> प्रतिसाद नहीं दे रही है.\n\nक्या आप इसे बंद करना चाहते हैं?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> प्रतिसाद नहीं दे रहा है. क्या आप इसे बंद करना चाहते हैं?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g> प्रतिसाद नहीं दे रही है.\n\nक्‍या आप इसे बंद करना चाहते हैं?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> प्रतिसाद नहीं दे रहा है"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> प्रतिसाद नहीं दे रही है"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> प्रतिसाद नहीं दे रहा है"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> प्रक्रिया प्रतिसाद नहीं दे रही है"</string>
     <string name="force_close" msgid="8346072094521265605">"ठीक है"</string>
     <string name="report" msgid="4060218260984795706">"रिपोर्ट करें"</string>
     <string name="wait" msgid="7147118217226317732">"प्रतीक्षा करें"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"सिम कार्ड जोड़ा गया"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"सेल्युलर नेटवर्क एक्सेस करने के लिए अपना डिवाइस पुन: प्रारंभ करें."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"पुन: प्रारंभ करें"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"आपकी नई SIM ठीक से काम करे, इसके लिए आपको अपने वाहक से किसी ऐप को इंस्टॉल करना होगा और खोलना होगा."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ऐप प्राप्त करें"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"अभी नहीं"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"नई SIM डाली गई"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"इसे सेट करने के लिए टैप करें"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"समय सेट करें"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"दिनांक सेट करें"</string>
     <string name="date_time_set" msgid="5777075614321087758">"सेट करें"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"अनपिन करने से पहले पिन के लिए पूछें"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"अनपिन करने से पहले अनलॉक पैटर्न के लिए पूछें"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ऐप का आकार बदला नहीं जा सकता है, इसे दो अंगुलियों से स्क्रॉल करें."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ऐप का आकार बदला नहीं जा सकता है, इसे दो अंगुलियों से स्क्रॉल करें."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ऐप विभाजित स्‍क्रीन का समर्थन नहीं करता है."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"आपके नियंत्रक द्वारा इंस्‍टॉल किया गया"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"आपके नियंत्रक द्वारा अपडेट किया गया"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"आपके नियंत्रक द्वारा हटाया गया"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"विविध"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"आपने इन नोटिफिकेशन का महत्व सेट किया है."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"यह मौजूद व्यक्तियों के कारण महत्वपूर्ण है."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" नए उपयोगकर्ता को जोड़ने का प्रयास कर रहा है, लेकिन वह इस समय प्रतिबंधित है."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" नए उपयोगकर्ता को जोड़ने का प्रयास कर रहा है, लेकिन उपयोगकर्ता की सीमा पूरी हो गई है."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" नए उपयोगकर्ता को जोड़ने का प्रयास कर रहा है, लेकिन "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" खाता इस डिवाइस पर पहले से मौजूद है. फिर भी आगे बढ़ें?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" इस "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" खाते के लिए नया उपयोगकर्ता जोड़ने का प्रयास कर रहा है. आगे बढ़ें?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें (इस खाते वाला एक उपयोगकर्ता पहले से मौजूद है) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"भाषा प्राथमिकता"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"क्षेत्र प्राथमिकता"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"भाषा का नाम लिखें"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"सुझाए गए"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"सभी भाषाएं"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"खोजें"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बंद है"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"ऐप्स, पृष्ठभूमि समन्वयन और संबंधित सुविधाओं सहित कार्य प्रोफ़ाइल को काम करने की अनुमति दें"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"चालू करें"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s को अक्षम किया गया"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s व्‍यवस्‍थापक द्वारा अक्षम किया गया. अधिक जानने के लिए उनसे संपर्क करें."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"आपके पास नए संदेश हैं"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"देखने के लिए SMS ऐप खोलें"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"संभवत: कुछ फंक्‍शन उपलब्‍ध न हों"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"जारी रखने के लिए स्‍पर्श करें"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"उपयोगकर्ता प्रोफ़ाइल लॉक है"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> से कनेक्ट किया गया"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"फ़ाइलें देखने के लिए टैप करें"</string>
+    <string name="pin_target" msgid="3052256031352291362">"पिन करें"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"अनपिन करें"</string>
+    <string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 2584260..407841f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -215,8 +215,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivno izvješće"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"To možete upotrebljavati u većini slučajeva. Moći ćete pratiti izradu izvješća i unijeti više pojedinosti o problemu. Mogu se izostaviti neki odjeljci koji se upotrebljavaju rjeđe i produljuju izradu izvješća."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Potpuno izvješće"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Ta vam opcija omogućuje minimalno ometanje sustava kad uređaj ne reagira ili je prespor ili kada su vam potrebni svi odjeljci izvješća. Ne izrađuje se snimka zaslona i ne možete unijeti više pojedinosti."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Izrada snimke zaslona za izvješće o programskoj pogrešci za <xliff:g id="NUMBER_1">%d</xliff:g> sekundu.</item>
       <item quantity="few">Izrada snimke zaslona za izvješće o programskoj pogrešci za <xliff:g id="NUMBER_1">%d</xliff:g> sekunde.</item>
@@ -235,6 +234,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Sadržaj je skriven"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Sadržaj je skriven prema pravilima"</string>
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osobno"</string>
@@ -915,15 +915,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Odaberi radnju"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Odabir aplikacije za USB uređaj"</string>
     <string name="noApplications" msgid="2991814273936504689">"Tu radnju ne može izvesti nijedna aplikacija."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Nažalost, aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> prekinula je s radom."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Nažalost, zaustavljen je proces <xliff:g id="PROCESS">%1$s</xliff:g>."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Utišavanje se ruši od postupka <xliff:g id="PROCESS">%1$s</xliff:g> do ponovnog pokretanja."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> je zaustavljena"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Postupak <xliff:g id="PROCESS">%1$s</xliff:g> je zaustavljen"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> neprekidno se ruši"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Postupak <xliff:g id="PROCESS">%1$s</xliff:g> neprekidno se ruši"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Ponovo pokreni aplikaciju"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Vrati aplikaciju na zadano i pokreni ponovo"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Pošalji povratne informacije"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Zatvori"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Zanemari"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Čekaj"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Zatvori aplikaciju"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Aplikacija <xliff:g id="APPLICATION">%2$s</xliff:g> ne reagira.\n\nŽelite li je zatvoriti?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktivnost <xliff:g id="ACTIVITY">%1$s</xliff:g> ne reagira.\n\nŽelite li je zatvoriti?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> ne reagira. Želite li je zatvoriti?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Postupak <xliff:g id="PROCESS">%1$s</xliff:g> ne reagira.\n\nŽelite li ga zatvoriti?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ne reagira"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ne reagira"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ne reagira"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> ne reagira"</string>
     <string name="force_close" msgid="8346072094521265605">"U redu"</string>
     <string name="report" msgid="4060218260984795706">"Izvješće"</string>
     <string name="wait" msgid="7147118217226317732">"Pričekaj"</string>
@@ -1032,6 +1039,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM kartica dodana"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Za pristup mobilnoj mreži ponovo pokrenite uređaj."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Ponovno pokreni"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Postavljanje vremena"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Postavi datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Postavi"</string>
@@ -1465,7 +1482,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Traži PIN radi otkvačivanja"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Traži uzorak za otključavanje radi otkvačivanja"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži zaporku radi otkvačivanja"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Veličina aplikacije ne može se mijenjati, pomičite je s dva prsta."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veličina aplikacije ne može se mijenjati, pomičite je s dva prsta."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podržava podijeljeni zaslon."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalirao administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurira vaš administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisao administrator"</string>
@@ -1546,14 +1564,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Razno"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Postavili ste važnost tih obavijesti."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Važno je zbog uključenih osoba."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" pokušava dodati novog korisnika, no to trenutačno nije dopušteno."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" pokušava dodati novog korisnika, no dosegnuto je ograničenje broja korisnika."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" pokušava dodati novog korisnika, ali račun "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" već postoji na ovom uređaju. Želite li ipak nastaviti?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" pokušava dodati novog korisnika za račun "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Želite li nastaviti?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Želite li dopustiti aplikaciji <xliff:g id="APP">%1$s</xliff:g> da izradi novog korisnika s računom <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Želite li dopustiti aplikaciji <xliff:g id="APP">%1$s</xliff:g> da izradi novog korisnika s računom <xliff:g id="ACCOUNT">%2$s</xliff:g> (korisnik s tim računom već postoji)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Postavke jezika"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Postavke regije"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Unesite naziv jezika"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženo"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Pretraži"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Radni je način ISKLJUČEN"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Omogućuje radnom profilu da funkcionira, uključujući aplikacije, sinkronizaciju u pozadini i povezane značajke."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s – onemogućeno"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Onemogućio administrator (%1$s). Obratite mu se za više informacija."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite SMS aplikaciju da biste pregledali poruke"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Možda ima nedostupnih funkcija"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Dodirnite da biste nastavili"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Korisnički je profil zaključan"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> – veza je uspostavljena"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Dodirnite da biste pregledali datoteke"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Prikvači"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Otkvači"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index a5d8f14..22a9ac4 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktív jelentés"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Ezt használja a legtöbb esetben. Segítségével nyomon követheti a jelentés folyamatát, és további információkat kaphat a problémáról. A folyamat során kimaradhatnak az olyan kevésbé használt részek, amelyek jelentése túl sok időt igényel."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Teljes jelentés"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Ezt a beállítást minimális rendszerzavar esetén használja, amikor eszköze nem válaszol, túl lassú, illetve ha minden jelentésrészre szüksége van. A rendszer nem készít képernyőképet, illetve nem engedélyezi a hozzáférést a további részletekhez."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Képernyőkép készítése a hibajelentéshez <xliff:g id="NUMBER_1">%d</xliff:g> másodpercen belül.</item>
       <item quantity="one">Képernyőkép készítése a hibajelentéshez <xliff:g id="NUMBER_0">%d</xliff:g> másodpercen belül.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Tartalom elrejtve"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"A tartalom irányelv miatt elrejtve"</string>
     <string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Személyes"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Válasszon egy műveletet"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Válasszon egy alkalmazást az USB-eszközhöz"</string>
     <string name="noApplications" msgid="2991814273936504689">"Egy alkalmazás sem tudja végrehajtani ezt a műveletet."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás sajnos leállt."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Sajnos a <xliff:g id="PROCESS">%1$s</xliff:g> alkalmazás leállt."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"A(z) <xliff:g id="PROCESS">%1$s</xliff:g> összeomlásainak elnémítása az újraindításig."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> – az alkalmazás leállt"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> – az alkalmazás leállt"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás állandóan leáll"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"A(z) <xliff:g id="PROCESS">%1$s</xliff:g> folyamat állandóan leáll"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Alkalmazás újraindítása"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Alkalmazás alaphelyzetbe állítása és újraindítása"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Visszajelzés küldése"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Bezárás"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Némítás"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Várakozás"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Alkalmazás bezárása"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"A(z) <xliff:g id="APPLICATION">%2$s</xliff:g> nem válaszol.\n\nSzeretné bezárni?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"A(z) <xliff:g id="ACTIVITY">%1$s</xliff:g> tevékenység nem válaszol.\n\nSzeretné bezárni?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás nem válaszol. Szeretné bezárni?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"A(z) <xliff:g id="PROCESS">%1$s</xliff:g> folyamat nem válaszol. \n\nSzeretné bezárni?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"A(z) <xliff:g id="APPLICATION">%2$s</xliff:g> alkalmazás nem válaszol"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"A(z) <xliff:g id="ACTIVITY">%1$s</xliff:g> tevékenység nem válaszol"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás nem válaszol"</string>
+    <string name="anr_process" msgid="6156880875555921105">"A(z) <xliff:g id="PROCESS">%1$s</xliff:g> folyamat nem válaszol"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Jelentés"</string>
     <string name="wait" msgid="7147118217226317732">"Várakozás"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM kártya hozzáadva"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"A mobilhálózat eléréséhez indítsa újra az eszközt."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Újraindítás"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Idő beállítása"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Dátum beállítása"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Beállítás"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-kód kérése a rögzítés feloldásához"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Feloldási minta kérése a rögzítés feloldásához"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Jelszó kérése a rögzítés feloldásához"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Az alkalmazást nem lehet átméretezni – két ujjal görgessen."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Az alkalmazást nem lehet átméretezni – két ujjal görgessen."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Az alkalmazás nem támogatja az osztott képernyős nézetet."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"A rendszergazda telepítette"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Frissítette a rendszergazda"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"A rendszergazda törölte"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Vegyes"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Ön állította be ezen értesítések fontossági szintjét."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Ez az üzenet a résztvevők miatt fontos."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"A(z) "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" alkalmazás egy új felhasználót szeretne megadni, ami jelenleg nem engedélyezett."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"A(z) "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" alkalmazás egy új felhasználót szeretne megadni, azonban Ön elérte a felhasználók számára vonatkozó felső korlátot."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"A(z) "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" alkalmazás egy új felhasználót szeretne megadni, de a(z) "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" fiók már létezik ezen az eszközön. Ettől függetlenül is folytatja?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392">"A(z) "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" alkalmazás egy új felhasználót szeretne hozzáadni a(z) "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" fiókhoz. Folytatja a műveletet?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Engedélyezi a(z) <xliff:g id="APP">%1$s</xliff:g> számára, hogy új felhasználót hozzon létre a(z) <xliff:g id="ACCOUNT">%2$s</xliff:g> fiókkal?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Engedélyezi a(z) <xliff:g id="APP">%1$s</xliff:g> számára, hogy új felhasználót hozzon létre a(z) <xliff:g id="ACCOUNT">%2$s</xliff:g> fiókkal? (Már létezik felhasználó ezzel a fiókkal.)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Nyelvi beállítás"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Régió beállítása"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Adja meg a nyelvet"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Javasolt"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Minden nyelv"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Keresés"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"A munka mód KI van kapcsolva"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Munkaprofil használatának engedélyezése, beleértve az alkalmazásokat, a háttérben való szinkronizálást és a kapcsolódó funkciókat."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Bekapcsolás"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s letiltva"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"A(z) %1$s szervezet rendszergazdája letiltotta. További információért vegye fel vele a kapcsolatot."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Új üzenetei érkeztek"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"SMS-alkalmazás megnyitása a megtekintéshez"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Néhány funkció nem használható"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Érintse meg a folytatáshoz"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Felhasználói profil zárolva"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Csatlakoztatva a(z) <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> eszközhöz"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Koppintson ide a fájlok megtekintéséhez"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Rögzítés"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Feloldás"</string>
+    <string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string>
 </resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 1149ec1..dfdabaa 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Ինտերակտիվ զեկույց"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Հիմնականում օգտագործեք այս տարբերակը: Այն ձեզ թույլ է տալիս հետագծել զեկույցի ստեղծման գործընթացը և խնդրի մասին լրացուցիչ տեղեկություններ մուտքագրել: Կարող է բաց թողնել որոշ քիչ օգտագործվող բաժինները, որոնց ստեղծումը երկար է տևում:"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Ամբողջական զեկույց"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Օգտագործեք այս տարբերակը համակարգի միջամտությունը նվազեցնելու համար՝ երբ սարքը չի արձագանքում կամ շատ դանդաղ է աշխատում, կամ երբ ձեզ հարկավոր են զեկույցի բոլոր բաժինները: Էկրանի պատկեր չի լուսանկարում և ձեզ թույլ չի տալիս լրացուցիչ տվյալներ մուտքագրել:"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Վրիպակի զեկույցի համար էկրանի պատկերի լուսանկարումը կատարվելու է <xliff:g id="NUMBER_1">%d</xliff:g> վայրկյանից:</item>
       <item quantity="other">Վրիպակի զեկույցի համար էկրանի պատկերի լուսանկարումը կատարվելու է <xliff:g id="NUMBER_1">%d</xliff:g> վայրկյանից:</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Բովանդակությունը թաքցված է"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Բովանդակությունը թաքցվել է ըստ քաղաքականության"</string>
     <string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Անձնական"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Ընտրել գործողություն"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Ընտրեք հավելված USB սարքի համար"</string>
     <string name="noApplications" msgid="2991814273936504689">"Ոչ մի հավելված չի կարող կատարել այս գործողությունը:"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Ցավոք, <xliff:g id="APPLICATION">%1$s</xliff:g>-ը ընդհատվել է:"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Ցավոք, <xliff:g id="PROCESS">%1$s</xliff:g> գործընթացը դադարել է:"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Խափանում է տեղի ունենում <xliff:g id="PROCESS">%1$s</xliff:g>-ից վերաբեռնում ընկած ընթացքում:"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածի աշխատանքն ընդհատվել է"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> գործընթացն ընդհատվել է"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածի աշխատանքը շարունակաբար ընդհատվում է"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> գործընթացը շարունակաբար ընդհատվում է"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Վերագործարկել հավելվածը"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Վերակայել և վերագործարկել հավելվածը"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Ուղարկել կարծիք"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Փակել"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Անջատել ձայնը"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Սպասել"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Փակել հավելվածը"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g>-ը չի արձագանքում:\n\nՑանկանու՞մ եք փակել այն:"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> գործողությունը չի պատասխանում:\n\nՑանկանու՞մ եք այն փակել:"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g>-ը չի արձագանքում: Ցանկանու՞մ եք փակել այն:"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> գործընթացը չի արձագանքում:\n\nՑանկանու՞մ եք փակել այն:"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> հավելվածը չի արձագանքում"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> գործունեությունը չի արձագանքում"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը չի արձագանքում"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> գործընթացը չի արձագանքում"</string>
     <string name="force_close" msgid="8346072094521265605">"Լավ"</string>
     <string name="report" msgid="4060218260984795706">"Զեկույց"</string>
     <string name="wait" msgid="7147118217226317732">"Սպասեք"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM քարտը ավելացվել է"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Վերագործարկեք ձեր սարքը` բջջային ցանց մուտք ունենալու համար:"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Վերագործարկել"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Սահմանել ժամը"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Սահմանել ամսաթիվը"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Սահմանել"</string>
@@ -1201,7 +1218,7 @@
     <string name="activitychooserview_choose_application" msgid="2125168057199941199">"Ընտրել ծրագիր"</string>
     <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"Չհաջողվեց գործարկել <xliff:g id="APPLICATION_NAME">%s</xliff:g> ծրագիրը"</string>
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Տարածել"</string>
-    <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Համօգտագործել <xliff:g id="APPLICATION_NAME">%s</xliff:g>-ի հետ"</string>
+    <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Կիսվել <xliff:g id="APPLICATION_NAME">%s</xliff:g>-ի հետ"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Սահող բռնակ: Հպել &amp; պահել:"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Սահեցրեք` ապակողպելու համար:"</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Միացրեք ականջակալները` արտասանվող գաղտնաբառը լսելու համար:"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Ապաամրացնելուց առաջ հարցնել PIN-կոդը"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Ապաամրացնելուց առաջ հարցնել ապակողպող նախշը"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ապաամրացնելուց առաջ հարցնել գաղտնաբառը"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Հավելվածի չափը հնարավոր չէ փոխել, ոլորեք այն երկու մատի օգնությամբ:"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Հավելվածի չափը հնարավոր չէ փոխել, ոլորեք այն երկու մատի օգնությամբ:"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Հավելվածը չի աջակցում էկրանի տրոհումը:"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Ադմինիստրատորը տեղադրել է այն"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ադմինիստրատորը թարմացրել է այն"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Ադմինիստրատորը ջնջել է այն"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Զանազան"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Դուք սահմանել եք այս ծանուցումների կարևորությունը:"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Կարևոր է, քանի որ որոշակի մարդիկ են ներգրավված:"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" հավելվածը փորձում է նոր օգտվող ավելացնել, սակայն ներկայումս արգելափակված է:"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" հավելվածը փորձում է նոր օգտվող ավելացնել, սակայն օգտվողների քանակի սահմանաչափը լրացել է:"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" հավելվածը փորձում է նոր օգտվող ավելացնել, սակայն "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" հաշիվն այս սարքում արդեն գոյություն ունի: Շարունակե՞լ:"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" հավելվածը փորձում է "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" հաշվի համար նոր օգտվող ավելացնել: Շարունակե՞լ:"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Թույլ տա՞լ <xliff:g id="APP">%1$s</xliff:g> հավելվածին <xliff:g id="ACCOUNT">%2$s</xliff:g> հաշվով նոր Օգտվող ստեղծել:"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Թույլ տա՞լ <xliff:g id="APP">%1$s</xliff:g> հավելվածին <xliff:g id="ACCOUNT">%2$s</xliff:g> հաշվով նոր Օգտվող ստեղծել (նման հաշվով Օգտվող արդեն գոյություն ունի):"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Նախընտրելի լեզու"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Նախընտրելի տարածաշրջան"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Մուտքագրեք լեզուն"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Առաջարկներ"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Բոլոր լեզուները"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Որոնում"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Աշխատանքային ռեժիմն ԱՆՋԱՏՎԱԾ Է"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Թույլատրել աշխատանքային պրոֆիլի (այդ թվում նաև հավելվածների, ֆոնային համաժամացման և առնչվող գործառական հնարավորությունների) աշխատանքը:"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Միացնել"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s-ը կասեցվել է"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Կասեցվել է %1$s ադմինիստրատորի կողմից: Ավելին իմանալու համար կապվեք նրա հետ:"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Դուք ունեք նոր հաղորդագրություններ"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Դիտելու համար բացել SMS հավելվածը"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Հնարավոր է՝ որոշ գործառույթներ հասանելի չլինեն"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Հպեք՝ շարունակելու համար"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Օգտվողի պրոֆիլը կողպված է"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Միացված է <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>-ին"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Հպեք՝ ֆայլերը տեսնելու համար"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Ամրացնել"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Ապամրացնել"</string>
+    <string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 37084e3..4d4f45e 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Laporan interaktif"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Gunakan ini di berbagai keadaan. Ini memungkinkan Anda melacak kemajuan laporan dan memasukkan detail masalah selengkapnya. Mungkin menghilangkan beberapa bagian yang jarang digunakan dan yang perlu waktu lama untuk dilaporkan."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Laporan lengkap"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Gunakan opsi ini untuk meminimalkan gangguan sistem jika perangkat tidak responsif atau terlalu lambat, atau jika Anda perlu semua bagian laporan. Tidak akan mengambil tangkapan layar atau mengizinkan Anda memasukkan lebih banyak detail."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Mengambil tangkapan layar untuk laporan bug dalam <xliff:g id="NUMBER_1">%d</xliff:g> detik.</item>
       <item quantity="one">Mengambil tangkapan layar untuk laporan bug dalam <xliff:g id="NUMBER_0">%d</xliff:g> detik.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Konten tersembunyi"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Konten disembunyikan menurut kebijakan"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pribadi"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Pilih tindakan"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Pilih apl untuk perangkat USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Tidak ada apl yang dapat melakukan tindakan ini."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Sayangnya, <xliff:g id="APPLICATION">%1$s</xliff:g> telah berhenti."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Sayangnya, proses <xliff:g id="PROCESS">%1$s</xliff:g> telah berhenti."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Fitur bisu rusak akibat <xliff:g id="PROCESS">%1$s</xliff:g> hingga boot ulang."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> telah berhenti"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> telah berhenti"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> terus berhenti"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> terus berhenti"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Mulai ulang aplikasi"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Setel ulang dan mulai ulang aplikasi"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Kirim masukan"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Tutup"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Bisukan"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Tunggu"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Tutup aplikasi"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> tidak menanggapi.\n\nAnda ingin menutupnya?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktivitas <xliff:g id="ACTIVITY">%1$s</xliff:g> tidak menanggapi.\n\nAnda ingin menutupnya?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> tidak menanggapi. Anda ingin menutupnya?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> tidak menanggapi.\n\nAnda ingin menutupnya?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> tidak menanggapi"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> tidak menanggapi"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> tidak menanggapi"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> tidak menanggapi"</string>
     <string name="force_close" msgid="8346072094521265605">"Oke"</string>
     <string name="report" msgid="4060218260984795706">"Laporkan"</string>
     <string name="wait" msgid="7147118217226317732">"Tunggu"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Kartu SIM ditambahkan"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Mulai ulang perangkat untuk mengakses jaringan seluler."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Mulai Ulang"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Agar SIM baru bekerja dengan baik, Anda harus memasang dan membuka aplikasi dari operator."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"DAPATKAN APLIKASI"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"LAIN KALI"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"SIM baru dimasukkan"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Ketuk untuk menyiapkan"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Setel waktu"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setel tanggal"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Setel"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Meminta PIN sebelum melepas sematan"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Meminta pola pembukaan kunci sebelum melepas sematan"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Meminta sandi sebelum melepas sematan"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Aplikasi tidak dapat diubah ukurannya, gulir dengan dua jari."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Aplikasi tidak dapat diubah ukurannya, gulir dengan dua jari."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App tidak mendukung layar terpisah."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Dipasang oleh administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Diperbarui oleh administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Dihapus oleh administrator"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Lain-Lain"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Anda menyetel tingkat kepentingan notifikasi ini."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Ini penting karena orang-orang yang terlibat."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" mencoba menambahkan pengguna baru, tetapi saat ini dilarang."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" mencoba menambahkan pengguna baru, tetapi batas jumlah pengguna telah tercapai."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" mencoba menambahkan pengguna baru, tetapi akun "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" sudah ada di perangkat. Tetap lanjutkan?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" mencoba menambahkan pengguna baru untuk akun "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Lanjutkan?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Izinkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baru dengan <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Izinkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baru dengan <xliff:g id="ACCOUNT">%2$s</xliff:g> (Pengguna dengan akun ini sudah ada) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferensi bahasa"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferensi wilayah"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Ketik nama bahasa"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Disarankan"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Semua bahasa"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Telusuri"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Mode kerja NONAKTIF"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Izinkan profil kerja berfungsi, termasuk aplikasi, sinkronisasi latar belakang, dan fitur terkait."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktifkan"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s dinonaktifkan"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Dinonaktifkan oleh administrator %1$s. Hubungi administrator untuk mempelajari lebih lanjut."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Ada pesan baru"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Buka aplikasi SMS untuk melihat"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Beberapa fungsi tidak ada"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Sentuh untuk melanjutkan"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil pengguna terkunci"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Tersambung ke <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Ketuk untuk melihat file"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Pasang pin"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Lepas pin"</string>
+    <string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
 </resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 662d1dd..4ad48a9 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Gagnvirk skýrsla"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Þú getur notað þetta í flestum tilvikum. Með þessu móti geturðu fylgst með framgangi skýrslunnar og slegið inn viðbótarupplýsingar um vandamálið. Hugsanlegt er að lítið notuðum hlutum verði sleppt til að spara tíma."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Heildarskýrsla"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Notaðu þennan valmöguleika til að lágmarka truflun frá kerfinu þegar tækið þitt svarar ekki eða er of hægt, eða þegar þú þarft alla hluta skýrslunnar. Tekur ekki skjámynd eða leyfir þér að slá inn viðbótarupplýsingar."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Tekur skjámynd fyrir villutilkynningu eftir <xliff:g id="NUMBER_1">%d</xliff:g> sekúndu.</item>
       <item quantity="other">Tekur skjámynd fyrir villutilkynningu eftir <xliff:g id="NUMBER_1">%d</xliff:g> sekúndur.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Innihald falið"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Efni falið með reglu"</string>
     <string name="safeMode" msgid="2788228061547930246">"Örugg stilling"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android kerfið"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Persónulegt"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Veldu aðgerð"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Veldu forrit fyrir USB-tækið"</string>
     <string name="noApplications" msgid="2991814273936504689">"Engin forrit geta framkvæmt þessa aðgerð."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"<xliff:g id="APPLICATION">%1$s</xliff:g> lokaðist því miður."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Forritið <xliff:g id="PROCESS">%1$s</xliff:g> lokaðist því miður."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Þagga hrun frá <xliff:g id="PROCESS">%1$s</xliff:g> fram að endurræsingu."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> stöðvaðist"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> stöðvaðist"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> stöðvast ítrekað"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> stöðvast ítrekað"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Endurræsa forritið"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Endurstilla og endurræsa forritið"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Senda ábendingu"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Loka"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Þagga"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Bíða"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Loka forriti"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> svarar ekki.\n\nViltu loka því?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aðgerðin <xliff:g id="ACTIVITY">%1$s</xliff:g> svarar ekki.\n\nViltu loka henni?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> svarar ekki. Viltu að loka því?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Ferlið <xliff:g id="PROCESS">%1$s</xliff:g> svarar ekki.\n\nViltu loka því?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> svarar ekki"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> svarar ekki"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> svarar ekki"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Vinnslan <xliff:g id="PROCESS">%1$s</xliff:g> svarar ekki"</string>
     <string name="force_close" msgid="8346072094521265605">"Í lagi"</string>
     <string name="report" msgid="4060218260984795706">"Tilkynna"</string>
     <string name="wait" msgid="7147118217226317732">"Bíða"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-korti bætt við"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Endurræstu tækið til að tengjast farsímakerfinu."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Endurræsa"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Þú þarft að setja upp og opna forrit frá símafyrirtækinu þínu til að nýja SIM-kortið þitt virki eins og vera ber."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"SÆKJA FORRITIÐ"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"EKKI NÚNA"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Nýtt SIM-kort sett í"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Ýttu til að setja það upp"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Veldu tíma"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Veldu dagsetningu"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Velja"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Biðja um PIN-númer til að losa"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Biðja um opnunarmynstur til að losa"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Biðja um aðgangsorð til að losa"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Ekki er hægt að breyta stærð forritsins, flettu upp og niður með tveimur fingrum."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Ekki er hægt að breyta stærð forritsins; flettu upp og niður með tveimur fingrum."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Forritið styður ekki að skjánum sé skipt."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Uppsett af kerfisstjóra"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Uppfært af kerfisstjóranum"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eytt af kerfisstjóra"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Ýmislegt"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Þú stilltir mikilvægi þessara tilkynninga."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Þetta er mikilvægt vegna fólksins sem tekur þátt í þessu."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" er að reyna að bæta við nýjum notanda, en er sjálfur á bannlista."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" er að reyna að bæta við nýjum notanda, en notandahámarkinu hefur þegar verið náð."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" er að reyna að bæta við nýjum notanda, en reikningurinn "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" er nú þegar til á þessu tæki. Halda samt áfram?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" er að reyna að bæta nýjum notanda við reikninginn "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Halda áfram?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Leyfa <xliff:g id="APP">%1$s</xliff:g> að stofna nýjan notanda með <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Leyfa <xliff:g id="APP">%1$s</xliff:g> að stofna nýjan notanda með <xliff:g id="ACCOUNT">%2$s</xliff:g> (notandi með þennan reikning er þegar fyrir hendi)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Val tungumáls"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Svæðisval"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Sláðu inn heiti tungumáls"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Tillögur"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Öll tungumál"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Leita"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Slökkt á vinnusniði"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Leyfa virkni vinnusniðs, m.a. forrita, samstillingar í bakgrunni og tengdra eiginleika."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Kveikja"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s óvirkt"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Gert óvirkt af stjórnanda %1$s. Hafðu samband við hann til að fá frekari upplýsingar."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Þú ert með ný skilaboð"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Opnaðu SMS-forritið til að skoða"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Sumir eiginleikar e.t.v. ekki í boði"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Snertu til að halda áfram"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Notandaprófíll læstur"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Tengt við <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Ýttu til að skoða skrárnar"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Festa"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Losa"</string>
+    <string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 230f3e0..88bbf56 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Rapporto interattivo"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Utilizza questa opzione nella maggior parte dei casi. Ti consente di monitorare l\'avanzamento del rapporto e di inserire maggiori dettagli relativi al problema. Potrebbero essere omesse alcune sezioni meno utilizzate il cui inserimento nel rapporto richiede molto tempo."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Rapporto completo"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Utilizza questa opzione per ridurre al minimo l\'interferenza di sistema quando il dispositivo non risponde, è troppo lento oppure quando ti servono tutte le sezioni del rapporto. Non viene acquisito alcuno screenshot e non puoi inserire altri dettagli."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Lo screenshot per la segnalazione di bug verrà acquisito tra <xliff:g id="NUMBER_1">%d</xliff:g> secondi.</item>
       <item quantity="one">Lo screenshot per la segnalazione di bug verrà acquisito tra <xliff:g id="NUMBER_0">%d</xliff:g> secondo.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Contenuti nascosti"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Contenuti nascosti in base alle norme"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personale"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Scegli un\'azione"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Scegli un\'applicazione per il dispositivo USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Nessuna applicazione è in grado di eseguire questa azione."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"L\'applicazione <xliff:g id="APPLICATION">%1$s</xliff:g> si è bloccata in modo anomalo."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> si è interrotto."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Arresti anomali di Silence da <xliff:g id="PROCESS">%1$s</xliff:g> fino al riavvio."</string>
+    <string name="aerr_application" msgid="250320989337856518">"L\'app <xliff:g id="APPLICATION">%1$s</xliff:g> si è interrotta"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> si è interrotto"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"L\'app <xliff:g id="APPLICATION">%1$s</xliff:g> continua a interrompersi"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> continua a interrompersi"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Riavvia app"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Reimposta e riavvia app"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Invia feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Chiudi"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Disattiva"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Attendi"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Chiudi app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> non risponde.\n\nVuoi chiuderla?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"L\'attività <xliff:g id="ACTIVITY">%1$s</xliff:g> non risponde.\n\nVuoi chiuderla?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> non risponde. Vuoi chiuderla?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> non risponde.\n\nVuoi chiuderlo?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"L\'app <xliff:g id="APPLICATION">%2$s</xliff:g> non risponde"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"L\'app <xliff:g id="ACTIVITY">%1$s</xliff:g> non risponde"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"L\'app <xliff:g id="APPLICATION">%1$s</xliff:g> non risponde"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> non risponde"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Segnala"</string>
     <string name="wait" msgid="7147118217226317732">"Attendi"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Scheda SIM aggiunta"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Riavvia il dispositivo per accedere alla rete cellulare."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Riavvia"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Per far funzionare correttamente la tua nuova SIM, dovrai installare e aprire un\'app del tuo operatore."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"SCARICA L\'APP"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NON ORA"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Nuova SIM inserita"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Tocca per configurarla"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Imposta ora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Imposta data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Imposta"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Richiedi il PIN per lo sblocco"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Richiedi sequenza di sblocco prima di sbloccare"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Richiedi password prima di sbloccare"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Non è posssibile ridimensionare l\'app: scorri con due dita."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Non è possibile ridimensionare l\'app: scorri con due dita."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"L\'app non supporta la modalità Schermo diviso."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installato dall\'amministratore"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Aggiornato dall\'amministratore"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminato dall\'amministratore"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Vari"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Stabilisci tu l\'importanza di queste notifiche."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Importante a causa delle persone coinvolte."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" sta cercando di aggiungere un nuovo utente, ma l\'app non è consentita."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" sta cercando di aggiungere un nuovo utente, ma è stato raggiunto il limite massimo di utenti."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" sta cercando di aggiungere un nuovo utente, ma l\'account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" esiste già su questo dispositivo. Continuare comunque?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" sta cercando di aggiungere un nuovo utente per l\'account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Continuare?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Consentire a <xliff:g id="APP">%1$s</xliff:g> di creare un nuovo utente con <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Consentire a <xliff:g id="APP">%1$s</xliff:g> di creare un nuovo utente con <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Esiste già un utente con questo account)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferenza lingua"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Area geografica preferita"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Digita nome lingua"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggerite"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Tutte le lingue"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Cerca"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Modalità Lavoro DISATTIVATA"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Attiva il profilo di lavoro, incluse app, sincronizzazione in background e funzioni correlate."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Attiva"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disattivato"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Disattivato dall\'amministratore di %1$s. Contattalo per ulteriori informazioni."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Hai nuovi messaggi"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Apri l\'app SMS per la visualizzazione"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Alcune funzioni potrebbero non essere disponibili"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Tocca per continuare"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profilo utente bloccato"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Connesso a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Tocca per visualizzare i file"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Blocca"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Sblocca"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informazioni app"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 0278191..ffdfdab 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -216,13 +216,12 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"דוח אינטראקטיבי"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"השתמש באפשרות זו ברוב המקרים. היא מאפשרת לך לעקוב אחר התקדמות הדוח ולהזין פרטים נוספים על הבעיה. היא עשויה להשמיט כמה קטעים שנמצאים פחות בשימוש ואשר יצירת הדיווח עליהם נמשכת זמן רב."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"דוח מלא"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"השתמש באפשרות זו כדי שההפרעה למערכת תהיה מזערית, כשהמכשיר אינו מגיב או איטי מדי, או כשאתה זקוק לכל קטעי הדוח. לא ניתן ליצור צילום מסך או להזין פרטים נוספים."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="two">יוצר צילום מסך לדוח על באג בעוד <xliff:g id="NUMBER_1">%d</xliff:g> שניות.</item>
       <item quantity="many">יוצר צילום מסך לדוח על באג בעוד <xliff:g id="NUMBER_1">%d</xliff:g> שניות.</item>
       <item quantity="other">יוצר צילום מסך לדוח על באג בעוד <xliff:g id="NUMBER_1">%d</xliff:g> שניות.</item>
-      <item quantity="one">יוצר צילום מסך לדוח על באג בעוד <xliff:g id="NUMBER_0">%d</xliff:g> שנייה.</item>
+      <item quantity="one">יוצר צילום מסך לדוח על באג בעוד שנייה <xliff:g id="NUMBER_0">%d</xliff:g>.</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"מצב שקט"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"הקול כבוי"</string>
@@ -237,6 +236,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"התוכן מוסתר"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"התוכן מוסתר על ידי המדיניות"</string>
     <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏מערכת Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"אישי"</string>
@@ -921,15 +921,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"בחירת פעולה"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"‏בחר אפליקציה עבור התקן ה-USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"אין אפליקציות שיכולות לבצע פעולה זו."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"לצערנו, פעולת <xliff:g id="APPLICATION">%1$s</xliff:g> הופסקה."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"לצערנו, התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הופסק."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"השתק קריסות מ-<xliff:g id="PROCESS">%1$s</xliff:g> עד לאתחול."</string>
+    <string name="aerr_application" msgid="250320989337856518">"האפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> הפסיקה"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הפסיק"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"האפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> נעצרת שוב ושוב"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"האפליקציה <xliff:g id="PROCESS">%1$s</xliff:g> נעצרת שוב ושוב"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"הפעל מחדש את האפליקציה"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"אפס והפעל מחדש את האפליקציה"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"שלח משוב"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"סגור"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"השתק"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"המתן"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"סגור את האפליקציה"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> אינו מגיב.\n\nתרצה לסגור אותו?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"הפעילות <xliff:g id="ACTIVITY">%1$s</xliff:g> אינה מגיבה.\n\nתרצה לסגור אותה?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> אינו מגיב. תרצה לסגור אותו?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"תהליך <xliff:g id="PROCESS">%1$s</xliff:g> אינו מגיב.\n\nתרצה לסגור אותו?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"האפליקציה <xliff:g id="APPLICATION">%2$s</xliff:g> אינה מגיבה"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"האפליקציה <xliff:g id="ACTIVITY">%1$s</xliff:g> אינה מגיבה"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"האפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> אינה מגיבה"</string>
+    <string name="anr_process" msgid="6156880875555921105">"התהליך <xliff:g id="PROCESS">%1$s</xliff:g> אינו מגיב."</string>
     <string name="force_close" msgid="8346072094521265605">"אישור"</string>
     <string name="report" msgid="4060218260984795706">"שלח דוח"</string>
     <string name="wait" msgid="7147118217226317732">"המתן"</string>
@@ -1040,6 +1047,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"‏כרטיס ה-SIM נוסף"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"אתחל את המכשיר כדי לגשת אל הרשת הסלולרית."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"הפעל מחדש"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"הגדרת שעה"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"הגדר תאריך"</string>
     <string name="date_time_set" msgid="5777075614321087758">"הגדר"</string>
@@ -1475,7 +1492,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"‏בקש PIN לפני ביטול הצמדה"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"בקש קו ביטול נעילה לפני ביטול הצמדה"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"בקש סיסמה לפני ביטול הצמדה"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"אין אפשרות לשנות את גודל האפליקציה, גלול אותה בשתי אצבעות."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"אין אפשרות לשנות את גודל האפליקציה, גלול אותה בשתי אצבעות."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"האפליקציה אינה תומכת במסך מפוצל."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"הותקנה על ידי מנהל המערכת שלך"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"עודכן על ידי מנהל המערכת שלך"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"נמחקה על ידי מנהל המערכת שלך"</string>
@@ -1565,14 +1583,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"שונות"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"אתה מגדיר את החשיבות של ההודעות האלה."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ההודעה חשובה בשל האנשים המעורבים."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" מנסה להוסיף משתמש חדש, אך אין הרשאה מתאימה."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" מנסה להוסיף משתמש חדש, אך מכסת המשתמשים כבר מלאה."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" מנסה להוסיף משתמש חדש, אך החשבון "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" כבר קיים במכשיר זה. להמשיך בכל זאת?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" מנסה להוסיף משתמש חדש לחשבון "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". להמשיך?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"האם לאפשר ל-<xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש לחשבון <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"האם לאפשר ל-<xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש לחשבון <xliff:g id="ACCOUNT">%2$s</xliff:g> (כבר קיים משתמש לחשבון הזה) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"העדפת שפה"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"העדפת אזור"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"הקלד שם שפה"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"הצעות"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"כל השפות"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"חיפוש"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"מצב העבודה כבוי"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"אפשר לפרופיל העבודה לפעול, כולל אפליקציות, סנכרון ברקע ותכונות קשורות."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"הפעל"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"‏החבילה %1$s הושבתה"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"‏הושבתה על ידי מנהל המערכת של %1$s. צור איתו קשר כדי לקבל מידע נוסף."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"יש לך הודעות חדשות"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"‏פתח את אפליקציית ה-SMS כדי להציג"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"ייתכן שפונקציות מסוימות לא יהיו זמינות"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"גע כדי להמשיך"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"פרופיל המשתמש נעול"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"מחובר אל <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"הקש כדי להציג קבצים"</string>
+    <string name="pin_target" msgid="3052256031352291362">"הצמד"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"בטל הצמדה"</string>
+    <string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a92a800..7dc7653 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -233,6 +233,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g> 件)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"コンテンツが非表示"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ポリシーによって非表示になっているコンテンツ"</string>
     <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"個人用"</string>
@@ -909,15 +910,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"操作の選択"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USBデバイス用アプリを選択"</string>
     <string name="noApplications" msgid="2991814273936504689">"この操作を実行できるアプリはありません。"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"問題が発生したため、<xliff:g id="APPLICATION">%1$s</xliff:g>を終了します。"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"問題が発生したため、プロセス「<xliff:g id="PROCESS">%1$s</xliff:g>」を終了します。"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"再起動するまで「<xliff:g id="PROCESS">%1$s</xliff:g>」のクラッシュを表示しません。"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> が停止しました"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> が停止しました"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」が繰り返し停止しています"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"「<xliff:g id="PROCESS">%1$s</xliff:g>」が繰り返し停止しています"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"アプリを再起動"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"アプリをリセットして再起動"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"フィードバックを送信"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"閉じる"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"ミュート"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"待機"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"アプリを閉じる"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g>は応答していません。\n\nこのアプリを終了しますか?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"操作「<xliff:g id="ACTIVITY">%1$s</xliff:g>」は応答していません。\n\nこの操作を終了しますか?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g>は応答していません。このアプリを終了しますか?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"プロセス「<xliff:g id="PROCESS">%1$s</xliff:g>」は応答していません。\n\nこのプロセスを終了しますか?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"「<xliff:g id="APPLICATION">%2$s</xliff:g>」は応答していません"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"「<xliff:g id="ACTIVITY">%1$s</xliff:g>」は応答していません"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」は応答していません"</string>
+    <string name="anr_process" msgid="6156880875555921105">"プロセス「<xliff:g id="PROCESS">%1$s</xliff:g>」は応答していません"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"レポート"</string>
     <string name="wait" msgid="7147118217226317732">"待機"</string>
@@ -1024,6 +1032,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIMカードが追加されました"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"モバイルネットワークにアクセスするには端末を再起動してください。"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"再起動"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"時刻設定"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日付設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
@@ -1455,7 +1473,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"オフライン再生を解除する前にPINの入力を求める"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"オフライン再生を解除する前にパスワードの入力を求める"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"アプリのサイズは変更できません。2 本の指でスクロールしてください。"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"アプリのサイズは変更できません。2 本の指でスクロールしてください。"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"アプリで分割画面がサポートされていません。"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"管理者によってインストールされました"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"管理者によって更新されています"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"管理者によって削除されました"</string>
@@ -1527,14 +1546,32 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"その他"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"このような通知の重要度を設定します。"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"関係するユーザーのため、この設定は重要です。"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" で新しいユーザーを追加しようとしていますが、現在この操作は禁止されています。"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" で新しいユーザーを追加しようとしていますが、ユーザー数の上限に達しています。"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" で新しいユーザーを追加しようとしていますが、アカウント "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" は既にこの端末に存在します。続行しますか?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" でアカウント "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" に新しいユーザーを追加しようとしています。続行しますか?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> が <xliff:g id="ACCOUNT">%2$s</xliff:g> で新しいユーザーを作成できるようにしますか?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> が <xliff:g id="ACCOUNT">%2$s</xliff:g> で新しいユーザーを作成できるようにしますか?(このアカウントのユーザーはすでに存在します)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"言語設定"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"地域設定"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"言語名を入力"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"言語の候補"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"すべての言語"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"検索"</string>
+    <!-- no translation found for work_mode_off_title (8954725060677558855) -->
+    <skip />
+    <!-- no translation found for work_mode_off_message (3286169091278094476) -->
+    <skip />
+    <!-- no translation found for work_mode_turn_on (2062544985670564875) -->
+    <skip />
+    <!-- no translation found for suspended_package_title (3408150347778524435) -->
+    <skip />
+    <!-- no translation found for suspended_package_message (6341091587106868601) -->
+    <skip />
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"新着メッセージがあります"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"表示するには SMS アプリを開きます"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"一部の機能が利用できない可能性"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"続行するにはタップしてください"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"ユーザー プロフィールはロックされています"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> に接続しました"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"タップしてファイルを表示"</string>
+    <string name="pin_target" msgid="3052256031352291362">"固定"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"固定を解除"</string>
+    <string name="app_info" msgid="6856026610594615344">"アプリ情報"</string>
 </resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 3f5ad1f..be172aa 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ინტერაქტიული ანგარიში"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"გამოიყენეთ ეს ვარიანტი შემთხვევათა უმეტესობაში. ის საშუალებას მოგცემთ, თვალი მიადევნოთ ანგარიშის პროგრესს და პრობლემის შესახებ მეტი დეტალი შეიყვანოთ. ამ ვარიანტის არჩევის შემთხვევაში, შეიძლება მოხდეს ზოგიერთი ნაკლებად გამოყენებადი სექციის გამოტოვება, რომელთა შესახებ მოხსენებასაც დიდი დრო სჭირდება."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"სრული ანგარიში"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"გამოიყენეთ ეს ვარიანტი სისტემის ხარვეზების მინიმუმამდე დასაყვანად, როცა თქვენი მოწყობილობა არ რეაგირებს, მეტისმეტად ნელია, ან ანგარიშის ყველა სექცია გჭირდებათ. ამ შემთხვევაში, არ მოხდება ეკრანის ანაბეჭდის გადაღება თუ მეტი დეტალის შეყვანის მოთხოვნა."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">ხარვეზის შესახებ ანგარიშის ეკრანის ანაბეჭდის გადაღება მოხდება <xliff:g id="NUMBER_1">%d</xliff:g> წამში.</item>
       <item quantity="one">ხარვეზის შესახებ ანგარიშის ეკრანის ანაბეჭდის გადაღება მოხდება <xliff:g id="NUMBER_0">%d</xliff:g> წამში.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"შიგთავსი დამალულია"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"შიგთავსი დამალულია წესების შესაბამისად"</string>
     <string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-ის სისტემა"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"პირადი"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"აირჩიეთ მოქმედება"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB მოწყობილობისათვის აპის შერჩევა"</string>
     <string name="noApplications" msgid="2991814273936504689">"ვერც ერთი აპი ვერ შეასრულებს ამ ქმედებას."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"სამწუხაროდ, <xliff:g id="APPLICATION">%1$s</xliff:g> შეწყდა."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"სამწუხაროდ, პროცესი <xliff:g id="PROCESS">%1$s</xliff:g> შეწყდა."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"აპლიკაციის ჩუმი ავარიული გათიშვები <xliff:g id="PROCESS">%1$s</xliff:g>-იდან, გადატვირთვამდე."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> შეჩერდა"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> შეწყდა"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> განუწყვეტლივ ჩერდება"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> განუწყვეტლივ წყდება"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"აპის გადატვირთვა"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"გადაყენება და აპის გადატვირთვა"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"გამოხმაურება"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"დახურვა"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"დადუმება"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"მოცდა"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"აპის დახურვა"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> არ რეაგირებს.\n\nგსურთ, მისი დახურვა?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> აქტივობა არ რეაგირებს.\n\nგსურთ მისი დახურვა?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> არ რეაგირებს. გსურთ მისი დახურვა?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"პროცესი <xliff:g id="PROCESS">%1$s</xliff:g> არ რეაგირებს.\n\nგსურთ, მისი დახურვა?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> არ რეაგირებს"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> არ რეაგირებს"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> არ რეაგირებს"</string>
+    <string name="anr_process" msgid="6156880875555921105">"პროცესი — <xliff:g id="PROCESS">%1$s</xliff:g> არ რეაგირებს"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"ანგარიში"</string>
     <string name="wait" msgid="7147118217226317732">"მოცდა"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM ბარათი დაემატა"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"გადატვირთეთ თქვენი მოწყობილობა ფიჭურ ქსელზე წვდომისთვის."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"გადატვირთვა"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"დროის დაყენება"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"თარიღის დაყენება"</string>
     <string name="date_time_set" msgid="5777075614321087758">"დაყენება"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ფიქსაციის მოხსნამდე PIN-ის მოთხოვნა"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ფიქსაციის მოხსნამდე განბლოკვის ნიმუშის მოთხოვნა"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"აპის ზომა ვერ შეიცვლება. გადაადგილდით მასში ორი თითის მეშვეობით."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"აპის ზომა ვერ შეიცვლება. გადაადგილდით მასში ორი თითის მეშვეობით."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ეკრანის გაყოფა არ არის მხარდაჭერილი აპის მიერ."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"თქვენი ადმინისტრატორის მიერ დაყენებული"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"განახლებულია თქვენი ადმინისტრატორის მიერ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"თქვენი ადმინისტრატორის მიერ წაშლილი"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"სხვადასხვა"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"ამ შეტყობინებების მნიშვნელობის დონე განისაზღვრება თქვენ მიერ."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"მნიშვნელოვანია ჩართული მომხმარებლების გამო."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ახალი მომხმარებლის დამატებას ცდილობს, მაგრამ ამჟამად ეს მას ეკრძალება."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ახალი მომხმარებლის დამატებას ცდილობს, მაგრამ მიღწეულია მომხმარებლების ლიმიტი."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ახალი მომხმარებლის დამატებას ცდილობს, მაგრამ ანგარიში — "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" უკვე არსებობს ამ მოწყობილობაში. მაინც გსურთ გაგრძელება?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ცდილობს, ანგარიშს — "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ახალი მომხმარებელი დაუმატოს. გსურთ გაგრძელება?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"მიეცეს უფლება <xliff:g id="APP">%1$s</xliff:g>-ს, <xliff:g id="ACCOUNT">%2$s</xliff:g>-ის მეშვეობით ახალი მომხმარებელი შექმნას ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"მიეცეს უფლება <xliff:g id="APP">%1$s</xliff:g>-ს, <xliff:g id="ACCOUNT">%2$s</xliff:g>-ის მეშვეობით ახალი მომხმარებელი შექმნას (ამ ანგარიშის მქონე მომხმარებელი უკვე არსებობს) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"ენის პარამეტრები"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"რეგიონის პარამეტრები"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"აკრიფეთ ენის სახელი"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"რეკომენდებული"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ყველა ენა"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"ძიება"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"სამსახურის რეჟიმი გამორთულია"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"სამსახურის პროფილის მუშაობის დაშვება, მათ შორის, აპების, ფონური სინქრონიზაციის და დაკავშირებული ფუნქციების."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ჩართვა"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s გათიშულია"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"გათიშულია „%1$s“-ის ადმინისტრატორის მიერ. დაუკავშირდით მას მეტის გასაგებად."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"თქვენ ახალი შეტყობინებები გაქვთ"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"სანახავად, გახსენით SMS აპი"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"ზოგიერთი ფუნქცია შეიძლება მიუწვდომელი იყოს"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"შეეხეთ გასაგრძელებლად"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"მომხმარებლის პროფილი ჩაკეტილია"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"დაკავშირებულია <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>-თან"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"შეეხეთ ფაილების სანახავად"</string>
+    <string name="pin_target" msgid="3052256031352291362">"ჩამაგრება"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"ჩამაგრების მოხსნა"</string>
+    <string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
 </resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 25de46b..a9eecd9 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивті есеп"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Мұны жағдайлардың көпшілігінде пайдаланыңыз. Ол есептің орындалу барысын бақылауға және мәселе туралы қосымша мәліметтер енгізуге мүмкіндік береді. Ол есеп беруге ұзақ уақыт кететін кейбір азырақ пайдаланылатын бөлімдерді өткізіп жіберуі мүмкін."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Толық есеп"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Бұл параметрді құрылғы жауап бермей жатқанда немесе тым бояу кезде, я болмаса, барлық есеп бөлімдері керек кезде кедергілерді барынша азайту үшін пайдаланыңыз. Скриншот түсірілмейді немесе қосымша мәліметтер енгізуге рұқсат етілмейді."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> секундтан кейін қате туралы есептің скриншоты түсіріледі.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> секундтан кейін қате туралы есептің скриншоты түсіріледі.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Мазмұн жасырылған"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Мазмұн саясатқа сай жасырылған"</string>
     <string name="safeMode" msgid="2788228061547930246">"Қауіпсіз режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android жүйесі"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Жеке"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Әрекет таңдау"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB құрылғысы үшін қолданбаны таңдау"</string>
     <string name="noApplications" msgid="2991814273936504689">"Бұл әрекетті ешбір қолданба орындай алмайды."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Өкінішке орай, <xliff:g id="APPLICATION">%1$s</xliff:g> тоқтап қалды."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Өкінішке орай, <xliff:g id="PROCESS">%1$s</xliff:g> үрдісі тоқтап қалды."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Қайта жүктеуге дейін <xliff:g id="PROCESS">%1$s</xliff:g> жаңылыстарын басу."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> тоқтады"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> тоқтады"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> тоқтай береді"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> тоқтай береді"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Қолданбаны қайта іске қосу"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Ысырып, қолданбаны қайта іске қосу"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Пікір жіберу"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Жабу"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Үнсіз"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Күту"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Қолданбаны жабу"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> жауап бермей жатыр.\n\nОны жабу керек пе?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> әрекеті жауап бермей жатыр.\n\nОны жабу керек пе?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> жауап бермей жатыр. Оны жабу керек пе?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> процесі жауап бермей жатыр.\n\nОны жабу керек пе?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> жауап бермей жатыр"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> жауап бермей жатыр"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> жауап бермей жатыр"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> процесі жауап бермей жатыр"</string>
     <string name="force_close" msgid="8346072094521265605">"Жарайды"</string>
     <string name="report" msgid="4060218260984795706">"Баяндау"</string>
     <string name="wait" msgid="7147118217226317732">"Күту"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM картасы қосылды"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Ұялы желіге қатынасу үшін құрылғыны қайта іске қосыңыз."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Қайта бастау"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Уақытты реттеу"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Мезгілін реттеу"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Орнату"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Босату алдында PIN кодын сұрау"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Босату алдында бекітпесін ашу өрнегін сұрау"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Босату алдында құпия сөзді сұрау"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Қолданба өлшемін өзгерту мүмкін емес, оны екі саусақпен айналдырыңыз."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Қолданба өлшемін өзгерту мүмкін емес, оны екі саусақпен айналдырыңыз."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Қодланба бөлінген экранды қолдамайды."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Әкімші орнатқан"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Әкімші жаңартты"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Әкімші жойған"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Әр түрлі"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Сіз осы хабарландырулардың маңыздылығын орнатасасыз."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Қатысты адамдарға байланысты бұл маңызды."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" есептік жазбасы үшін жаңа пайдаланушыны қосуға тырысуда, бірақ қазіргі уақытта тыйым салынған."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" жаңа пайдаланушыны қосуға тырысуда, бірақ пайдаланушылар саны шегіне жетті."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" жаңа пайдаланушыны қосуға тырысуда, бірақ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" есептік жазбасы осы құрылғыда әлдеқашан бар. Бәрібір жалғастыру керек пе?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" есептік жазбасы үшін жаңа пайдаланушыны қосуға тырысуда. Жалғастыру керек пе?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасы бар жаңа пайдаланушы жасауға рұқсат ету керек пе?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасында жаңа пайдаланушы жасауға рұқсат ету керек пе (осы есептік жазбасы бар пайдаланушы әлдеқашан бар) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Тіл параметрі"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Аймақ параметрі"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Тіл атауын теріңіз"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Ұсынылған"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Барлық тілдер"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Іздеу"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Жұмыс режимі ӨШІРУЛІ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Жұмыс профиліне, соның ішінде, қолданбаларға, фондық синхрондауға және қатысты мүмкіндіктерге жұмыс істеуге рұқсат ету."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Қосу"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s өшірілген"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s әкімшісі өшірген. Қосымша мәліметтер алу үшін оларға хабарласыңыз."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Сізде жаңа хабарлар бар"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Көру үшін SMS қолданбасын ашыңыз"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Кейбір функциялар қол жетімді болмауы мүмкін"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Жалғастыру үшін түртіңіз"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Пайдаланушы профилі құлыпталған"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> қосылу орындалды"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Файлдарды көру үшін түртіңіз"</string>
+    <string name="pin_target" msgid="3052256031352291362">"PIN код"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Босату"</string>
+    <string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string>
 </resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 6b51f61..4dbb283 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"របាយការណ៍អន្តរកម្ម"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"ប្រើវាគ្រប់កាលៈទេសៈទាំងអស់។ វាអនុញ្ញាតឲ្យអ្នកតាមដានដំណើរការនៃរបាយការណ៍ និងចូលទៅព័ត៌មានលម្អិតបន្ថែមអំពីបញ្ហានេះ។ វាអាចនឹងលុបផ្នែកមួយចំនួនដែលមិនសូវប្រើចេញ ដែលធ្វើឲ្យចំណាយពេលយូរក្នុងការរាយការណ៍។"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"របាយការណ៍ពេញលេញ"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"ប្រើជម្រើសនេះដើម្បីកាត់បន្ថយការរំខានឲ្យនៅកម្រិតទាបបំផុតនៅពេលដែលឧបករណ៍របស់អ្នកមិនមានការឆ្លើយតប ឬដំណើរការយឺតពេក ឬនៅពេលដែលអ្នកត្រូវការផ្នែករាយការណ៍ទាំងអស់។ មិនថតរូបអេក្រង់ ឬអនុញ្ញាតឲ្យអ្នកចូលទៅព័ត៌មានលម្អិតបន្ថែមទេ។"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">នឹងថតរូបអេក្រង់សម្រាប់របាយការណ៍កំហុសក្នុងរយៈពេល <xliff:g id="NUMBER_1">%d</xliff:g> វិនាទីទៀត។</item>
       <item quantity="one">នឹងថតរូបអេក្រង់សម្រាប់របាយការណ៍កំហុសក្នុងរយៈពេល <xliff:g id="NUMBER_0">%d</xliff:g> វិនាទីទៀត។</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"បាន​លាក់​មាតិកា"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"មាតិកាត្រូវបានលាក់ដោយផ្អែកលើគោលការណ៍"</string>
     <string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ប្រព័ន្ធ​​ Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ផ្ទាល់ខ្លួន"</string>
@@ -911,15 +911,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើស​សកម្មភាព​​"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"ជ្រើស​កម្មវិធី​សម្រាប់​ឧបករណ៍​យូអេសប៊ី"</string>
     <string name="noApplications" msgid="2991814273936504689">"គ្មាន​កម្មវិធី​អាច​អនុវត្ត​សកម្មភាព​នេះ។"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"ដោយ​បរាជ័យ <xliff:g id="APPLICATION">%1$s</xliff:g> បាន​បញ្ឈប់។"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"ដោយ​បរាជ័យ ដំណើរការ <xliff:g id="PROCESS">%1$s</xliff:g> បាន​បញ្ឈប់។"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"ការគាំងស្ងាត់ៗពី <xliff:g id="PROCESS">%1$s</xliff:g> រហូតទាល់តែចាប់ផ្តើមឡើងវិញ។"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> បានឈប់"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> បានឈប់"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ឈប់ដំណើរការម្តងហើយម្តងទៀត"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> ឈប់ដំណើរការម្តងហើយម្តងទៀត"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"ចាប់ផ្តើមកម្មវិធីឡើងវិញ"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"កំណត់ និងចាប់ផ្តើមកម្មវិធីឡើងវិញ"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"ផ្ញើមតិ"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"បិទ"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"បិទ"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"រង់ចាំ"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"បិទកម្មវិធី"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> មិន​ឆ្លើយតប។\n\nតើ​អ្នក​ចង់​បិទ​វា​ឬ?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"សកម្មភាព <xliff:g id="ACTIVITY">%1$s</xliff:g> មិន​ឆ្លើយតប។\n\nតើ​អ្នក​ចង់​បិទ​វា?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> មិន​ឆ្លើយតប។ តើ​អ្នក​ចង់​បិទ​វា?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"ដំណើរការ <xliff:g id="PROCESS">%1$s</xliff:g> មិន​ឆ្លើយតប។ \n\nតើ​អ្នក​ចង់​បិទ​វា​ឬ?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> មិនមានការឆ្លើយតបទេ"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> មិនមានការឆ្លើយតបទេ"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> មិនមានការឆ្លើយតបទេ"</string>
+    <string name="anr_process" msgid="6156880875555921105">"ដំណើរការ <xliff:g id="PROCESS">%1$s</xliff:g> មិនមានការឆ្លើយតបទេ"</string>
     <string name="force_close" msgid="8346072094521265605">"យល់​ព្រម​"</string>
     <string name="report" msgid="4060218260984795706">"រាយការណ៍"</string>
     <string name="wait" msgid="7147118217226317732">"រង់ចាំ"</string>
@@ -1026,6 +1033,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"បាន​បន្ថែម​ស៊ីម​កាត"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"ចាប់ផ្ដើម​ឧបករណ៍​របស់​អ្នក​ឡើងវិញ ដើម្បី​ចូល​ប្រើ​បណ្ដាញ​ចល័ត។"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"ចាប់ផ្ដើម​ឡើងវិញ"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"កំណត់​ម៉ោង​"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"កំណត់​កាល​បរិច្ឆេទ​"</string>
     <string name="date_time_set" msgid="5777075614321087758">"កំណត់"</string>
@@ -1457,7 +1474,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"សួរ​រក​កូដ PIN មុន​ពេល​ផ្ដាច់"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"សួរ​រក​លំនាំ​ដោះ​សោ​មុន​ពេល​ផ្ដាច់"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"សួរ​រក​ពាក្យ​សម្ងាត់​មុន​ពេល​ផ្ដាច់"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"កម្មវិធីមិនអាចផ្លាស់ប្តូរទំហំបានទេ សូមរមូរវាដោយប្រើម្រាមដៃពីរ។"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"កម្មវិធីមិនអាចផ្លាស់ប្តូរទំហំបានទេ សូមរមូរវាដោយប្រើម្រាមដៃពីរ។"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"កម្មវិធីមិនគាំទ្រអេក្រង់បំបែកជាពីរទេ"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"បានដំឡើងដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"បានធ្វើបច្ចុប្បន្នភាពដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"បានលុបដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
@@ -1529,14 +1547,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"ផ្សេងៗ"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"អ្នកបានកំណត់សារៈសំខាន់នៃការជូនដំណឹងទាំងនេះ"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"វាមានសារៈសំខាន់ដោយសារតែមនុស្សដែលពាក់ព័ន្ធ"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" កំពុងព្យាយាមបន្ថែមអ្នកប្រើថ្មី ប៉ុន្តែគណនីត្រូូវបានហាមឃាត់នាពេលបច្ចុប្បន្ន។"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" កំពុងព្យាយាមបន្ថែមអ្នកប្រើថ្មី ប៉ុន្តែបានឈានដល់ចំនួនកំណត់អ្នកប្រើហើយ។"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" កំពុងព្យាយាមបន្ថែមអ្នកប្រើថ្មី ប៉ុន្តែគណនី "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" មានរួចទៅហើយនៅលើឧបករណ៍នេះ។ បន្តទោះយ៉ាងណាក៏ដោយ?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" កំពុងព្យាយាមបន្ថែមអ្នកប្រើថ្មីសម្រាប់គណនី "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>"។ បន្តឬ?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"អនុញ្ញាតឲ្យ <xliff:g id="APP">%1$s</xliff:g> បង្កើតអ្នកប្រើថ្មីដោយប្រើ <xliff:g id="ACCOUNT">%2$s</xliff:g> ឬទេ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"អនុញ្ញាតឲ្យ <xliff:g id="APP">%1$s</xliff:g> បង្កើតអ្នកប្រើថ្មីដោយប្រើ <xliff:g id="ACCOUNT">%2$s</xliff:g> (មានអ្នកប្រើសម្រាប់គណនីនេះរួចហើយ) ឬទេ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"ចំណូល​ចិត្ត​ភាសា"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ចំណូលចិត្តតំបន់"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"វាយបញ្ចូលឈ្មោះភាសា"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"បាន​ស្នើ"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ភាសាទាំងអស់"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"ស្វែងរក"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"របៀបការងារបានបិទ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"អនុញ្ញាតឲ្យប្រវត្តិរូបការងារដំណើរការ ដោយរាប់បញ្ចូលទាំងកម្មវិធី ការធ្វើសមកាលកម្មផ្ទៃខាងក្រោយ និងលក្ខណៈពិសេសដែលពាក់ព័ន្ធ។"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"បើក"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"បានបិទដំណើរការ %1$s"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"បិទដំណើរការដោយអ្នកគ្រប់គ្រង %1$s។ សូមទាក់ទងពួកគេដើម្បីស្វែងយល់បន្ថែម។"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"អ្នកមានសារថ្មី"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"បើកកម្មវិធីសារ SMS ដើម្បីមើល"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"មុខងារមួយចំនួនមិនអាចប្រើបានទេ"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"ប៉ះដើម្បីបន្ត"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"ប្រវត្តិរូបអ្នកប្រើត្រូវបានចាក់សោ"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"បានភ្ជាប់ទៅ <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ប៉ះដើម្បីមើលឯកសារ"</string>
+    <string name="pin_target" msgid="3052256031352291362">"ខ្ទាស់"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"មិនខ្ទាស់"</string>
+    <string name="app_info" msgid="6856026610594615344">"ព័ត៌មាន​កម្មវិធី"</string>
 </resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index d85d3984..d251f82 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ಪರಸ್ಪರ ಸಂವಹನ ವರದಿ"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"ಹೆಚ್ಚಿನ ಸಂದರ್ಭಗಳಲ್ಲಿ ಇದನ್ನು ಬಳಸಿ. ಇದು ವರದಿಯ ಪ್ರಗತಿಯನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಮತ್ತು ಸಮಸ್ಯೆ ಕುರಿತು ಹೆಚ್ಚಿನ ವಿವರಗಳನ್ನು ನಮೂದಿಸಲು ಅನುಮತಿಸುತ್ತದೆ. ಇದು ವರದಿ ಮಾಡಲು ಹೆಚ್ಚು ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುವಂತಹ ಕೆಲವು ಕಡಿಮೆ ಬಳಸಲಾದ ವಿಭಾಗಗಳನ್ನು ತ್ಯಜಿಸಬಹುದು."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"ಪೂರ್ಣ ವರದಿ"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"ನಿಮ್ಮ ಸಾಧನವು ಸ್ಪಂದಿಸುತ್ತಿಲ್ಲದಿರುವಾಗ ಅಥವಾ ತುಂಬಾ ನಿಧಾನವಾಗಿರುವಾಗ ಕನಿಷ್ಟ ಹಸ್ತಕ್ಷೇಪಕ್ಕಾಗಿ ಅಥವಾ ನಿಮಗೆ ಎಲ್ಲಾ ವಿಭಾಗಗಳೂ ಅಗತ್ಯವಿರುವಾಗ ಈ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ. ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಲು ಅಥವಾ ಹೆಚ್ಚಿನ ವಿವರಗಳನ್ನು ನಮೂದಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">ಬಗ್ ವರದಿ ಮಾಡಲು <xliff:g id="NUMBER_1">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಲಾಗುತ್ತಿದೆ.</item>
       <item quantity="other">ಬಗ್ ವರದಿ ಮಾಡಲು <xliff:g id="NUMBER_1">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಲಾಗುತ್ತಿದೆ.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ವಿಷಯಗಳನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ನೀತಿಯಿಂದ ಮರೆಮಾಡಲಾಗಿರುವ ವಿಷಯಗಳು"</string>
     <string name="safeMode" msgid="2788228061547930246">"ಸುರಕ್ಷಿತ ಮೋಡ್"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ಸಿಸ್ಟಂ"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ವೈಯಕ್ತಿಕ"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"ಕ್ರಿಯೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ಸಾಧನಕ್ಕೆ ಅಪ್ಲಿಕೇಶನ್‌‌ವೊಂದನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="noApplications" msgid="2991814273936504689">"ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಈ ಕ್ರಿಯೆಗಾಗಿ ಬದ್ಧತೆ ತೋರಿಸುವುದಿಲ್ಲ."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"ದುರದೃಷ್ಟವಶಾತ್, <xliff:g id="APPLICATION">%1$s</xliff:g> ಕೊನೆಗೊಂಡಿದೆ."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"ದುರದೃಷ್ಟವಶಾತ್, <xliff:g id="PROCESS">%1$s</xliff:g> ಪ್ರಕ್ರಿಯೆಯು ಕೊನೆಗೊಂಡಿದೆ."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"ರೀಬೂಟ್ ಮಾಡುವವರೆಗೆ <xliff:g id="PROCESS">%1$s</xliff:g> ನಿಂದ ಕ್ರ್ಯಾಶ್‌ಗಳನ್ನು ನಿಲ್ಲಿಸಿ."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ನಿಲ್ಲಿಸಿದೆ"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ನಿಲ್ಲಿಸಿದೆ"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ನಿಲ್ಲುತ್ತಲೇ ಇರುತ್ತದೆ"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> ನಿಲ್ಲುತ್ತಲೇ ಇರುತ್ತದೆ"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"ಅಪ್ಲಿಕೇಶನ್ ಮರುಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"ಅಪ್ಲಿಕೇಶನ್ ಮರುಹೊಂದಿಸಿ ಮತ್ತು ಮರುಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"ಪ್ರತಿಕ್ರಿಯೆ ಕಳುಹಿಸು"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"ಮುಚ್ಚು"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"ಮ್ಯೂಟ್"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"ನಿರೀಕ್ಷಿಸು"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಮುಚ್ಚಿ"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ.\n\nನೀವು ಅದನ್ನು ಮುಚ್ಚಲು ಬಯಸುವಿರಾ?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"ಚಟುವಟಿಕೆಯು <xliff:g id="ACTIVITY">%1$s</xliff:g> ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ.\n\nನೀವು ಅದನ್ನು ಮುಚ್ಚಲು ಬಯಸುವಿರಾ?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ. ನೀವು ಅದನ್ನು ಮುಚ್ಚಲು ಬಯಸುವಿರಾ?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"ಪ್ರಕ್ರಿಯೆಯು <xliff:g id="PROCESS">%1$s</xliff:g> ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ.\n\nನೀವು ಅದನ್ನು ಮುಚ್ಚಲು ಬಯಸುವಿರಾ?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ"</string>
+    <string name="anr_process" msgid="6156880875555921105">"ಪ್ರಕ್ರಿಯೆ <xliff:g id="PROCESS">%1$s</xliff:g> ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ"</string>
     <string name="force_close" msgid="8346072094521265605">"ಸರಿ"</string>
     <string name="report" msgid="4060218260984795706">"ವರದಿ ಮಾಡು"</string>
     <string name="wait" msgid="7147118217226317732">"ನಿರೀಕ್ಷಿಸು"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"ಸಿಮ್‌ ಕಾರ್ಡ್ ಸೇರಿಸಲಾಗಿದೆ"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"ಸೆಲ್ಯುಲಾರ್‌ ನೆಟ್‍ವರ್ಕ್ ಪ್ರವೇಶಿಸಲು ನಿಮ್ಮ ಸಾಧನವನ್ನು ಮರುಪ್ರಾರಂಭಿಸಿ."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"ಮರುಪ್ರಾರಂಭಿಸು"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"ನಿಮ್ಮ ಹೊಸ ಸಿಮ್ ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡಲು, ನಿಮ್ಮ ವಾಹಕದಿಂದ ಒಂದು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ನೀವು ಸ್ಥಾಪಿಸಬೇಕಾಗುತ್ತದೆ ಮತ್ತು ತೆರೆಯಬೇಕಾಗುತ್ತದೆ."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ಅಪ್ಲಿಕೇಶನ್ ಪಡೆದುಕೊಳ್ಳಿ"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"ಈಗ ಬೇಡ"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"ಹೊಸ ಸಿಮ್ ಸೇರಿಸಲಾಗಿದೆ"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"ಇದನ್ನು ಸ್ಥಾಪಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ಸಮಯವನ್ನು ಹೊಂದಿಸಿ"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ದಿನಾಂಕವನ್ನು ಹೊಂದಿಸಿ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"ಹೊಂದಿಸು"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಿನ್‌ ಕೇಳು"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅನ್‌ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್ ಕೇಳು"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ, ಅದನ್ನು ಎರಡು ಬೆರಳುಗಳಿಂದ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ, ಅದನ್ನು ಎರಡು ಬೆರಳುಗಳಿಂದ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಸ್ಥಾಪಿಸಲಾಗಿದೆ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ನವೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಅಳಿಸಲಾಗಿದೆ"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"ಇತರೆ"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"ನೀವು ಈ ಅಧಿಸೂಚನೆಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಿರುವಿರಿ."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ಜನರು ತೊಡಗಿಕೊಂಡಿರುವ ಕಾರಣ ಇದು ಅತ್ಯಂತ ಪ್ರಮುಖವಾಗಿದೆ."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದಾರೆ, ಆದರೆ ಪ್ರಸ್ತುತವಾಗಿ ನಿಷೇಧಿಸಲಾಗಿದೆ."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದಾರೆ, ಆದರೆ ಬಳಕೆದಾರರ ಮಿತಿಯನ್ನು ತಲುಪಲಾಗಿದೆ."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದಾರೆ, ಆದರೆ ಈ ಸಾಧನದಲ್ಲಿ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ಖಾತೆ ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ. ಹೇಗಾದರೂ ಮುಂದುವರೆಯುವುದೇ?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ಖಾತೆಗೆ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಲು "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದಾರೆ. ಮುಂದುವರೆಯುವುದೇ?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> ಮೂಲಕ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲು <xliff:g id="APP">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸುವುದೇ ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> (ಈ ಖಾತೆಯ ಬಳಕೆದಾರರು ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದ್ದಾರೆ) ಮೂಲಕ ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲು <xliff:g id="APP">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸುವುದೇ ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"ಭಾಷೆಯ ಪ್ರಾಶಸ್ತ್ಯ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ಪ್ರದೇಶ ಪ್ರಾಶಸ್ತ್ಯ"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ಭಾಷೆ ಹೆಸರನ್ನು ಟೈಪ್ ಮಾಡಿ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"ಸಲಹೆ ಮಾಡಿರುವುದು"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ಎಲ್ಲಾ ಭಾಷೆಗಳು"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"ಹುಡುಕು"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"ಕೆಲಸದ ಮೋಡ್ ಆಫ್ ಆಗಿದೆ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಹಿನ್ನೆಲೆ ಸಿಂಕ್ ಮತ್ತು ಇತರ ಸಂಬಂಧಿತ ವೈಶಿಷ್ಟ್ಯಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌‌ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಅನುಮತಿಸಿ."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ಆನ್ ಮಾಡು"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s ನಿರ್ವಾಹಕರಿಂದ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ. ಇನ್ನಷ್ಟು ತಿಳಿದುಕೊಳ್ಳಲು ಅವರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"ನೀವು ಹೊಸ ಸಂದೇಶಗಳನ್ನು ಹೊಂದಿರುವಿರಿ"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"ವೀಕ್ಷಿಸಲು SMS ಅಪ್ಲಿಕೇಶನ್ ತೆರೆಯಿರಿ"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"ಕೆಲವು ಫಂಕ್ಷನ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲದಿರಬಹುದು"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"ಮುಂದುವರಿಸಲು ಸ್ಪರ್ಶಿಸಿ"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"ಬಳಕೆದಾರ ಪ್ರೊಫೈಲ್ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ಫೈಲ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್‌ ಮಾಡಿ"</string>
+    <string name="pin_target" msgid="3052256031352291362">"ಪಿನ್ ಮಾಡು"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"ಅನ್‌ಪಿನ್"</string>
+    <string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 1a92e93..6f725aa 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"대화형 보고서"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"대부분의 경우 이 옵션을 사용합니다. 신고 진행 상황을 추적할 수 있고 문제에 대한 세부정보를 입력할 수 있습니다. 신고하기에 시간이 너무 오래 걸리고 사용 빈도가 낮은 일부 섹션을 생략할 수 있습니다."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"전체 보고서"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"기기가 응답하지 않거나 반응 속도가 너무 느린 경우 또는 모든 신고 섹션이 필요한 경우 이 최소 시스템 간섭 옵션을 사용합니다. 스크린샷을 찍지 않으며 세부정보 입력을 허용하지 않습니다."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">버그 신고 스크린샷을 <xliff:g id="NUMBER_1">%d</xliff:g>초 후에 찍습니다.</item>
       <item quantity="one">버그 신고 스크린샷을 <xliff:g id="NUMBER_0">%d</xliff:g>초 후에 찍습니다.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>개)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"숨겨진 콘텐츠"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"콘텐츠가 정책에 의해 숨겨졌습니다."</string>
     <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"개인"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"작업 선택"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB 기기에 대한 앱 선택"</string>
     <string name="noApplications" msgid="2991814273936504689">"작업을 수행할 수 있는 앱이 없습니다."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"<xliff:g id="APPLICATION">%1$s</xliff:g>(이)가 중지되었습니다."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"<xliff:g id="PROCESS">%1$s</xliff:g> 프로세스가 중지되었습니다."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"재부팅할 때까지 <xliff:g id="PROCESS">%1$s</xliff:g>에서 소리 없이 다운됨"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g>이(가) 중지됨"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g>이(가) 중지됨"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g>이(가) 계속 중단됨"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g>이(가) 계속 중단됨"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"앱 다시 시작"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"앱 재설정 및 다시 시작"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"의견 보내기"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"닫기"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"숨기기"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"대기"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"앱 닫기"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g>이(가) 응답하지 않습니다.\n\n닫으시겠습니까?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g>이(가) 응답하지 않습니다.\n\n닫으시겠습니까?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g>이(가) 응답하지 않습니다. 닫으시겠습니까?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> 프로세스가 응답하지 않습니다.\n\n닫으시겠습니까?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g>이(가) 응답하지 않음"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g>이(가) 응답하지 않음"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g>이(가) 응답하지 않음"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> 프로세스가 응답하지 않음"</string>
     <string name="force_close" msgid="8346072094521265605">"확인"</string>
     <string name="report" msgid="4060218260984795706">"신고"</string>
     <string name="wait" msgid="7147118217226317732">"대기"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM 카드 추가됨"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"이동통신망에 액세스하려면 기기를 다시 시작하세요."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"다시 시작"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"시간 설정"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"날짜 설정"</string>
     <string name="date_time_set" msgid="5777075614321087758">"설정"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"고정 해제 이전에 PIN 요청"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"고정 해제 이전에 잠금해제 패턴 요청"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"고정 해제 이전에 비밀번호 요청"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"앱에서 크기 조절이 불가능합니다. 두 손가락을 사용해 스크롤하세요."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"앱에서 크기 조절이 불가능합니다. 두 손가락을 사용해 스크롤하세요."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"앱이 화면 분할을 지원하지 않습니다."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"관리자가 설치함"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"관리자에 의해 업데이트됨"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"관리자가 삭제함"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"기타"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"이러한 알림의 중요도를 설정했습니다."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"관련된 사용자가 있으므로 중요합니다."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"에서 새 사용자를 추가하려고 하지만 현재 금지되어 있습니다."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"에서 새 사용자를 추가하려고 하지만 사용자 한도에 도달했습니다."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"에서 새 사용자를 추가하려고 하지만 계정 "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>"이(가) 이미 기기에 있습니다. 계속할까요?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"에서 계정 "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>"에 새 사용자를 추가하려고 합니다. 계속할까요?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="ACCOUNT">%2$s</xliff:g>(으)로 신규 사용자를 만들도록 허용하시겠습니까?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="ACCOUNT">%2$s</xliff:g>(이 계정의 사용자가 이미 있음)(으)로 신규 사용자를 만들도록 허용하시겠습니까?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"언어 환경설정"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"지역 환경설정"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"언어 이름 입력"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"추천"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"모든 언어"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"검색"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"직장 모드가 사용 중지됨"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"앱, 백그라운드 동기화 및 관련 기능을 포함한 직장 프로필이 작동하도록 허용"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"사용 설정"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s이(가) 사용 중지됨"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s 관리자에 의해 사용 중지되었습니다. 자세히 알아보려면 관리자에게 문의하세요."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"새 메시지 있음"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"SMS 앱을 열고 확인"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"일부 기능을 사용할 수 없음"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"계속하려면 터치하세요."</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"사용자 프로필이 잠겨 있습니다."</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>에 연결됨"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"파일을 확인하려면 탭하세요."</string>
+    <string name="pin_target" msgid="3052256031352291362">"고정"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"고정 해제"</string>
+    <string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
 </resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index f9dcce5..6b6145e 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивдүү кабар"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Ката жөнүндө кабардын абалын жана көйгөй тууралуу кошумча маалыматты көрсөтүү үчүн ушул функцияны колдонууну сунуштайбыз. Ката жөнүндө кабар жөнөтүлүп жатканда көп убакыт талап кылынбашы үчүн негизги бөлүмдөр гана көрүнөт."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Толук кабар берүү"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Түзмөгүңүз жооп бербей же өтө жай иштеп жатса, ошондой эле жөндөөлөрдүн бардык бөлүмдөрүн карап чыккыңыз келсе, ушул функцияны колдонуңуз. Баса, ката жөнүндө кошумча маалыматты көрсөтүп же скриншотту ала албайсыз."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Мүчүлүштүк тууралуу кабарлоо үчүн <xliff:g id="NUMBER_1">%d</xliff:g> секундда скриншот алынат.</item>
       <item quantity="one">Мүчүлүштүк тууралуу кабарлоо үчүн <xliff:g id="NUMBER_0">%d</xliff:g> секундда скриншот алынат.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Мазмундар жашырылган"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Тийиштүү саясат боюнча жашырылган мазмундар"</string>
     <string name="safeMode" msgid="2788228061547930246">"Коопсуз режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Тутуму"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Жеке"</string>
@@ -910,15 +910,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Аракет тандаңыз"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB түзмөгү үчүн колдонмо тандаңыз"</string>
     <string name="noApplications" msgid="2991814273936504689">"Бул аракетти аткара турган колдонмо жок."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Тилекке каршы, <xliff:g id="APPLICATION">%1$s</xliff:g> токтотулду."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Тилекке каршы, <xliff:g id="PROCESS">%1$s</xliff:g> процесси токтотулду."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Жымжырттык режиминде <xliff:g id="PROCESS">%1$s</xliff:g> колдонмосун иштетип жатканда ката кетиши мүмкүн. Ал ката түзмөктү өчүрүп-күйгүзгөндөн кийин жоюлат."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> токтотулду"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> токтотулду"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> кайра эле токтотулууда"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> кайра эле токтотулууда"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Колдонмону кайра жүргүзүү"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Колдонмону баштапкы абалга келтирип, кайра жүргүзүү"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Жооп пикир жөнөтүү"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Жабуу"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Үнсүз"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Күтүү"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Колдонмону жабуу"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> жооп бербей жатат.\n\nЖабылсынбы?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> аракети жооп бербей жатат.\n\nЖабылсынбы?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> жооп бербей жатат. Жабылсынбы?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> процесси жооп бербей жатат.\n\nЖабылсынбы?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> жооп бербей жатат"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> жооп бербей жатат"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> жооп бербей жатат"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> процесси жооп бербей жатат"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Кабарлоо"</string>
     <string name="wait" msgid="7147118217226317732">"Күтүү"</string>
@@ -1025,6 +1032,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-карта кошулду"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Уюктук тармакка кирүү үчүн түзмөгүңүздү өчүрүп күйгүзүңүз."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Кайра баштоо"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Убакыт орнотуу"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Күнүн орнотуу"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Коюу"</string>
@@ -1456,7 +1473,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Бошотуудан мурун PIN суралсын"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Бошотуудан мурун кулпуну ачкан үлгү суралсын"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Бошотуудан мурун сырсөз суралсын"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Колдонмонун көлөмүн өзгөртүүгө болбойт, андыктан эки манжаңыз менен сыдырып караңыз."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Колдонмонун көлөмүн өзгөртүүгө болбойт, андыктан эки манжаңыз менен сыдырып караңыз."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Колдонмо экранды бөлүүнү колдобойт."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Администраторуңуз тарабынан орнотулган"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Администраторуңуз жаңырткан"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Администраторуңуз тарабынан жок кылынган"</string>
@@ -1528,14 +1546,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Калган-каткандар"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Бул эскертмелердин маанилүүлүгүн белгиледиңиз."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Булар сиз үчүн маанилүү адамдар."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" жаңы колдонуучуну кошууга аракет кылууда, бирок учурда ага тыюу салынган."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" жаңы колдонуучуну кошууга аракет кылууда, бирок колдонуучулардын саны эң жогорку чекке жетип калды."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" жаңы колдонуучуну кошууга аракет кылууда, бирок түзмөктө мындай каттоо эсеби "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" мурунтан эле бар. Баары бир уланта бересизби?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" жаңы колдонуучуну "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" каттоо эсебине кошууга аракет кылууда. Улантылсынбы?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу <xliff:g id="ACCOUNT">%2$s</xliff:g> каттоо эсеби менен жаңы колдонуучу түзө берсинби ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу <xliff:g id="ACCOUNT">%2$s</xliff:g> каттоо эсеби менен жаңы колдонуучу түзө берсинби (мындай каттоо эсеби бар колдонуучу мурунтан эле бар) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Тил жөндөөлөрү"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Чөлкөмдүк жөндөөлөр"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Тилди киргизиңиз"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Сунушталган"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Бардык тилдер"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Издөө"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Жумуш режими ӨЧҮРҮЛГӨН"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Жумуш профилин, ошондой эле колдонмолорду, фондо шайкештирүү жана ага байланыштуу функцияларды иштетиңиз."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Күйгүзүү"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s өчүрүлгөн"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s администратору тарабынан өчүрүлгөн. Көбүрөөк билүү үчүн администраторго кайрылыңыз."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Сизге жаңы билдирүүлөр келди"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Көрүү үчүн SMS колдонмосун ачыңыз"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Айрым функциялар иштбши мүмкн"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Улантуу үчүн тийип коюңуз"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Колдонуучнн профили кулпулнгн"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> менен туташты"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Файлдарды көрүү үчүн таптап коюңуз"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Кадоо"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Кадоодон алып коюу"</string>
+    <string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string>
 </resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 1fe72ac..2e0a6ad 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ລາຍງານແບບໂຕ້ຕອບ"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"ໃຊ້ອັນນີ້ພາຍໃຕ້ສະພາບການສ່ວນໃຫຍ່. ມັນອະນຸຍາດໃຫ້ທ່ານຕິດຕາມຄວາມຄືບໜ້າຂອງລາຍງານ ແລະ ປ້ອນລາຍລະອຽດເພີ່ມເຕີມກ່ຽວກັບບັນຫາ. ມັນອາດຈະຕັດບາງສ່ວນທີ່ບໍ່ຄ່ອຍໄດ້ໃຊ້ທີ່ໃຊ້ເວລາດົນໃນການລາຍງານອອກໄປ."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"ລາຍງານເຕັມ"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"ໃຊ້ຕົວເລືອກນີ້ເພື່ອໃຫ້ມີການລົບກວນລະບົບໜ້ອຍສຸດ ເມື່ອອຸປະກອນຂອງທ່ານບໍ່ຕອບສະໜອງ ຫຼືຊ້າເກີນໄປ ຫຼື ເມື່ອທ່ານຕ້ອງການທຸກສ່ວນຂອງລາຍງານ. ຈະບໍ່ມີການຖ່າຍພາບໜ້າຈໍ ຫຼືອະນຸຍາດໃຫ້ທ່ານປ້ອນລາຍລະອຽດຕື່ມອີກ."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">ກຳລັງຈະຖ່າຍພາບໜ້າຈໍສຳລັບການລາຍງານຂໍ້ຜິດພາດໃນ <xliff:g id="NUMBER_1">%d</xliff:g> ວິນາທີ.</item>
       <item quantity="one">ກຳລັງຈະຖ່າຍພາບໜ້າຈໍສຳລັບການລາຍງານຂໍ້ຜິດພາດໃນ <xliff:g id="NUMBER_0">%d</xliff:g> ວິນາທີ.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ເນື້ອຫາ​ຖືກ​ເຊື່ອງ​ໄວ້"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ເນື້ອຫາຖືກເຊື່ອງຕາມນະໂຍບາຍ"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"​ສ່ວນ​ໂຕ"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"ເລືອກການເຮັດວຽກ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"ເລືອກແອັບຯສໍາລັບອຸປະກອນ USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"ບໍ່ມີແອັບຯໃດສາມາດເຮັດວຽກນີ້ໄດ້."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"ຂໍອະໄພ, <xliff:g id="APPLICATION">%1$s</xliff:g> ຢຸດການເຮັດວຽກແລ້ວ."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"ຂໍອະໄພ, ໂປຣເຊສ <xliff:g id="PROCESS">%1$s</xliff:g> ໄດ້ຢຸດການເຮັດວຽກແລ້ວ."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"ຄວາມ​ງຽບ​ຂັດ​ຂ້ອງ​ຈາກ <xliff:g id="PROCESS">%1$s</xliff:g> ຈົນ​ກ່​ວາ​ປິດ​ເປີດ​ໃໝ່."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ໄດ້ຢຸດແລ້ວ"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ໄດ້ຢຸດແລ້ວ"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ຢຸດເລື້ອຍໆ"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> ຢຸດເລື້ອຍໆ"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"ເລີ່ມແອັບໃໝ່"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"ຣີເຊັດ ແລະ ເລີ່ມແອັບໃໝ່"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"ສົ່ງຄຳຕິຊົມ"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"ປິດ"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"ປິດສຽງ"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"ລໍຖ້າ"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"ປິດແອັບ"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ບໍ່ຕອບສະໜອງ. \n\nທ່ານຕ້ອງການປິດມັນບໍ່?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"ການເຮັດວຽກ <xliff:g id="ACTIVITY">%1$s</xliff:g> ບໍ່ຕອບສະໜອງ. \n\n ທ່ານຕ້ອງການທີ່ຈະປິດມັນບໍ່?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ບໍ່ຕອບສະໜອງ. ທ່ານຕ້ອງການປິດມັນບໍ່?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"ໂປຣເຊສ <xliff:g id="PROCESS">%1$s</xliff:g> ບໍ່ຕອບສະໜອງ. \n\n ທ່ານຕ້ອງການປິດມັນບໍ່?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ບໍ່ຕອບສະໜອງ"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ບໍ່ຕອບສະໜອງ"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ບໍ່ຕອບສະໜອງ"</string>
+    <string name="anr_process" msgid="6156880875555921105">"ຂະບວນການ <xliff:g id="PROCESS">%1$s</xliff:g> ບໍ່ຕອບສະໜອງ"</string>
     <string name="force_close" msgid="8346072094521265605">"ຕົກລົງ"</string>
     <string name="report" msgid="4060218260984795706">"ລາຍງານ"</string>
     <string name="wait" msgid="7147118217226317732">"ລໍ​ຖ້າ"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"ເພີ່ມຊິມກາດແລ້ວ"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"​ຣີ​ສະ​ຕາດ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ເພື່ອ​ເຂົ້າ​ເຖິງ​ເຄືອ​ຂ່າຍ​ມື​ຖື."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"ຣີສະຕາດ"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ຕັ້ງເວລາ"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ກໍານົດວັນທີ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"ຕັ້ງຄ່າ"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"​ຖາມ​ຫາ PIN ກ່ອນ​ຍົກ​ເລີກ​ການປັກ​ໝຸດ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"​ຖາມ​ຫາ​ຮູບ​ແບບ​ປົດ​ລັອກ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"​ຖາມ​ຫາ​ລະ​ຫັດ​ຜ່ານ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ບໍ່ສາມາດປັບຂະໜາດແອັບຯໄດ້, ກະລຸນາເລື່ອນມັນໂດຍໃຊ້ນິ້ວສອງນິ້ວແທນ."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ບໍ່ສາມາດປັບຂະໜາດແອັບໄດ້, ໃຫ້ເລື່ອນມັນໂດຍໃຊ້ນິ້ວມືສອງນິ້ວ."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ແອັບບໍ່ຮອງຮັບໜ້າຈໍແບບແຍກກັນ."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ຜູ້​ຄວບ​ຄຸມ​ຂອງ​ທ່ານ​ຕິດ​ຕັ້ງ​ໃສ່​ແລ້ວ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ອັບ​ເດດ​ໂດຍ​ຜູ້​ຄວບ​ຄຸມ​ຂອງ​ທ່ານ​ແລ້ວ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ຖືກ​ຜູ້​ຄວບ​ຄຸມ​ຂອງ​ທ່ານ​ລຶບ​ໄປ​ແລ້ວ"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"ອື່ນໆ"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"ທ່ານຕັ້ງຄວາມສຳຄັນຂອງການແຈ້ງເຕືອນເຫຼົ່ານີ້."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ຂໍ້ຄວາມນີ້ສຳຄັນເນື່ອງຈາກບຸກຄົນທີ່ກ່ຽວຂ້ອງ."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ກຳລັງພະຍາຍາມເພີ່ມຜູ້ໃຊ້ໃໝ່, ແຕ່ຖືກຫ້າມໃນຂະນະນີ້."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ກຳລັງພະຍາຍາມເພີ່ມຜູ້ໃຊ້ໃໝ່, ແຕ່ໄດ້ຮອດຂີດຈຳກັດຜູ້ໃຊ້ແລ້ວ."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ກຳລັງພະຍາຍາມເພີ່ມຜູ້ໃຊ້ໃໝ່, ແຕ່ບັນຊີ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ມີຢູ່ແລ້ວໃນອຸປະກອນນີ້. ແນວໃດກໍດຳເນີນຕໍ່ບໍ?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ກຳລັງພະຍາຍາມເພີ່ມຜູ້ໃຊ້ໃໝ່ສຳລັບບັນຊີ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". ດຳເນີນຕໍ່ບໍ?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"ອະນຸຍາດໃຫ້ <xliff:g id="APP">%1$s</xliff:g> ສ້າງຜູ້ໃຊ້ໃໝ່ສຳລັບ <xliff:g id="ACCOUNT">%2$s</xliff:g> ບໍ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"ອະນຸຍາດໃຫ້ <xliff:g id="APP">%1$s</xliff:g> ສ້າງຜູ້ໃຊ້ໃໝ່ສຳລັບ <xliff:g id="ACCOUNT">%2$s</xliff:g> (ຜູ້ໃຊ້ສຳລັບບັນຊີນີ້ມີຢູ່ແລ້ວ) ບໍ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"ການຕັ້ງຄ່າພາສາ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ການຕັ້ງຄ່າພາກພື້ນ"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ພິມຊື່ພາສາ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"ແນະນຳ"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ທຸກພາ​ສາ​"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"ຄົ້ນຫາ"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"ໂໝດບ່ອນເຮັດວຽກປິດຢູ່"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"ອະນຸຍາດໃຫ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກສາມາດນຳໃຊ້ໄດ້ ເຊິ່ງຮວມທັງແອັບ, ການຊິ້ງຂໍ້ມູນໃນພື້ນຫຼັງ ແລະ ຄຸນສົມບັດທີ່ກ່ຽວຂ້ອງ."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ເປີດ​"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ຖືກປິດໃຊ້ແລ້ວ"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"ຖືກປິດໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ %1$s. ກະລຸນາຕິດຕໍ່ຫາພວກເຂົາເພື່ອສຶກສາເພີ່ມເຕີມ."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"ທ່ານມີຂໍ້ຄວາມໃໝ່"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"ເປີດແອັບ SMS ເພື່ອເບິ່ງ"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"ບາງຟັງຊັນອາດບໍ່ສາມາດໃຊ້ໄດ້"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"ແຕະເພື່ອສືບຕໍ່"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"ໂປຣໄຟລ໌ຜູ້ໃຊ້ຖືກລັອກໄວ້ແລ້ວ"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"ເຊື່ອມຕໍ່ກັບ <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ແລ້ວ"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ແຕະເພື່ອເບິ່ງໄຟລ໌"</string>
+    <string name="pin_target" msgid="3052256031352291362">"ປັກໝຸດ"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"ຖອນປັກໝຸດ"</string>
+    <string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2e78344..698cebe 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -216,8 +216,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interakt. ataskaita"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Naudokite tai esant daugumai aplinkybių. Galite stebėti ataskaitos eigą ir įvesti daugiau išsamios informacijos apie problemą. Gali būti praleidžiamos kelios nelabai naudingos skiltys, kurių ataskaitų teikimas ilgai trunka."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Išsami ataskaita"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Naudokite šią parinktį, kad būtų minimalūs sistemos trukdžiai, kai įrenginys nereaguoja ar yra per lėtas arba kai jums reikia visų skilčių. Nefiksuojama ekrano kopija arba leidžiama įvesti daugiau išsamios informacijos."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Pranešimo apie riktą ekrano kopija bus užfiksuota po <xliff:g id="NUMBER_1">%d</xliff:g> sekundės.</item>
       <item quantity="few">Pranešimo apie riktą ekrano kopija bus užfiksuota po <xliff:g id="NUMBER_1">%d</xliff:g> sekundžių.</item>
@@ -237,6 +236,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Turinys paslėptas"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Turinys paslėptas vadovaujantis politika"</string>
     <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
     <string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Asmeninė"</string>
@@ -921,15 +921,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Pasirinkti veiksmą"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Pasirinkite USB įrenginio programą"</string>
     <string name="noApplications" msgid="2991814273936504689">"Jokios programos negali atlikti šio veiksmo."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Deja, <xliff:g id="APPLICATION">%1$s</xliff:g> sustojo."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Deja, <xliff:g id="PROCESS">%1$s</xliff:g> sustojo."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Nutildyti „<xliff:g id="PROCESS">%1$s</xliff:g>“ strigtis iki paleidimo iš naujo."</string>
+    <string name="aerr_application" msgid="250320989337856518">"„<xliff:g id="APPLICATION">%1$s</xliff:g>“ sustabdyta"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> sustabdytas"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"„<xliff:g id="APPLICATION">%1$s</xliff:g>“ vis sustabdoma"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> vis sustabdomas"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Paleisti programą iš naujo"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Nustatyti ir paleisti programą iš naujo"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Siųsti atsiliepimą"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Uždaryti"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Paslėpti"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Laukti"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Uždaryti programą"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"„<xliff:g id="APPLICATION">%2$s</xliff:g>“ neatsako.\n\nAr norite ją uždaryti?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Veiksmas „<xliff:g id="ACTIVITY">%1$s</xliff:g>“ neatsako.\n\nAr norite jį uždaryti?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"„<xliff:g id="APPLICATION">%1$s</xliff:g>“ neatsako. Ar norite ją uždaryti?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Procesas „<xliff:g id="PROCESS">%1$s</xliff:g>“ neatsako.\n\nAr norite jį uždaryti?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"„<xliff:g id="APPLICATION">%2$s</xliff:g>“ neatsako"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"„<xliff:g id="ACTIVITY">%1$s</xliff:g>“ neatsako"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"„<xliff:g id="APPLICATION">%1$s</xliff:g>“ neatsako"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Procesas <xliff:g id="PROCESS">%1$s</xliff:g> neatsako"</string>
     <string name="force_close" msgid="8346072094521265605">"Gerai"</string>
     <string name="report" msgid="4060218260984795706">"Pranešti"</string>
     <string name="wait" msgid="7147118217226317732">"Palaukti"</string>
@@ -1040,6 +1047,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM kortelė pridėta"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Iš naujo paleiskite įrenginį, kad pasiektumėte korinį tinklą."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Paleisti iš naujo"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Kad nauja SIM kortelė veiktų tinkamai, turite įdiegti ir atidaryti iš operatoriaus gautą programą."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"GAUTI PROGRAMĄ"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NE DABAR"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Įdėta nauja SIM kortelė"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Jei norite tai nustatyti, palieskite"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nustatyti laiką"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nustatyti datą"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nustatyti"</string>
@@ -1475,7 +1487,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Prašyti PIN kodo prieš atsegant"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Prašyti atrakinimo piešinio prieš atsegant"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Prašyti slaptažodžio prieš atsegant"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Programos dydis nekeičiamas, slinkite dviem pirštais."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Programos dydis nekeičiamas, slinkite dviem pirštais."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Programoje nepalaikomas skaidytas ekranas."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Įdiegė administratorius"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atnaujino administratorius"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Ištrynė administratorius"</string>
@@ -1565,14 +1578,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Įvairūs"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Galite nustatyti šių pranešimų svarbą."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Tai svarbu dėl susijusių žmonių."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"„<xliff:g id="APP">%1$s</xliff:g>“"</b>" bando pridėti naują naudotoją, tačiau šiuo metu tai draudžiama."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"„<xliff:g id="APP">%1$s</xliff:g>“"</b>" bando pridėti naują naudotoją, tačiau pasiektas naudotojų skaičiaus apribojimas."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"„<xliff:g id="APP">%1$s</xliff:g>“"</b>" bando pridėti naują naudotoją, tačiau paskyra "<b>"„<xliff:g id="ACCOUNT">%2$s</xliff:g>“"</b>" jau yra šiame įrenginyje. Vis tiek tęsti?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"„<xliff:g id="APP">%1$s</xliff:g>“"</b>" bando pridėti naują paskyros "<b>"„<xliff:g id="ACCOUNT">%2$s</xliff:g>“"</b>" naudotoją. Tęsti?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Leisti „<xliff:g id="APP">%1$s</xliff:g>“ kurti naują <xliff:g id="ACCOUNT">%2$s</xliff:g> naudotoją?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Leisti „<xliff:g id="APP">%1$s</xliff:g>“ kurti naują <xliff:g id="ACCOUNT">%2$s</xliff:g> naudotoją (šią paskyrą naudojantis naudotojas jau yra)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Kalbos nuostata"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regiono nuostata"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Įveskite kalbos pav."</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Siūloma"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Visos kalbos"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Paieška"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Darbo režimas išjungtas"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Leisti veikti darbo profiliui, įskaitant programas, sinchronizavimą fone ir susijusias funkcijas."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Įjungti"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s išjungtas"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Išjungė %1$s administratorius. Kad sužinotumėte daugiau, susisiekite su juo."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Turite naujų pranešimų"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Atidaryti SMS programą, norint peržiūrėti"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Kelios funkc. gali būti nepas."</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Jei norite tęsti, palieskite"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Naudotojo profilis užrakintas"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Prisijungta prie „<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>“"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Palieskite, kad peržiūrėtumėte failus"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Prisegti"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Atsegti"</string>
+    <string name="app_info" msgid="6856026610594615344">"Programos informacija"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 9da04df..8c0081b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -215,8 +215,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktīvs pārskats"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Izmantojiet lielākajā daļā gadījumu. Varat izsekot pārskata izveides norisi un ievadīt papildu informāciju par problēmu. Var tikt izlaistas dažas mazāk izmantotas sadaļas, kuru izveidei nepieciešams daudz laika."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Viss pārskats"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Izmantojiet, lai minimāli iejauktos sistēmā, ja ierīce nereaģē, darbojas pārāk lēni vai ja ir nepieciešamas visas pārskata sadaļas. Netiek veikts ekrānuzņēmums, un nevarat ievadīt papildu informāciju."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="zero">Pēc <xliff:g id="NUMBER_1">%d</xliff:g> sekundēm tiks veikts ekrānuzņēmums kļūdas pārskatam.</item>
       <item quantity="one">Pēc <xliff:g id="NUMBER_1">%d</xliff:g> sekundes tiks veikts ekrānuzņēmums kļūdas pārskatam.</item>
@@ -235,6 +234,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Pārsniedz"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Saturs paslēpts"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Saskaņā ar politiku saturs ir paslēpts."</string>
     <string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personisks"</string>
@@ -915,15 +915,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Darbības izvēle"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Lietotnes izvēlēšanās USB ierīcei"</string>
     <string name="noApplications" msgid="2991814273936504689">"Šo darbību nevar veikt neviena lietotne."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Diemžēl lietojumprogrammas <xliff:g id="APPLICATION">%1$s</xliff:g> darbība ir apturēta."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Diemžēl process <xliff:g id="PROCESS">%1$s</xliff:g> ir apturēts."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Lietojumprogramma Silence avarē no procesa <xliff:g id="PROCESS">%1$s</xliff:g>, kamēr netiek atkārtoti palaista."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Lietotne <xliff:g id="APPLICATION">%1$s</xliff:g> pārtrauca darboties."</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Lietotne <xliff:g id="PROCESS">%1$s</xliff:g> pārtrauca darboties."</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> atkārtoti pārtrauc darboties"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> atkārtoti pārtrauc darboties"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Restartēt lietotni"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Atiestatīt un restartēt lietotni"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Sūtīt atsauksmes"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Aizvērt"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Nerādīt"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Gaidīt"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Aizvērt lietotni"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Lietojumprogramma <xliff:g id="APPLICATION">%2$s</xliff:g> nereaģē.\n\nVai vēlaties to aizvērt?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Darbība <xliff:g id="ACTIVITY">%1$s</xliff:g> nereaģē.\n\nVai vēlaties to aizvērt?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Lietojumprogramma <xliff:g id="APPLICATION">%1$s</xliff:g> nereaģē. Vai vēlaties to aizvērt?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Process <xliff:g id="PROCESS">%1$s</xliff:g> nereaģē.\n\nVai vēlaties to aizvērt?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> nereaģē"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nereaģē"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> nereaģē"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Process <xliff:g id="PROCESS">%1$s</xliff:g> nereaģē"</string>
     <string name="force_close" msgid="8346072094521265605">"Labi"</string>
     <string name="report" msgid="4060218260984795706">"Pārskats"</string>
     <string name="wait" msgid="7147118217226317732">"Gaidīt"</string>
@@ -1032,6 +1039,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM karte ir pievienota."</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Lai piekļūtu mobilajam tīklam, restartējiet ierīci."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Restartēt"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Iestatīt laiku"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datuma iestatīšana"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Iestatīt"</string>
@@ -1465,7 +1482,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Prasīt PIN kodu pirms atspraušanas"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pirms atspraušanas pieprasīt grafisko atslēgu"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pirms atspraušanas pieprasīt paroli"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Lietotnes lielumu nevar mainīt. Ritiniet to ar diviem pirkstiem."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Lietotnes lielumu nevar mainīt. Ritiniet to ar diviem pirkstiem."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Lietotnē netiek atbalstīta ekrāna sadalīšana."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalēja jūsu administrators"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atjaunināja administrators"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Izdzēsa jūsu administrators"</string>
@@ -1546,14 +1564,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Dažādi"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Jūs iestatījāt šo paziņojumu svarīguma līmeni."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Tas ir svarīgi iesaistīto personu dēļ."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" mēģina pievienot jaunu lietotāju, taču pašlaik tas ir aizliegts."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" mēģina pievienot jaunu lietotāju, taču ir sasniegts lietotāju skaita ierobežojums."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" mēģina pievienot jaunu lietotāju, taču šajā ierīcē jau ir izveidots konts "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Vai turpināt?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" mēģina pievienot jaunu lietotāju kontam "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Vai turpināt?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Vai atļaut lietotnei <xliff:g id="APP">%1$s</xliff:g> izveidot jaunu lietotāju, izmantojot e-pasta adresi <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Vai atļaut lietotnei <xliff:g id="APP">%1$s</xliff:g> izveidot jaunu lietotāju, izmantojot e-pasta adresi <xliff:g id="ACCOUNT">%2$s</xliff:g> (lietotājs ar šādu kontu jau pastāv)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Valodas preference"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Reģiona preference"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Ierakstiet valodas nosaukumu"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Ieteiktās"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Visas valodas"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Meklēt"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Darba režīms IZSLĒGTS"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Atļaujiet darboties darba profilam, tostarp lietotnēm, sinhronizācijai fonā un saistītajām funkcijām."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Ieslēgt"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Pakotne %1$s atspējota"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Atspējoja %1$s administrators. Lai uzzinātu vairāk, sazinieties ar administratoru."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Jums ir jaunas īsziņas."</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Lai skatītu, atveriet īsziņu lietotni."</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Dažas funkcijas var nebūt pieejamas"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Pieskarieties, lai turpinātu."</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Lietotāja profils ir bloķēts."</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Izveidots savienojums ar: <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Pieskarieties, lai skatītu failus."</string>
+    <string name="pin_target" msgid="3052256031352291362">"Piespraust"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Atspraust"</string>
+    <string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc200-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc200-az-rAZ/strings.xml
new file mode 100644
index 0000000..94e7f88
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200-es/strings.xml b/core/res/res/values-mcc310-mnc200-es/strings.xml
new file mode 100644
index 0000000..9ec401a
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200-hi/strings.xml b/core/res/res/values-mcc310-mnc200-hi/strings.xml
new file mode 100644
index 0000000..1d8272a
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200-in/strings.xml b/core/res/res/values-mcc310-mnc200-in/strings.xml
new file mode 100644
index 0000000..c71dbf7
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc200-mr-rIN/strings.xml
new file mode 100644
index 0000000..fc89cfc
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200-nl/strings.xml b/core/res/res/values-mcc310-mnc200-nl/strings.xml
new file mode 100644
index 0000000..22f8de2
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc200-pa-rIN/strings.xml
new file mode 100644
index 0000000..0083af3
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc200-pt-rPT/strings.xml
new file mode 100644
index 0000000..530b065
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc200-te-rIN/strings.xml
new file mode 100644
index 0000000..85f29ee
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200-zu/strings.xml b/core/res/res/values-mcc310-mnc200-zu/strings.xml
new file mode 100644
index 0000000..f4209a6
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9107329079910661798">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2841003137832065541">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6806975706640442517">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc210-az-rAZ/strings.xml
new file mode 100644
index 0000000..6a81835
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-es/strings.xml b/core/res/res/values-mcc310-mnc210-es/strings.xml
new file mode 100644
index 0000000..8fe5eba
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-hi/strings.xml b/core/res/res/values-mcc310-mnc210-hi/strings.xml
new file mode 100644
index 0000000..b560f04
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-in/strings.xml b/core/res/res/values-mcc310-mnc210-in/strings.xml
new file mode 100644
index 0000000..264bb51
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc210-mr-rIN/strings.xml
new file mode 100644
index 0000000..1d29585
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-nl/strings.xml b/core/res/res/values-mcc310-mnc210-nl/strings.xml
new file mode 100644
index 0000000..d90df12
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc210-pa-rIN/strings.xml
new file mode 100644
index 0000000..39bdd6405
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc210-pt-rPT/strings.xml
new file mode 100644
index 0000000..173d97d
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc210-te-rIN/strings.xml
new file mode 100644
index 0000000..d3141d8
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210-zu/strings.xml b/core/res/res/values-mcc310-mnc210-zu/strings.xml
new file mode 100644
index 0000000..cde0a8c
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="5217754856196352581">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4688475512286389971">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5475635312889002673">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc220-az-rAZ/strings.xml
new file mode 100644
index 0000000..e169bc2
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-es/strings.xml b/core/res/res/values-mcc310-mnc220-es/strings.xml
new file mode 100644
index 0000000..5292afe
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-hi/strings.xml b/core/res/res/values-mcc310-mnc220-hi/strings.xml
new file mode 100644
index 0000000..d1e7bd2
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-in/strings.xml b/core/res/res/values-mcc310-mnc220-in/strings.xml
new file mode 100644
index 0000000..075d2ef
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc220-mr-rIN/strings.xml
new file mode 100644
index 0000000..c401864
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-nl/strings.xml b/core/res/res/values-mcc310-mnc220-nl/strings.xml
new file mode 100644
index 0000000..ed37e20
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc220-pa-rIN/strings.xml
new file mode 100644
index 0000000..0da091d
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc220-pt-rPT/strings.xml
new file mode 100644
index 0000000..4fcb178
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc220-te-rIN/strings.xml
new file mode 100644
index 0000000..3529f93
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220-zu/strings.xml b/core/res/res/values-mcc310-mnc220-zu/strings.xml
new file mode 100644
index 0000000..f0c0f6a
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6238990105876016549">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="2866631708941520085">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="3422704506272221128">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc230-az-rAZ/strings.xml
new file mode 100644
index 0000000..f85048a
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-es/strings.xml b/core/res/res/values-mcc310-mnc230-es/strings.xml
new file mode 100644
index 0000000..034e47f
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-hi/strings.xml b/core/res/res/values-mcc310-mnc230-hi/strings.xml
new file mode 100644
index 0000000..61cdf58
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-in/strings.xml b/core/res/res/values-mcc310-mnc230-in/strings.xml
new file mode 100644
index 0000000..d385771
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc230-mr-rIN/strings.xml
new file mode 100644
index 0000000..008a2cc
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-nl/strings.xml b/core/res/res/values-mcc310-mnc230-nl/strings.xml
new file mode 100644
index 0000000..157bd3c
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc230-pa-rIN/strings.xml
new file mode 100644
index 0000000..20160e8
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc230-pt-rPT/strings.xml
new file mode 100644
index 0000000..d253f8f
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc230-te-rIN/strings.xml
new file mode 100644
index 0000000..f14c574
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230-zu/strings.xml b/core/res/res/values-mcc310-mnc230-zu/strings.xml
new file mode 100644
index 0000000..0b043d0
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="9007462326786949889">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="6747587721329739803">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="903741468703044544">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc240-az-rAZ/strings.xml
new file mode 100644
index 0000000..84575b6
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-es/strings.xml b/core/res/res/values-mcc310-mnc240-es/strings.xml
new file mode 100644
index 0000000..29b80aa
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-hi/strings.xml b/core/res/res/values-mcc310-mnc240-hi/strings.xml
new file mode 100644
index 0000000..9053137
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-in/strings.xml b/core/res/res/values-mcc310-mnc240-in/strings.xml
new file mode 100644
index 0000000..2d17f20
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc240-mr-rIN/strings.xml
new file mode 100644
index 0000000..d9ffd635
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-nl/strings.xml b/core/res/res/values-mcc310-mnc240-nl/strings.xml
new file mode 100644
index 0000000..c35dc6a
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc240-pa-rIN/strings.xml
new file mode 100644
index 0000000..0f1b5bc
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc240-pt-rPT/strings.xml
new file mode 100644
index 0000000..af05505
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc240-te-rIN/strings.xml
new file mode 100644
index 0000000..ccace1a
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240-zu/strings.xml b/core/res/res/values-mcc310-mnc240-zu/strings.xml
new file mode 100644
index 0000000..9aa62d3
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2734345662112241986">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5561711399459051107">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="6383482961309785661">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc250-az-rAZ/strings.xml
new file mode 100644
index 0000000..fb70ba85
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-es/strings.xml b/core/res/res/values-mcc310-mnc250-es/strings.xml
new file mode 100644
index 0000000..afe979d
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-hi/strings.xml b/core/res/res/values-mcc310-mnc250-hi/strings.xml
new file mode 100644
index 0000000..46c756b
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-in/strings.xml b/core/res/res/values-mcc310-mnc250-in/strings.xml
new file mode 100644
index 0000000..b1d5024
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc250-mr-rIN/strings.xml
new file mode 100644
index 0000000..a2a10e1
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-nl/strings.xml b/core/res/res/values-mcc310-mnc250-nl/strings.xml
new file mode 100644
index 0000000..f356b49
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc250-pa-rIN/strings.xml
new file mode 100644
index 0000000..29bac71
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc250-pt-rPT/strings.xml
new file mode 100644
index 0000000..4748260
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc250-te-rIN/strings.xml
new file mode 100644
index 0000000..81e7e3c8
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250-zu/strings.xml b/core/res/res/values-mcc310-mnc250-zu/strings.xml
new file mode 100644
index 0000000..fc845e7
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="3177110876268966">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5743977848030289234">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1221554601313232001">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc270-az-rAZ/strings.xml
new file mode 100644
index 0000000..71e7a8a
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-es/strings.xml b/core/res/res/values-mcc310-mnc270-es/strings.xml
new file mode 100644
index 0000000..733412a
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-hi/strings.xml b/core/res/res/values-mcc310-mnc270-hi/strings.xml
new file mode 100644
index 0000000..c91d0b5
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-in/strings.xml b/core/res/res/values-mcc310-mnc270-in/strings.xml
new file mode 100644
index 0000000..67edf3c
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc270-mr-rIN/strings.xml
new file mode 100644
index 0000000..650735c
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-nl/strings.xml b/core/res/res/values-mcc310-mnc270-nl/strings.xml
new file mode 100644
index 0000000..fd4957c
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc270-pa-rIN/strings.xml
new file mode 100644
index 0000000..d17c01f
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc270-pt-rPT/strings.xml
new file mode 100644
index 0000000..09a8dcb
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc270-te-rIN/strings.xml
new file mode 100644
index 0000000..d103e22
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc270-zu/strings.xml b/core/res/res/values-mcc310-mnc270-zu/strings.xml
new file mode 100644
index 0000000..49a2037
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="6674750523418536585">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5880767641285399402">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="5634367913183683816">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc310-az-rAZ/strings.xml
new file mode 100644
index 0000000..0748e91
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-es/strings.xml b/core/res/res/values-mcc310-mnc310-es/strings.xml
new file mode 100644
index 0000000..6dd980b
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-hi/strings.xml b/core/res/res/values-mcc310-mnc310-hi/strings.xml
new file mode 100644
index 0000000..611ec9c
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-in/strings.xml b/core/res/res/values-mcc310-mnc310-in/strings.xml
new file mode 100644
index 0000000..e65f265
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc310-mr-rIN/strings.xml
new file mode 100644
index 0000000..ce76a49
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-nl/strings.xml b/core/res/res/values-mcc310-mnc310-nl/strings.xml
new file mode 100644
index 0000000..0266e3d
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc310-pa-rIN/strings.xml
new file mode 100644
index 0000000..7e9b8a4
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc310-pt-rPT/strings.xml
new file mode 100644
index 0000000..e782c43
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc310-te-rIN/strings.xml
new file mode 100644
index 0000000..0161342
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310-zu/strings.xml b/core/res/res/values-mcc310-mnc310-zu/strings.xml
new file mode 100644
index 0000000..465ee60
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="1972026366984640493">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="1383416528714661108">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="7770475174975527040">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc490-az-rAZ/strings.xml
new file mode 100644
index 0000000..e74d247
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-es/strings.xml b/core/res/res/values-mcc310-mnc490-es/strings.xml
new file mode 100644
index 0000000..949fabb
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-hi/strings.xml b/core/res/res/values-mcc310-mnc490-hi/strings.xml
new file mode 100644
index 0000000..27f5351
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-in/strings.xml b/core/res/res/values-mcc310-mnc490-in/strings.xml
new file mode 100644
index 0000000..4ae2c34
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc490-mr-rIN/strings.xml
new file mode 100644
index 0000000..25564bd
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-nl/strings.xml b/core/res/res/values-mcc310-mnc490-nl/strings.xml
new file mode 100644
index 0000000..27c41cf
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc490-pa-rIN/strings.xml
new file mode 100644
index 0000000..39142f0
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc490-pt-rPT/strings.xml
new file mode 100644
index 0000000..743348b
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc490-te-rIN/strings.xml
new file mode 100644
index 0000000..a7ec753
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490-zu/strings.xml b/core/res/res/values-mcc310-mnc490-zu/strings.xml
new file mode 100644
index 0000000..f8468b7
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="2780619740658228275">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="4633656294483906293">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="1518868466785799436">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc660-az-rAZ/strings.xml
new file mode 100644
index 0000000..24d9da3
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-es/strings.xml b/core/res/res/values-mcc310-mnc660-es/strings.xml
new file mode 100644
index 0000000..1c107ef
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-hi/strings.xml b/core/res/res/values-mcc310-mnc660-hi/strings.xml
new file mode 100644
index 0000000..487af67
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-in/strings.xml b/core/res/res/values-mcc310-mnc660-in/strings.xml
new file mode 100644
index 0000000..a894b4c
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc660-mr-rIN/strings.xml
new file mode 100644
index 0000000..34a8182
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-nl/strings.xml b/core/res/res/values-mcc310-mnc660-nl/strings.xml
new file mode 100644
index 0000000..100d7fc
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc660-pa-rIN/strings.xml
new file mode 100644
index 0000000..57fc35e
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc660-pt-rPT/strings.xml
new file mode 100644
index 0000000..39b1ec1
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc660-te-rIN/strings.xml
new file mode 100644
index 0000000..ac3c891
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660-zu/strings.xml b/core/res/res/values-mcc310-mnc660-zu/strings.xml
new file mode 100644
index 0000000..9ee70df
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="4027376374798357928">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-FI, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-FI futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="5536938168415300276">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="979929705672330">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-az-rAZ/strings.xml b/core/res/res/values-mcc310-mnc800-az-rAZ/strings.xml
new file mode 100644
index 0000000..ac2fec3
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-az-rAZ/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"Operatorla qeydiyyatdan keçin"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"%s Wi-Fi Zəngi"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-es/strings.xml b/core/res/res/values-mcc310-mnc800-es/strings.xml
new file mode 100644
index 0000000..ca19be3
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-es/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"Para hacer llamadas y enviar mensajes por Wi-Fi, solicita a tu operador que configure este servicio y, cuando lo haga, vuelve a activar las llamadas por Wi-Fi en Ajustes."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"Regístrate con tu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"Llamada por Wi-Fi de %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-hi/strings.xml b/core/res/res/values-mcc310-mnc800-hi/strings.xml
new file mode 100644
index 0000000..c2b121b
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-hi/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"अपने वाहक के साथ पंजीकृत करें"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"%s वाई-फ़ाई कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-in/strings.xml b/core/res/res/values-mcc310-mnc800-in/strings.xml
new file mode 100644
index 0000000..52b1f6e
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-in/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"Harap daftarkan ke operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"Panggilan Wi-Fi %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc800-mr-rIN/strings.xml
new file mode 100644
index 0000000..1f360d5
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-mr-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"आपल्या वाहकासह नोंदणी करा"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"%s वाय-फाय कॉलिंग"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-nl/strings.xml b/core/res/res/values-mcc310-mnc800-nl/strings.xml
new file mode 100644
index 0000000..b87fce9
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-nl/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"Registreren bij je provider"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"Bellen via wifi van %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-pa-rIN/strings.xml b/core/res/res/values-mcc310-mnc800-pa-rIN/strings.xml
new file mode 100644
index 0000000..5923eba
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-pa-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"Wi-Fi \'ਤੇ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਹ ਸੇਵਾ ਸੈੱਟ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਤੋਂ Wi-Fi ਕਾਲਿੰਗ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ।"</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"%s Wi-Fi ਕਾਲਿੰਗ"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc800-pt-rPT/strings.xml
new file mode 100644
index 0000000..1ff0681
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as Chamadas Wi-Fi."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"Registar-se junto do seu operador"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"Chamadas Wi-Fi da %s"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc800-te-rIN/strings.xml
new file mode 100644
index 0000000..28bba73
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-te-rIN/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"Wi-Fiలో కాల్‌లు చేయడానికి మరియు సందేశాలు పంపడానికి, ముందుగా ఈ సేవను సెటప్ చేయమని మీ క్యారియర్‌ను అడగండి. ఆపై సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ను మళ్లీ ఆన్ చేయండి."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"%s Wi-Fi కాలింగ్"</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800-zu/strings.xml b/core/res/res/values-mcc310-mnc800-zu/strings.xml
new file mode 100644
index 0000000..1335ac5
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800-zu/strings.xml
@@ -0,0 +1,32 @@
+<?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 my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="8435554129271297367">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-FI, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-FI futhi kusukela kuzilungiselelo."</item>
+  </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="8993797655078232716">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8604078859021657352">"%s ukushaya kwe-Wi-Fi"</string>
+</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 14fe940..d67d78d 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивен извештај"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Користете го ова во повеќето ситуации. Ви дозволува да го следите напредокот на извештајот и да внесете повеќе детали во врска со проблемот. Може да испушти некои помалку користени делови за коишто е потребно долго време за да се пријават."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Целосен извештај"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Користете ја опцијава за да имате минимално системско попречување кога уредот не реагира или е премногу бавен, или кога ви требаат сите делови на извештајот. Не прави слика од екранот, ниту ви дозволува да внесете повеќе детали."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Ќе се направи слика од екранот за извештајот за грешки за <xliff:g id="NUMBER_1">%d</xliff:g> секунда.</item>
       <item quantity="other">Ќе се направи слика од екранот за извештајот за грешки за <xliff:g id="NUMBER_1">%d</xliff:g> секунди.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Содржините се скриени"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содржините се скриени поради политиката"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбеден режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Систем Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Лични"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Избери дејство"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Изберете апликација за УСБ-уредот"</string>
     <string name="noApplications" msgid="2991814273936504689">"Нема апликации што можат да го извршат ова дејство."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"За жал, <xliff:g id="APPLICATION">%1$s</xliff:g> запре."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"За жал, процесот <xliff:g id="PROCESS">%1$s</xliff:g> запре."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silence паѓа од <xliff:g id="PROCESS">%1$s</xliff:g> до рестартирањето."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> запре"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> запре"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> постојано запира"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> постојано запира"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Рестартирај ја апликацијата"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Ресетирај ја и рестартирај ја апликацијата"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Испрати повратни информации"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Затвори"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Исклучи звук"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Почекај"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Затвори ја апликацијата"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> не реагира.\n\nДали сакате да ја затворите?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Активноста <xliff:g id="ACTIVITY">%1$s</xliff:g> не реагира.\n\nДали сакате да ја затворите?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Апликацијата <xliff:g id="APPLICATION">%1$s</xliff:g> не реагира. Дали сакате да ја затворите?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Процесот <xliff:g id="PROCESS">%1$s</xliff:g> не реагира.\n\nДали сакате да го затворите?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> не реагира"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> не реагира"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> не реагира"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Процесот <xliff:g id="PROCESS">%1$s</xliff:g> не реагира"</string>
     <string name="force_close" msgid="8346072094521265605">"Во ред"</string>
     <string name="report" msgid="4060218260984795706">"Извештај"</string>
     <string name="wait" msgid="7147118217226317732">"Почекај"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Додадена е СИМ картичка"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Рестартирајте го уредот за да пристапите кон мобилна мрежа."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Рестартирај"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"За да работи правилно вашата нова СИМ-картичка, треба да ја инсталирате и да ја отворите апликацијата од операторот."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ПРЕЗЕМИ ЈА АПЛИКАЦИЈАТА"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"НЕ СЕГА"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Вметната е нова СИМ-картичка"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Допрете за да поставите"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Подеси време"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Постави датум"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Подеси"</string>
@@ -1457,7 +1469,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Прашај за ПИН пред откачување"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Прашај за шема за отклучување пред откачување"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Прашај за лозинка пред откачување"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Не може да се промени големината на апликацијата. Движете ја со два прста."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Не може да се промени големината на апликацијата, лизгајте ја со два прста."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Апликацијата не поддржува поделен екран."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирано од администраторот"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирано од администраторот"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Избришано од администраторот"</string>
@@ -1529,14 +1542,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Разно"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Ја поставивте важноста на известувањава."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Ова е важно заради луѓето кои се вклучени."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" се обидува да додаде нов корисник, но во моментов е забрането."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" се обидува да додаде нов корисник, но ограничувањето за корисници е достигнато."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" се обидува да додаде нов корисник, но сметката "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" веќе постои на уредот. Сепак продолжете?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" се обидува да додаде нов корисник за сметката "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Продолжете?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Дозволувате ли <xliff:g id="APP">%1$s</xliff:g> да создаде нов корисник со <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Дозволувате ли <xliff:g id="APP">%1$s</xliff:g> да создаде нов корисник со <xliff:g id="ACCOUNT">%2$s</xliff:g> (веќе постои корисник со оваа сметка)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Претпочитувања за јазик"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Претпочитувања за регион"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Внеси име на јазик"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Сите јазици"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Пребарај"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Режимот на работа е ИСКЛУЧЕН"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Дозволете работниот профил да функционира, вклучувајќи ги апликациите, синхронизирањето во заднина и други поврзани функции."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Вклучи"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s е оневозможен"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Оневозможено од администраторот на %1$s. Контактирајте со него за да дознаете повеќе."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Имате нови пораки"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Отворете ја апликацијата за СМС за приказ"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Некои функции се недостапни"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Допрете за да продолжите"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Корисничкиот профил е заклучен"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Поврзан на <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Допрете за да ги погледнете датотеките"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Прикачете"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Откачете"</string>
+    <string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string>
 </resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index ce3c32f..4054577 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -212,10 +212,9 @@
     <string name="bugreport_title" msgid="2667494803742548533">"ബഗ് റിപ്പോർട്ട് എടുക്കുക"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ഒരു ഇമെയിൽ സന്ദേശമായി അയയ്‌ക്കുന്നതിന്, ഇത് നിങ്ങളുടെ നിലവിലെ ഉപകരണ നിലയെക്കുറിച്ചുള്ള വിവരങ്ങൾ ശേഖരിക്കും. ബഗ് റിപ്പോർട്ട് ആരംഭിക്കുന്നതിൽ നിന്ന് ഇത് അയയ്‌ക്കാനായി തയ്യാറാകുന്നതുവരെ അൽപ്പസമയമെടുക്കും; ക്ഷമയോടെ കാത്തിരിക്കുക."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ഇന്റരാക്റ്റീവ് റിപ്പോർട്ട്"</string>
-    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"മിക്ക സാഹചര്യങ്ങളിലും ഇത് ഉപയോഗിക്കുക. റിപ്പോർട്ടിന്റെ പുരോഗതി കാണാനും പ്രശ്നത്തിന്റെ കൂടുതൽ വിശദാംശങ്ങളിലേക്ക് പ്രവേശിക്കാനും ഇത് അനുവദിക്കുന്നു. റിപ്പോർട്ടുചെയ്യാൻ നീണ്ട സമയം എടുക്കുന്ന, നിങ്ങൾ കുറവായി ഉപയോഗിക്കുന്ന ചില വിഭാഗങ്ങളെ ഇത് വിട്ടുകളഞ്ഞേക്കാം."</string>
+    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"മിക്ക സാഹചര്യങ്ങളിലും ഇത് ഉപയോഗിക്കുക. റിപ്പോർട്ടിന്റെ പുരോഗതി കാണാനും പ്രശ്നത്തിന്റെ കൂടുതൽ വിശദാംശങ്ങളിലേക്ക് പ്രവേശിക്കാനും ഇത് അനുവദിക്കുന്നു. റിപ്പോർട്ടുചെയ്യാൻ നീണ്ട സമയം എടുക്കുന്ന, നിങ്ങൾ കുറച്ച് ഉപയോഗിക്കുന്ന ചില വിഭാഗങ്ങളെ ഇത് വിട്ടുകളഞ്ഞേക്കാം."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"പൂർണ്ണ റിപ്പോർട്ട്"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"നിങ്ങളുടെ ഉപകരണം പ്രതികരിക്കുന്നില്ലെങ്കിലോ അതിനു വേഗത കുറവാണെങ്കിലോ നിങ്ങൾക്ക് എല്ലാ വിഭാഗങ്ങളും ആവശ്യമുള്ളപ്പോഴോ, സിസ്റ്റത്തിന്റെ തടസ്സം പരിമിതപ്പെടുത്തുന്നതിന്, ഈ ഓപ്ഷൻ ഉപയോഗിക്കുക. സ്ക്രീൻഷോട്ട് എടുക്കുകയോ കൂടുതൽ വിശദാംശങ്ങളിലേക്ക് പ്രവേശിക്കാൻ നിങ്ങളെ അനുവദിക്കുകയോ ചെയ്യില്ല."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">ബഗ് റിപ്പോർട്ടിനായി <xliff:g id="NUMBER_1">%d</xliff:g> സെക്കൻഡിൽ സ്ക്രീൻഷോട്ട് എടുക്കുന്നു.</item>
       <item quantity="one">ബഗ് റിപ്പോർട്ടിനായി <xliff:g id="NUMBER_0">%d</xliff:g> സെക്കൻഡിൽ സ്ക്രീൻഷോട്ട് എടുക്കുന്നു.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"കോൺടാക്‌റ്റുകൾ മറച്ചു"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"നയം അനുസരിച്ച് ഉള്ളടക്കം മറച്ചിരിക്കുന്നു"</string>
     <string name="safeMode" msgid="2788228061547930246">"സുരക്ഷിത മോഡ്"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android സിസ്റ്റം"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"വ്യക്തിഗതം"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"ഒരു പ്രവർത്തനം തിരഞ്ഞെടുക്കുക"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ഉപകരണത്തിന് ഒരു അപ്ലിക്കേഷൻ തിരഞ്ഞെടുക്കുക"</string>
     <string name="noApplications" msgid="2991814273936504689">"അപ്ലിക്കേഷനുകൾക്കൊന്നും ഈ പ്രവർത്തനം നിർവഹിക്കാനാവില്ല."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"നിർഭാഗ്യവശാൽ, <xliff:g id="APPLICATION">%1$s</xliff:g> പ്രവർത്തനം നിർത്തി."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"നിർഭാഗ്യവശാൽ, <xliff:g id="PROCESS">%1$s</xliff:g> എന്ന പ്രോസസ്സ് നിർത്തി."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"റീബൂട്ട് വരെ <xliff:g id="PROCESS">%1$s</xliff:g> എന്നതിൽ നിന്നുള്ള ക്രാഷ് സന്ദേശങ്ങൾ തടയുക."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> നിലച്ചിരിക്കുന്നു"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> നിലച്ചിരിക്കുന്നു"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> നിലയ്ക്കുന്നത് തുടരുന്നു"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> നിലയ്ക്കുന്നത് തുടരുന്നു"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"ആപ്പ് പുനഃരാരംഭിക്കുക"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"ആപ്പ് പുനഃക്രമീകരിച്ച് പുനഃരാരംഭിക്കുക"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"ഫീഡ്‌ബാക്ക് അയയ്‌ക്കുക"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"അടയ്‌ക്കുക"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"മ്യൂട്ടുചെയ്യുക"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"കാത്തിരിക്കുക"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"ആപ്പ് അടയ്‌ക്കുക"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g>, പ്രതികരിക്കുന്നില്ല.\n\nനിങ്ങൾക്കത് അടയ്‌ക്കണോ?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> പ്രവർത്തനം പ്രതികരിക്കുന്നില്ല.\n\nനിങ്ങൾക്കത് അടയ്‌ക്കണോ?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g>, പ്രതികരിക്കുന്നില്ല. നിങ്ങൾക്കത് അടയ്‌ക്കണോ?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> പ്രോസസ്സ് പ്രതികരിക്കുന്നില്ല.\n\nനിങ്ങൾക്കത് അടയ്‌ക്കണോ?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> പ്രതികരിക്കുന്നില്ല"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> പ്രതികരിക്കുന്നില്ല"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> പ്രതികരിക്കുന്നില്ല"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> എന്ന പ്രോസസ്സ് പ്രതികരിക്കുന്നില്ല"</string>
     <string name="force_close" msgid="8346072094521265605">"ശരി"</string>
     <string name="report" msgid="4060218260984795706">"റിപ്പോര്‍ട്ടുചെയ്യുക"</string>
     <string name="wait" msgid="7147118217226317732">"കാത്തിരിക്കുക"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"സിം കാർഡ് ചേർത്തു"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"സെല്ലുലാർ നെറ്റ്‌വർക്ക് ആക്‌സസ്സുചെയ്യാൻ നിങ്ങളുടെ ഉപകരണം പുനരാരംഭിക്കുക."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"പുനരാരംഭിക്കുക"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"സമയം സജ്ജീകരിക്കുക"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ദിവസം സജ്ജീകരിക്കുക"</string>
     <string name="date_time_set" msgid="5777075614321087758">"സജ്ജമാക്കുക"</string>
@@ -1049,7 +1066,7 @@
     <string name="remote_bugreport_progress_notification_message_can_cancel" msgid="5743435483005099451">"റദ്ദാക്കുന്നതിന് സ്പർശിക്കുക"</string>
     <string name="select_input_method" msgid="8547250819326693584">"കീബോഡ് മാറ്റുക"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"കീബോർഡുകൾ തിരഞ്ഞെടുക്കുക"</string>
-    <string name="show_ime" msgid="2506087537466597099">"ഭൗതിക കീബോർഡ് സജീവമായിരിക്കുമ്പോൾ സ്ക്രീനിൽ നിലനിർത്തുക"</string>
+    <string name="show_ime" msgid="2506087537466597099">"ഫിസിക്കൽ കീബോർഡ് സജീവമായിരിക്കുമ്പോൾ സ്ക്രീനിൽ നിലനിർത്തുക"</string>
     <string name="hardware" msgid="194658061510127999">"വെർച്വൽ കീബോർഡ് കാണിക്കുക"</string>
     <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"കീബോർഡ് ലേഔട്ട് തിരഞ്ഞെടുക്കുക"</string>
     <string name="select_keyboard_layout_notification_message" msgid="4465907700449257063">"ഒരു കീബോർഡ് ലേഔട്ട് തിരഞ്ഞെടുക്കാൻ സ്‌പർശിക്കുക."</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ചെയ്യുംമുമ്പ് പിൻ ചോദിക്കൂ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് അൺലോക്ക് പാറ്റേൺ ആവശ്യപ്പെടുക"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് പാസ്‌വേഡ് ആവശ്യപ്പെടുക"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ആപ്പിന്റെ വലുപ്പം ക്രമീകരിക്കാൻ കഴിയില്ല, രണ്ട് വിരലുകൾ ഉപയോഗിച്ച് അത് സ്ക്രോൾ ചെയ്യുക."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ആപ്പിന്റെ വലുപ്പം ക്രമീകരിക്കാൻ കഴിയില്ല, രണ്ട് വിരലുകൾ ഉപയോഗിച്ച് അത് സ്ക്രോൾ ചെയ്യുക."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"സ്പ്ലിറ്റ്-സ്ക്രീനിനെ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്റർ ഇൻസ്റ്റാളുചെയ്‌തു"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്റർ അപ്‌ഡേറ്റുചെയ്‌തു"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്റർ ഇല്ലാതാക്കി"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"പലവക"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"ഈ അറിയിപ്പുകളുടെ പ്രാധാന്യം നിങ്ങൾ സജ്ജീകരിച്ചു."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ഉൾപ്പെട്ടിട്ടുള്ള ആളുകളെ കണക്കിലെടുക്കുമ്പോള്‍ ഇത് പ്രധാനപ്പെട്ടതാണ്‌."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"പുതിയൊരു ഉപയോക്താവിനെ ചേർക്കാൻ "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ശ്രമിക്കുന്നു, എന്നാലിത് നിലവിൽ നിരോധിക്കപ്പെട്ടിരിക്കുന്നു."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"പുതിയൊരു ഉപയോക്താവിനെ ചേർക്കാൻ "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ശ്രമിക്കുന്നു, എന്നാൽ ഉപയോക്തൃ പരിധി എത്തിക്കഴിഞ്ഞിരിക്കുന്നു."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"പുതിയൊരു ഉപയോക്താവിനെ ചേർക്കാൻ "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ശ്രമിക്കുന്നു, എന്നാൽ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" എന്ന അക്കൗണ്ട് ഇതിനകം തന്നെ ഈ ഉപകരണത്തിൽ നിലവിലുണ്ട്. എന്തായാലും തുടരണോ?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" എന്ന അക്കൗണ്ടിനായി പുതിയൊരു ഉപയോക്താവിനെ ചേർക്കാൻ "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ശ്രമിക്കുന്നു. തുടരണോ?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> എന്ന അക്കൗണ്ട് ഉപയോഗിച്ച് പുതിയൊരു ഉപയോക്താവിനെ സൃഷ്ടിക്കാൻ <xliff:g id="APP">%1$s</xliff:g> എന്ന ആപ്പിനെ അനുവദിക്കണോ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> എന്ന അക്കൗണ്ട് (ഈ അക്കൗണ്ട് ഉപയോഗിച്ചുള്ള ഒരു ഉപയോക്താവ് ഇതിനകം തന്നെ നിലവിലുണ്ട്) ഉപയോഗിച്ച് പുതിയൊരു ഉപയോക്താവിനെ സൃഷ്ടിക്കാൻ <xliff:g id="APP">%1$s</xliff:g> എന്ന ആപ്പിനെ അനുവദിക്കണോ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"ഭാഷാ മുൻഗണന"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"മേഖലാ മുൻഗണന"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ഭാഷയുടെ പേര് ടൈപ്പുചെയ്യുക"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"നിര്‍‌ദ്ദേശിച്ചത്"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"എല്ലാ ഭാഷകളും"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"തിരയുക"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"ഔദ്യോഗിക മോഡ് ഓഫാണ്"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"ആപ്സും, പശ്ചാത്തല സമന്വയവും ബന്ധപ്പെട്ട ഫീച്ചറുകളും ഉൾപ്പെടെ, ഔദ്യോഗിക പ്രൊഫൈലിനെ പ്രവർത്തിക്കാൻ അനുവദിക്കുക."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ഓണാക്കുക"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s പ്രവർത്തനരഹിതമാക്കി"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s അഡ്മിനിസ്ട്രേറ്റർ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു. കൂടുതലറിയാൻ അഡ്മിനിസ്ട്രേറ്ററെ ബന്ധപ്പെടുക."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"നിങ്ങൾക്ക് പുതിയ സന്ദേശങ്ങൾ ഉണ്ട്"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"കാണുന്നതിന് SMS ആപ്പ് തുറക്കുക"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"ചില ഫംഗ്ഷനുകൾ ലഭ്യമായേക്കില്ല"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"തുടരുന്നതിന് സ്പർശിക്കുക"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"ഉപയോക്തൃ പ്രൊഫൈൽ ലോക്കുചെയ്തു"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്തു"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ഫയലുകൾ കാണുന്നതിന് ടാപ്പുചെയ്യുക"</string>
+    <string name="pin_target" msgid="3052256031352291362">"പിൻ ചെയ്യുക"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"അൺപിൻ ചെയ്യുക"</string>
+    <string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
 </resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 08233f8..3321b5d 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактив тайлан"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Ихэнх тохиолдолд үүнийг хэрэглэнэ үү. Энэ нь танд тайлангийн явцыг хянах болон асуудлын талаар дэлгэрэнгүйг мэдэх боломж олгоно. Таны бага ашигладаг, тайлагнахад хугацаа их шаарддаг зарим хэсгийг алгана."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Бүрэн тайлан"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Таны төхөөрөмж хариу үйлдэл үзүүлэхгүй байх, хэт удаан байх эсвэл танд тайлангийн бүх хэсэг хэрэгтэй үед ситемийн оролцоог хамгийн бага байлгах энэ сонголтыг ашиглана уу. Энэ нь дэлгэцийн зураг авах, эсвэл дэлгэрэнгүй мэдээлэлд хандахыг зөвшөөрөхгүй."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Алдааны тайлангийн дэлгэцийн зургийг <xliff:g id="NUMBER_1">%d</xliff:g> секундад авна.</item>
       <item quantity="one">Алдааны тайлангийн дэлгэцийн зургийг <xliff:g id="NUMBER_0">%d</xliff:g> секундад авна.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Контентыг нуусан"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Удирдамжийн дагуу нуусан агуулга"</string>
     <string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Андройд систем"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Хувийн"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Үйлдэл сонгох"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB төхөөрөмжийн апп-г сонгох"</string>
     <string name="noApplications" msgid="2991814273936504689">"Энэ ажиллагааг гүйцэтгэх апп байхгүй."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Харамсалтай, <xliff:g id="APPLICATION">%1$s</xliff:g> зогссон."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Харамсалтай нь <xliff:g id="PROCESS">%1$s</xliff:g> процесс зогссон."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Дахин эхлүүлэхгүй бол <xliff:g id="PROCESS">%1$s</xliff:g>-ээс гэмтэл гарсаар байна."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> зогсчихлоо"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> зогсчихлоо"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> зогссоор байна"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> зогссоор байна"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Апп-ыг дахин эхлүүлэх"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Апп-ыг шинэчилж, дахин эхлүүлэх"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Санал хүсэлт илгээх"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Хаах"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Дуу хаах"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Хүлээх"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Апп-ыг хаах"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> хариу өгөхгүй байна.\n\nТа хаамаар байна уу?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> активити хариу өгөхгүй байна.\n\nТа энийг хаах уу?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> хариу өгөхгүй байна. Та энийг хаамаар байна уу?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> процесс хариу өгөхгүй байн.\n\nТа хаамаар байна уу?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> хариу өгөхгүй байна"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> хариу өгөхгүй байна"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> хариу өгөхгүй байна"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> явц хариу өгөхгүй байна"</string>
     <string name="force_close" msgid="8346072094521265605">"Тийм"</string>
     <string name="report" msgid="4060218260984795706">"Мэдэгдэх"</string>
     <string name="wait" msgid="7147118217226317732">"Хүлээх"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM карт нэмэгдсэн"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Үүрэн сүлжээнд хандах бол төхөөрөмжөө дахин асаан уу."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Дахин эхлүүлэх"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Цагийн тохируулах"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Огноо оруулах"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Тохируулах"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Тогтоосныг суллахаас өмнө PIN асуух"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Тогтоосныг суллахаас өмнө түгжээ тайлах хээ асуух"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Апп-н хэмжээ нь өөрчлөгддөггүй. Үүнийг 2 хуруугаараа гүйлгэнэ үү."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Апп-ын хэмжээг өөрчлөх боломжгүй. Үүнийг 2 хуруугаар гүйлгэнэ үү."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Энэ апп нь дэлгэц хуваах тохиргоог дэмждэггүй."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Таны админ суулгасан байна"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Танай админ шинэчилсэн"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Таны админ устгасан байна"</string>
@@ -1525,14 +1543,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Бусад"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Та эдгээр мэдэгдлийн ач холбогдлыг тогтоосон."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Оролцсон хүмүүсээс шалтгаалан энэ нь өндөр ач холбогдолтой."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" шинэ хэрэглэгч нэмэхээр оролдож байгаа боловч одоогоор боломжгүй байна."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" шинэ хэрэглэгч нэмэхээр оролдож байгаа ч хэрэглэгчийн тооны хязгаарт хүрсэн байна."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" шинэ хэрэглэгч нэмэх гэсэн боловч "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" бүртгэл нь энэ төхөөрөмжид аль хэдийн бүртгэгдсэн байна. Үргэлжлүүлэх үү?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" нь "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" бүртгэлд шинэ хэрэглэгч нэмэх гэж байна. Үргэлжлүүлэх үү?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g>-г <xliff:g id="ACCOUNT">%2$s</xliff:g>-р шинэ Хэрэглэгч үүсгэхийг зөвшөөрөх үү?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g>-г <xliff:g id="ACCOUNT">%2$s</xliff:g>-р шинэ хэрэглэгч үүсгэхийг зөвшөөрөх үү (ийм бүртгэлтэй хэрэглэгч аль хэдийн байна) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Хэлний тохиргоо"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Бүс нутгийн тохиргоо"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Улсын хэлийг бичнэ үү"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Санал болгосон"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Бүх хэл"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Хайх"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Ажлын горимыг УНТРААСАН байна"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Ажлын профайлд апп, дэвсгэр синхрончлол болон бусад холбоотой тохиргоог ажиллахыг зөвшөөрнө үү."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Асаах"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s идэвхгүй болгосон"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s админ идэвхгүй болгосон. Дэлгэрэнгүй мэдэхийн тулд тэдэнтэй холбоо барина уу."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Танд шинэ зурвасууд байна"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Үзэхийн тулд SMS аппыг нээх"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Зарим функц байхгүй"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Үргэлжлүүлэхийн тулд дарах"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Хэрэглэгчийн профайл түгжээтэй"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>-д холбогдсон"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Файлыг үзэхийн тулд дарна уу"</string>
+    <string name="pin_target" msgid="3052256031352291362">"PIN"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
+    <string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string>
 </resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 30edff7..3041601 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"परस्परसंवादी अहवाल"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"बहुतांश प्रसंगांमध्‍ये याचा वापर करा. ते आपल्‍याला अहवालाच्या प्रगतीचा मागोवा घेण्‍याची आणि समस्येविषयी अधिक तपशील प्रविष्‍ट करण्‍याची अनुमती देतात. ते अहवाल देण्‍यासाठी बराच वेळ घेणार्‍या कमी वापरलेल्या विभागांना कदाचित वगळेल."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"संपूर्ण अहवाल"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"आपले डिव्‍हाइस प्रतिसाद देत नाही किंवा खूप धीमे होते किंवा आपल्‍याला सर्व अहवाल विभागांची आवश्‍यकता असते तेव्‍हा कमीत कमी सिस्टीम हस्तक्षेपासाठी या पर्यायाचा वापर करा. स्क्रीनशॉट घेत नाही किंवा आपल्‍याला अधिक तपशील प्रविष्‍ट करण्‍याची अनुमती देत नाही."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">दोष अहवालासाठी <xliff:g id="NUMBER_1">%d</xliff:g> सेकंदामध्‍ये स्क्रीनशॉट घेत आहे.</item>
       <item quantity="other">दोष अहवालासाठी <xliff:g id="NUMBER_1">%d</xliff:g> सेकंदांमध्‍ये स्क्रीनशॉट घेत आहे.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"लपविलेली सामग्री"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"धोरणाद्वारे सामग्री लपविली"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"वैयक्तिक"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"क्रिया निवडा"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB डिव्हाइससाठी अॅप निवडा"</string>
     <string name="noApplications" msgid="2991814273936504689">"कोणतेही अॅप्स ही क्रिया करू शकत नाहीत."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"दुर्दैवाने, <xliff:g id="APPLICATION">%1$s</xliff:g> थांबला."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"दुर्दैवाने, प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g> थांबली."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"रीबूट होईपर्यंत <xliff:g id="PROCESS">%1$s</xliff:g> मधून असे क्रॅश जे लक्षात येत नाहीत"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> थांबला आहे"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> थांबली आहे"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> थांबतो"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> थांबते"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"अॅप रीस्टार्ट करा"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"अॅप रीसेट आणि रीस्टार्ट करा"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"अभिप्राय पाठवा"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"बंद करा"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"नि:शब्द करा"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"प्रतीक्षा करा"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"अॅप बंद करा"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> प्रतिसाद देत नाही. \n\nआपण तो बंद करू इच्छिता?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> क्रियाकलाप प्रतिसाद देत नाही.\n\nआपण ती बंद करू इच्छिता?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> प्रतिसाद देत नाही. आपण तो बंद करू इच्छिता?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> प्रक्रिया प्रतिसाद देत नाही.\n\nआपण ती बंद करू इच्छिता?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> प्रतिसाद देत नाही"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> प्रतिसाद देत नाही"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> प्रतिसाद देत नाही"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> प्रक्रिया प्रतिसाद देत नाही"</string>
     <string name="force_close" msgid="8346072094521265605">"ठीक"</string>
     <string name="report" msgid="4060218260984795706">"अहवाल द्या"</string>
     <string name="wait" msgid="7147118217226317732">"प्रतीक्षा करा"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"सिम कार्ड जोडले"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"सेल्युलर नेटवर्कवर प्रवेश करण्यासाठी आपले डिव्हाइस रीस्टार्ट करा."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"रीस्टार्ट"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"आपल्या नवीन सिमने योग्यरित्या कार्य करण्यासाठी, आपल्याला अॅप स्थापित करण्याची आणि तो आपल्या वाहकामधून उघडण्याची आवश्यकता असेल."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"अ‍ॅप मिळवा"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"आता नाही"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"नवीन सिम घाला"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"ते सेट करण्यासाठी टॅप करा"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"वेळ सेट करा"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"तारीख सेट करा"</string>
     <string name="date_time_set" msgid="5777075614321087758">"सेट करा"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"अनपिन करण्‍यापूर्वी पिन साठी विचारा"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"अनपिन करण्‍यापूर्वी अनलॉक नमुन्यासाठी विचारा"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करण्‍यापूर्वी संकेतशब्दासाठी विचारा"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"अॅपचा आकार बदलण्यायोग्य नाही, दोन बोटांनी तो स्क्रोल करा."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"अॅपचा आकार बदलण्यायोग्य नाही, दोन बोटांनी तो स्क्रोल करा."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"अॅप स्क्रीन-विभाजनास समर्थन देत नाही."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"आपल्या प्रशासकाद्वारे स्थापित केले आहे"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"आपल्या प्रशासकाद्वारे अद्यतनित केले"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"आपल्या प्रशासकाद्वारे हटविले आहे"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"संकीर्ण"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"आपण या सूचनांचे महत्त्व सेट केले."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"सामील असलेल्या लोकांमुळे हे महत्वाचे आहे."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" नवीन वापरकर्ता जोडण्याचा प्रयत्न करीत आहे परंतु तो सध्‍या प्रतिबंधित आहे."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" नवीन वापरकर्ता जोडण्यासाठी प्रयत्न करीत आहे परंतु वापरकर्ता मर्यादा गाठली गेली आहे."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" नवीन वापरकर्ता जोडण्‍याचा प्रयत्न करीत आहे परंतु या डिव्‍हाइसवर "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" खाते आधीपासून अस्तित्वात आहे. तरीही पुढे सुरु ठेवायचे?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" खात्यासाठी "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" नवीन वापरकर्ता जोडण्याचा प्रयत्न करीत आहे. पुढे सुरु ठेवायचे?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सह नवीन वापरकर्ता तयार करण्याची <xliff:g id="APP">%1$s</xliff:g> ला अनुमती द्यायची?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सह नवीन वापरकर्ता तयार करण्याची (हे खाते असलेला वापरकर्ता आधीपासून विद्यमान आहे) <xliff:g id="APP">%1$s</xliff:g> ला अनुमती द्यायची?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"भाषा प्राधान्य"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"प्रदेश प्राधान्य"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"भाषा नाव टाइप करा"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"सूचित केलेले"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"सर्व भाषा"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"शोध"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बंद आहे"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"कार्य प्रोफाइलला अॅप्स, पार्श्वभूमी संकालन आणि संबंधित वैशिष्ट्यांच्या समावेशासह कार्य करण्याची परवानगी द्या."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"चालू करा"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s अक्षम केले"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s प्रशासकाद्वारे अक्षम केले. अधिक जाणून घेण्‍यासाठी त्यांच्याशी संपर्क साधा."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"आपल्याकडे नवीन संदेश आहेत"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"पाहण्‍यासाठी SMS अॅप उघडा"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"काही कार्ये कदाचित उपलब्ध नसू शकतात"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"सुरू ठेवण्यासाठी स्पर्श करा"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"वापरकर्ता प्रोफाईल लॉक केले"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> शी कनेक्ट केलेले"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"फायली पाहण्यासाठी टॅप करा"</string>
+    <string name="pin_target" msgid="3052256031352291362">"पिन"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"अनपिन करा"</string>
+    <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
 </resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 3f1bb14..d88d97f 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Laporan interaktif"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Gunakan laporan ini dalam kebanyakan keadaan. Anda boleh menjejak kemajuan dan memasukkan butiran lanjut tentang masalah tersebut. Laporan ini mungkin meninggalkan beberapa bahagian yang kurang digunakan, yang mengambil masa lama untuk dilaporkan."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Laporan penuh"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Untuk gangguan sistem yang minimum, gunakan pilihan ini jika peranti tidak responsif, terlalu perlahan atau anda memerlukan semua bahagian. Tidak mengambil tangkapan skrin dan tidak boleh memasukkan butiran lanjut."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Mengambil tangkapan skrin untuk laporan pepijat dalam masa <xliff:g id="NUMBER_1">%d</xliff:g> saat.</item>
       <item quantity="one">Mengambil tangkapan skrin untuk laporan pepijat dalam masa <xliff:g id="NUMBER_0">%d</xliff:g> saat.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Kandungan tersembunyi"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Kandungan disembunyikan oleh dasar"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Peribadi"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Pilih tindakan"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Pilih apl untuk peranti USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Tiada apl yang boleh menjalankan tindakan ini."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Malangnya, <xliff:g id="APPLICATION">%1$s</xliff:g> telah berhenti."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Malangnya, proses <xliff:g id="PROCESS">%1$s</xliff:g> telah berhenti."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Senyapkan ranap daripada <xliff:g id="PROCESS">%1$s</xliff:g> sehingga but semula."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> telah berhenti"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> telah berhenti"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> asyik berhenti"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> asyik berhenti"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Mulakan semula apl"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Tetapkan semula dan mulakan semula apl"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Hantar maklum balas"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Tutup"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Redam"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Tunggu"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Tutup apl"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> tidak bertindak balas.\n\nAdakah anda mahu menutupnya?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktiviti <xliff:g id="ACTIVITY">%1$s</xliff:g> tidak bertindak balas. \n\n Adakah anda mahu menutupnya?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> tidak bertindak balas. Adakah anda mahu menutupnya?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> tidak bertindak balas. \n\nAdakah anda mahu menutupnya?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> tidak bertindak balas"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> tidak bertindak balas"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> tidak bertindak balas"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> tidak bertindak balas"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Laporkan"</string>
     <string name="wait" msgid="7147118217226317732">"Tunggu"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Kad SIM ditambah"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Mulakan semula peranti anda untuk mengakses rangkaian selular."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Mulakan semula"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Tetapkan masa"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tetapkan tarikh"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Tetapkan"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Minta PIN sebelum menyahsemat"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Minta corak buka kunci sebelum menyahsemat"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Minta kata laluan sebelum menyahsemat"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Apl tidak boleh tukar saiznya, tatal apl itu menggunakan dua jari."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Apl tidak boleh ditukar saiznya, tatal apl itu menggunakan dua jari."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Apl tidak menyokong skrin pisah."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Dipasang oleh pentadbir anda"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Dikemas kini oleh pentadbir anda"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Dipadamkan oleh pentadbir anda"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Pelbagai"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Anda menetapkan kepentingan pemberitahuan ini."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Mesej ini penting disebabkan orang yang terlibat."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" cuba menambahkan pengguna baharu tetapi dilarang pada masa ini."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" cuba menambahkan pengguna baharu tetapi had pengguna telah dicapai."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" cuba menambahkan pengguna baharu tetapi akaun "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" sudah wujud pada peranti ini. Teruskan juga?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" cuba menambahkan pengguna baharu untuk akaun "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Teruskan?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Benarkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baharu dengan <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Benarkan <xliff:g id="APP">%1$s</xliff:g> membuat Pengguna baharu dengan <xliff:g id="ACCOUNT">%2$s</xliff:g> (Pengguna dengan akaun ini sudah wujud)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Pilihan bahasa"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Pilihan wilayah"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Taipkan nama bahasa"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Dicadangkan"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Semua bahasa"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Cari"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Mod kerja DIMATIKAN"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Benarkan profil kerja berfungsi, termasuk apl, penyegerakan latar belakang dan ciri yang berkaitan."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Hidupkan"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s dilumpuhkan"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Dilumpuhkan oleh pentadbir %1$s. Hubungi mereka untuk mengetahui lebih lanjut."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Anda mempunyai mesej baharu"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Buka apl SMS untuk melihat"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Sesetengah fungsi mgkn tidak tersedia"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Ketik untuk meneruskan"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil pengguna dikunci"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Disambungkan ke <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Ketik untuk melihat fail"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Semat"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Nyahsemat"</string>
+    <string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string>
 </resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 17c1eda..ca28662 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"လက်ငင်းတုံ့ပြန်နိုင်သည့် အစီရင်ခံချက်"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"အများအားဖြင့် ၎င်းကိုအသုံးပြုပါ။ ၎င်းသည် အစီရင်ခံချက်ကို ခြေရာခံခွင့်ပေးပြီး ပြဿနာအကြောင်း အသေးစိတ်များကို ထည့်ခွင့်ပြုပါသည်။ အစီရင်ခံရန်ကြာသည့် သိပ်မသုံးသော ကဏ္ဍများကို ချန်ထားခဲ့နိုင်ပါသည်။"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"အစီရင်ခံချက်အပြည့်"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"သင့်စက်ပစ္စည်းမတုံ့ပြန်ချိန် သို့မဟုတ် အလွန်နှေးကွေးချိန်၊ သို့မဟုတ် အစီရင်ခံမှုကဏ္ဍများအားလုံး လိုအပ်သည့်အချိန်တွင် စနစ်ကြားဝင်စွတ်ဖက်မှုအနည်းဆုံး ဤရွေးချယ်မှုကိုအသုံးပြုပါ။ မျက်နှာပြင်ဓာတ်ပုံ မရိုက်ပါ သို့မဟုတ် သင့်ကိုနောက်ထပ် အသေးစိတ်များထည့်ရန် ခွင့်မပြုပါ။"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> စက္ကန့်အတွင်း ချွတ်ယွင်းချက် အစီရင်ခံရန်အတွက် မျက်နှာပြင်ဓာတ်ပုံ ရိုက်ပါမည်။</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> စက္ကန့်အတွင်း ချွတ်ယွင်းချက် အစီရင်ခံရန်အတွက် မျက်နှာပြင်ဓာတ်ပုံ ရိုက်ပါမည်။</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"၉၉၉+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"အကြောင်းအရာများ ဝှက်ထား"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"မူဝါဒမှ အကြောင်းအရာများကို ဝှက်ထားသည်"</string>
     <string name="safeMode" msgid="2788228061547930246">"အန္တရာယ်ကင်းမှု စနစ်(Safe mode)"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android စနစ်"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ကိုယ်ရေး"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"လုပ်စရာ တစ်ခု ရွေးချယ်ပါ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ကိရိယာ အတွက် app တစ်ခု ရွေးပါ"</string>
     <string name="noApplications" msgid="2991814273936504689">"ဘယ် appကမှ ဒီ လုပ်ဆောင်ချက်ကို မလုပ်ကိုင်နိုင်ပါ။"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"ဝမ်းနည်းစွာဖြင့်<xliff:g id="APPLICATION">%1$s</xliff:g>မှာ ရပ်ဆိုင်းသွားသည်။"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"ဝမ်းနည်းစွာဖြင့် လုပ်ဆောင်ချက်<xliff:g id="PROCESS">%1$s</xliff:g>မှာ ရပ်ဆိုင်းသွားသည်။"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"စက်ကို ပြန်ဖွင့်ပေးခဲ့သည့် အထိ <xliff:g id="PROCESS">%1$s</xliff:g> အသံတိတ် ပျက်စီးမှုများ"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ရပ်သွားပါပြီ"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ရပ်တန့်သွားပါပြီ"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> သည်ထပ်တလဲလဲ ရပ်တန့်နေပါသည်"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> သည်ထပ်တလဲလဲ ရပ်တန့်နေပါသည်"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"အက်ပ်ကိုပြန်လည်စတင်ပါ"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"အက်ပ်ကို ပြန်လည်ပြင်ဆင်သတ်မှတ်ပြီး ပြန်လည်စတင်ပါ"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"တုံ့ပြန်ချက်ပို့ပါ"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"ပိတ်ပါ"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"အသံတိတ်ပါ"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"စောင့်ပါ"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"အက်ပ်ကိုပိတ်ပါ"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> က မတုံ့ပြန်ပါ။ \n\n၎င်းကို သင် ပိတ်လိုပါသလား?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"လှုပ်ရှားမှု <xliff:g id="ACTIVITY">%1$s</xliff:g>က မတုံ့ပြန်ပါ။\n\n၎င်းကို သင် ပိတ်လိုပါသလား?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> က မတုံ့ပြန်ပါ။ ၎င်းကို သင် ပိတ်လိုပါသလား?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"ဖြစ်စဉ်<xliff:g id="PROCESS">%1$s</xliff:g> က မတုံ့ပြန်ပါ။ \n\n၎င်းကို သင် ပိတ် ချင်သလား?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> သည်တုံ့ပြန်မှုမရှိပါ"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> သည်တုံ့ပြန်မှုမရှိပါ"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> သည်တုံ့ပြန်မှုမရှိပါ"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> လုပ်ဆောင်ချက်သည် တုံ့ပြန်မှုမရှိပါ"</string>
     <string name="force_close" msgid="8346072094521265605">"ကောင်းပြီ"</string>
     <string name="report" msgid="4060218260984795706">"သတင်းပို့ပါ"</string>
     <string name="wait" msgid="7147118217226317732">"စောင့်ဆိုင်းရန်"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"ဆင်းမ်ကဒ် ထည့်ပါသည်"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"ဆယ်လူလာ ကွန်ရက်ကို ရယူသုံးရန် သင့် ကိရိယာကို ပြန်ဖွင့်ပေးပါ။"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"အစက ပြန်စရန်"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"သင့် SIM အသစ်ပုံမှန် အလုပ်လုပ်ရန်၊ သင်အသုံးပြုသည့် မိုဘိုင်းဝန်ဆောင်မှုမှ အက်ပ်တစ်ခုထည့်သွင်း၍ ဖွင့်ရန်လိုအပ်ပါသည်။"</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"အက်ပ်ကို ရယူပါ"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"ယခုမဟုတ်သေးပါ"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"SIM အသစ်ထည့်သွင်းလိုက်ပါသည်"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"၎င်းကိုတပ်ဆင်ရန် တို့ပါ"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"အချိန်သတ်မှတ်ရန်"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ရက်စွဲ အတည်ပြုရန်"</string>
     <string name="date_time_set" msgid="5777075614321087758">"အတည်ပြုရန်"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ပင်မဖြုတ်မီမှာ PIN ကို မေးကြည့်ရန်"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ပင်မဖြုတ်မီမှာ သော့ဖွင့် ရေးဆွဲမှုပုံစံကို မေးကြည့်ရန်"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"အက်ပ်ကို ဆိုက်ပြောင်းမရပါ၊ ၎င်းကို လက်နှစ်​ချောင်းဖြင့် ရွှေ့ယူပါ။"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"အက်ပ်ကို အရွယ်အစားချိန်၍မရပါ၊ လက်ချောင်းနှစ်ချောင်းဖြင့် အပေါ်အောက်ဆွဲပါ။"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"အက်ပ်သည် မျက်နှာပြင်ခွဲပြရန် ပံ့ပိုးထားခြင်းမရှိပါ။"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"သင့် အက်ဒမင်မှ သွင်းယူထား၏"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"သင့်စီမံခန့်ခွဲသူမှ အဆင့်မြှင့်ထားပါသည်။"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"သင့် အက်ဒမင်အား ဖျက်ပစ်ရန်"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"အထွေထွေ"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"ဤအသိပေးချက်များ၏ အရေးပါမှုကိုသင်သတ်မှတ်ပြီးပါပြီ။"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ပါဝင်သည့်လူများကြောင့် အရေးပါပါသည်။"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"က အသုံးပြုသူ အသစ်ကို ထည့်ရန် ကြိုးစားနေပါသည်၊ သို့သော် လောလောဆယ်မှာ တားမြစ်ထားပါသည်။"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"က အသုံးပြုသူ အသစ်ကို ထည့်ရန် ကြိုးစားနေပါသည်၊ သို့သော် အသုံးပြုသူ ကန့်သတ်ချက် ပြည့်မီသွားပါပြီ။"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"က အသုံးပြုသူ အသစ်ကို ထည့်ရန် ကြိုးစားနေပါသည်၊ သို့သော် အကောင့် "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>"မှာ ဤကိရိယာထဲတွင် ရှိနှင့်နေပါပြီ။ မည်သို့ပင်ဖြစ်စေ ဆက်လက်လုပ်ဆောင်ရမလား။"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"က အကောင့် "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>"အတွက် အသုံးပြုသူ အသစ်ကို ထည့်ရန် ကြိုးစားနေပါသည်။ ဆက်လက်လုပ်ဆောင်ရမလား။"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ကို <xliff:g id="ACCOUNT">%2$s</xliff:g> ဖြင့်အသုံးပြုသူအသစ်ဖန်တီးခွင့်ပြုမလား။"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> ကို <xliff:g id="ACCOUNT">%2$s</xliff:g> ဖြင့်အသုံးပြုသူအသစ် ဖန်တီးခွင့်ပြုမလား (ဤအကောင့်ဖြင့် အသုံးပြုသူ ရှိနှင့်ပြီးဖြစ်သည်)။"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"ဘာသာစကားရွေးချယ်မှု"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ဒေသရွေးချယ်မှု"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ဘာသာစကားအမည် ထည့်ပါ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"အကြံပြုထားသော"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ဘာသာစကားများအားလုံး"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"ရှာဖွေရန်"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"အလုပ်မုဒ် ပိတ်ထားသည်"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"အက်ပ်များ၊ နောက်ခံစင့်ခ်လုပ်ခြင်း၊ နှင့်သက်ဆိုင်သည့်အင်္ဂါရပ်များကို ဆောင်ရွက်ရန် အလုပ်ပရိုဖိုင်ကိုခွင့်ပြုပါ။"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ဖွင့်ပါ"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ကိုပိတ်ထားသည်"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s စီမံခန့်ခွဲသူမှ ပိတ်ထားသည်။ ပိုမိုလေ့လာရန် ၎င်းတို့ကိုဆက်သွယ်ပါ။"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"သင့်ထံတွင် စာအသစ်များရောက်နေသည်"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"ကြည့်ရှုရန် SMS အက်ပ်ကိုဖွင့်ပါ"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"အချို့လုပ်ဆောင်ချက်များ ရနိုင်သေးမည်မဟုတ်ပါ"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"ရှေ့ဆက်ရန်တို့ပါ"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"အသုံးပြုသူပရိုဖိုင် သော့ခတ်ထားသည်"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ချိတ်ဆက်ထားသည်"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ဖိုင်များကိုကြည့်ရန် တို့ပါ"</string>
+    <string name="pin_target" msgid="3052256031352291362">"တွဲပါ"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"ဖြုတ်ပါ"</string>
+    <string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 2385ad7..737743a 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv rapport"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Bruk dette alternativet i de fleste tilfeller. Da kan du spore fremgangen for rapporten samt skrive inn flere detaljer om problemet. Noen deler som tar lang tid å behandle, blir kanskje utelatt."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Fullstendig rapport"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Bruk dette alternativet for minst mulig forstyrrelser på systemet når enheten din er treg eller ikke svarer, eller når du trenger alle rapportdelene. Det tas ikke noen skjermdump, og du kan ikke legge til flere detaljer."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Tar skjermdump for feilrapporten om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder.</item>
       <item quantity="one">Tar skjermdump for feilrapporten om <xliff:g id="NUMBER_0">%d</xliff:g> sekund.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Innholdet er skjult"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Innholdet er skjult i henhold til retningslinjene"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personlig"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Velg en handling"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Velg en app for USB-enheten"</string>
     <string name="noApplications" msgid="2991814273936504689">"Ingen apper kan gjøre dette."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"<xliff:g id="APPLICATION">%1$s</xliff:g> har dessverre stoppet."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Prosessen <xliff:g id="PROCESS">%1$s</xliff:g> har dessverre stoppet."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Appen Silence kræsjer som følge av <xliff:g id="PROCESS">%1$s</xliff:g>, frem til omstart."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> har stoppet"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> har stoppet"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> stopper gjentatte ganger"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> stopper gjentatte ganger"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Start appen på nytt"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Tilbakestill appen, og start den på nytt"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Send tilbakemelding"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Lukk"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorer"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Vent"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Lukk app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> svarer ikke.\n\nVil du lukke appen?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktiviteten <xliff:g id="ACTIVITY">%1$s</xliff:g> svarer ikke.\n\nVil du lukke den?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> svarer ikke. Vil du lukke appen?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Prosessen <xliff:g id="PROCESS">%1$s</xliff:g> svarer ikke.\n\nVil du lukke den?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> svarer ikke"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> svarer ikke"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> svarer ikke"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Prossessen <xliff:g id="PROCESS">%1$s</xliff:g> svarer ikke"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Rapportér"</string>
     <string name="wait" msgid="7147118217226317732">"Vent"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-kort er lagt til"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Start enheten på nytt for å få tilgang til mobilnettverket."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Start på nytt"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"For at det nye SIM-kortet ditt skal fungere skikkelig, må du installere og åpne en app fra operatøren din."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"SKAFF DEG APPEN"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"IKKE NÅ"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Et nytt SIM-kort er satt inn"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Trykk for å konfigurere"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Stille klokken"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angi dato"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Lagre"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-kode for å løsne apper"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Krev bruk av opplåsningsmønster for å løsne apper"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Krev passord for å løsne apper"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Du kan ikke endre størrselse på appen – rull med to fingre."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Du kan ikke endre størrelse på appen – rull med to fingre."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen støtter ikke delt skjerm."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Installert av administratoren"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Oppdatert av administratoren"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Slettet av administratoren"</string>
@@ -1527,14 +1540,29 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Du angir viktigheten for disse varslene."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Dette er viktig på grunn av folkene som er involvert."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" prøver å legge til en ny bruker, men den har for øyeblikket ikke de nødvendige tillatelsene."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" prøver å legge til en ny bruker, men brukergrensen er nådd."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" prøver å legge til en ny bruker, men kontoen "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" finnes allerede på denne enheten. Vil du fortsette likevel?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" prøver å legge til en ny bruker på kontoen "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Vil du fortsette?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Vil du la <xliff:g id="APP">%1$s</xliff:g> opprette en ny bruker med <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Vil du la <xliff:g id="APP">%1$s</xliff:g> opprette en ny bruker med <xliff:g id="ACCOUNT">%2$s</xliff:g>? (Det finnes allerede en bruker med denne kontoen.)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Språkinnstilling"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regionsinnstilling"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Skriv inn språknavn"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Foreslått"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Alle språk"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Søk"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Jobbmodus er AV"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Slå på jobbprofilen, inkludert apper, synkronisering i bakgrunnen og relaterte funksjoner."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Slå på"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s er slått av"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for suspended_package_message (6341091587106868601) -->
+    <skip />
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nye meldinger"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Åpne SMS-appen for å se"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Noen funksjoner kan være utilgjengelige"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Trykk for å fortsette"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Brukerprofilen er låst"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Koblet til <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Trykk for å se filer"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fest"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Løsne"</string>
+    <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
 </resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 3e0cb29..7ea4b48 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -211,11 +211,10 @@
     <string name="global_action_bug_report" msgid="7934010578922304799">"बग रिपोर्ट"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"बग रिपोर्ट लिनुहोस्"</string>
     <string name="bugreport_message" msgid="398447048750350456">"एउटा इमेल सन्देशको रूपमा पठाउनलाई यसले तपाईँको हालैको उपकरणको अवस्थाको बारेमा सूचना जम्मा गर्ने छ। बग रिपोर्ट सुरु गरेदेखि पठाउन तयार नभएसम्म यसले केही समय लिन्छ; कृपया धैर्य गर्नुहोस्।"</string>
-    <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"पारस्परिक रिपोर्ट"</string>
-    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"यसलाई धेरै परिस्थिति भन्दा मुनि प्रयोग गर्नुहोस्। यसले तपाईंलाई रिपोर्टको प्रगति ट्र्याक गर्न र समस्या सम्बन्धी थप विवरणहरू प्रविष्ट गर्न अनुमति दिन्छ। यसले रिपोर्ट गर्न धेरै नै समय लिने केही कम प्रयोग भएका खण्डहरू मेटाउन सक्छ।"</string>
+    <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"अन्तरक्रियामूलक रिपोर्ट"</string>
+    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"यसलाई बढी भन्दा बढी परिस्थितिहरूमा प्रयोग गर्नुहोस्।यसले तपाईँलाई रिपोर्टको प्रगति ट्र्याक गर्नका साथै समस्याका बारे थप विवरणहरू प्रविष्ट गर्न अनुमति दिन्छ।यसले रिपोर्ट गर्न लामो समय लिने केही कम्ती प्रयोग हुने खण्डहरूलाई मेटाउन सक्छ।"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"पूर्ण रिपोर्ट"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"तपाईँको यन्त्र अनुत्तरदायी वा धेरै सुस्त हुँदा वा तपाईँलाई सबै रिपोर्ट खण्डहरूको आवश्यक पर्दा न्यूनतम प्रणाली हस्तक्षेपको लागि यो विकल्प प्रयोग गर्नुहोस्। स्क्रिनशट लिँदैन वा थप विवरणहरू प्रविष्ट गर्न तपाईँलाई अनुमति दिँदैन।"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other"> बग रिपोर्टको लागि <xliff:g id="NUMBER_1">%d</xliff:g> सेकेन्डमा स्क्रिनशट लिँदै।</item>
       <item quantity="one"> बग रिपोर्टको लागि <xliff:g id="NUMBER_0">%d</xliff:g> सेकेन्डमा स्क्रिनशट लिँदै।</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"९९९+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"लुकेका सामाग्रीहरू"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"नीतिद्वारा लुकाइएका सामग्री"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"एन्ड्रोइड प्रणाली"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"व्यक्तिगत"</string>
@@ -915,15 +915,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"एउटा कार्यको चयन गर्नुहोस्"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB उपकरणको लागि एउटा अनुप्रयोग छान्नुहोस्"</string>
     <string name="noApplications" msgid="2991814273936504689">"कुनै पनि अनुप्रयोगहरूले यो कार्य गर्न सक्दैनन्।"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"दुर्भाग्यवश, <xliff:g id="APPLICATION">%1$s</xliff:g> रोकिएको छ।"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"दुर्भाग्यवश, प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g> बन्द भयो।"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"साइलेन्स पुनःबुट नभएसम्म <xliff:g id="PROCESS">%1$s</xliff:g> बाट क्र्यास हुन्छ।"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> रोकिएको छ"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> रोकिएको छ"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> रोकिरहन्छ"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> रोकिरहन्छ"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"अनुप्रयोगलाई पुन: सुरु गर्नुहोस्"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"अनुप्रयोगलाई रिसेट गरी पुन: सुरु गर्नुहोस्"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"प्रतिक्रिया पठाउनुहोस्"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"बन्द गर्नुहोस्"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"म्यूट गर्नुहोस्"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"पर्खनुहोस्"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"अनुप्रयोग बन्द गर्नुहोस्"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g>ले कार्य गरिरहेको छैन।\n\nके तपाईँ यसलाई बन्द गर्न चाहनु हुन्छ?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"गतिविधि <xliff:g id="ACTIVITY">%1$s</xliff:g> ले प्रतिक्रिया देखाइरहेको छैन।\n\nके तपाईँ यसलाई बन्द गर्न चाहनु हुन्छ?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> जवाफ दिइरहेको छैन। के तपाईँ यसलाई बन्द गर्न चाहनु हुन्छ?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g>ले कार्य गरिरहेको छैन।\n\nके तपाईँ यसलाई बन्द गर्न चाहनु हुन्छ?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ले प्रतिक्रिया दिइरहेको छैन"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ले प्रतिक्रिया दिइरहेको छैन"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ले प्रतिक्रिया दिइरहेको छैन"</string>
+    <string name="anr_process" msgid="6156880875555921105">"प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g> ले प्रतिक्रिया दिइरहेको छैन"</string>
     <string name="force_close" msgid="8346072094521265605">"ठिक छ"</string>
     <string name="report" msgid="4060218260984795706">"रिपोर्ट गर्नुहोस्"</string>
     <string name="wait" msgid="7147118217226317732">"प्रतीक्षा गर्नुहोस्"</string>
@@ -1030,6 +1037,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM कार्ड थप गरियो"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"सेलुलर सञ्जाल पहुँच गर्न तपाईँको उपकरण पुनः सुरु गर्नुहोस्।"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"पुनःस्टार्ट गर्नुहोस्"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"तपाईंको नयाँ SIM ले राम्रोसँग काम गर्न, तपाईंले आफ्नो वाहक मार्फत अनुप्रयोग स्थापना र खोल्न आवश्यक हुनेछ।"</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"अनुप्रयोग प्राप्त गर्नुहोस्"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"अहिले होइन"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"नयाँ SIM घुसाइयो"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"यसलाई सेटअप गर्न ट्याप गर्नुहोस्"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"समय मिलाउनुहोस्"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"मिति मिलाउनुहोस्"</string>
     <string name="date_time_set" msgid="5777075614321087758">"सेट गर्नुहोस्"</string>
@@ -1461,7 +1473,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"पिन निकाल्नुअघि PIN सोध्नुहोस्"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"पिन निकाल्नुअघि खोल्ने रूपरेखा सोध्नुहोस्"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"अनुप्रयोगको आकार सानो-ठुलो बनाउन मिल्दैन, दुई औँलाले यसलाई स्क्रोल गर्नुहोस्।"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"अनुप्रयोगको आकार सानो-ठूलो बनाउन मिल्दैन, दुई औँलाले यसलाई स्क्रोल गर्नुहोस्।"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"अनुप्रयोगले विभाजित-स्क्रिनलाई समर्थन गर्दैन।"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"तपाईँको प्रशासकद्वारा स्थापना गरिएको"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"तपाईँको प्रशासकद्वारा अद्यावधिक गरिएको"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"तपाईँको प्रशासकद्वारा हटाइएको"</string>
@@ -1533,14 +1546,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"विविध"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"तपाईंले यी सूचनाहरूको महत्त्व सेट गर्नुहुन्छ।"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"यसमा सङ्लग्न भएका मानिसहरूको कारणले गर्दा यो महत्वपूर्ण छ।"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ले नयाँ प्रयोगकर्ता थप्ने प्रयास गरिरहेको छ तर हाललाई निषेधित छ।"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ले नयाँ प्रयोगकर्ता थप्ने प्रयास गरिरहेको छ तर प्रयोगकर्ताको सीमा पुगेको छ।"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ले नयाँ प्रयोगकर्ता थप्ने प्रयास गरिरहेको छ तर यो यन्त्रमा खाता "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" पहिले नै अवस्थित छ। जे भए पनि अगाडि बढ्ने हो?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ले खाता "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" मा नयाँ प्रयोगकर्ता थप्ने प्रयास गरिरहेको छ। अगाडि बढ्ने हो?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सँगै नयाँ प्रयोगकर्ता सिर्जना गर्न <xliff:g id="APP">%1$s</xliff:g> लाई अनुमति दिने हो?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> सँगै नयाँ प्रयोगकर्ता सिर्जना गर्न <xliff:g id="APP">%1$s</xliff:g> लाई अनुमति दिने (यस खाताको प्रयोगकर्ता पहिले नै अवस्थित छ) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"भाषाको प्राथमिकता"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"क्षेत्रको प्राथमिकता"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"भाषाको नाम टाइप गर्नुहोस्"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"सुझाव दिइयो"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"सम्पूर्ण भाषाहरू"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"खोज"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बन्द छ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"अनुप्रयोग, पृष्ठभूमि सिंक र सम्बन्धित विशेषताहरू सहित, कार्य प्रोफाइललाई कार्य गर्न अनुमति दिनुहोस्।"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"सक्रिय गर्नुहोस्"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s असक्षम भयो"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s प्रशासकद्वारा असक्षम गरिएको। थप जान्नका लागि तिनीहरूलाई सम्पर्क गर्नुहोस्।"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"तपाईंलाई नयाँ सन्देश आएको छ"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"हेर्नका लागि SMS अनुप्रयोग खोल्नुहोस्"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"केही कार्यहरू उपलब्ध नहुन सक्छन्"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"जारी राख्नका लागि छुनुहोस्"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"प्रयोगकर्ता प्रोफाइल लक भयो"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> मा जडान गरिएको छ"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"फाइलहरू हेर्न ट्याप गर्नुहोस्"</string>
+    <string name="pin_target" msgid="3052256031352291362">"पिन गर्नुहोस्"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"अनपिन गर्नुहोस्"</string>
+    <string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index d0a333b..750b716 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactief rapport"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Gebruik deze optie in de meeste situaties. Hiermee kun je de voortgang van het rapport bijhouden en meer gegevens over het probleem opgeven. Mogelijk worden bepaalde minder vaak gebruikte gedeelten weggelaten (waarvoor het lang zou duren om een rapport te genereren)."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Volledig rapport"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Gebruik deze optie voor minimale systeemverstoring wanneer je apparaat niet reageert of te langzaam is, of wanneer je alle rapportgedeelten nodig hebt. Er wordt geen screenshot gemaakt en je kunt geen extra gegevens opgeven."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Er wordt over <xliff:g id="NUMBER_1">%d</xliff:g> seconden een screenshot gemaakt voor het bugrapport.</item>
       <item quantity="one">Er wordt over <xliff:g id="NUMBER_0">%d</xliff:g> seconde een screenshot gemaakt voor het bugrapport.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Inhoud verborgen"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Content verborgen op basis van beleid"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Persoonlijk"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Een actie selecteren"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Een app voor het USB-apparaat selecteren"</string>
     <string name="noApplications" msgid="2991814273936504689">"Geen enkele app kan deze actie uitvoeren."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"<xliff:g id="APPLICATION">%1$s</xliff:g> is gestopt."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Het proces <xliff:g id="PROCESS">%1$s</xliff:g> is gestopt."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Crashes van <xliff:g id="PROCESS">%1$s</xliff:g> negeren tot opnieuw opstarten."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> is gestopt"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> is gestopt"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> stopt steeds"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> stopt steeds"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"App opnieuw starten"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"App resetten en opnieuw starten"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Feedback verzenden"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Sluiten"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Negeren"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Wachten"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"App sluiten"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> reageert niet.\n\nWilt u deze app sluiten?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Activiteit <xliff:g id="ACTIVITY">%1$s</xliff:g> reageert niet.\n\nWilt u deze activiteit sluiten?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> reageert niet. Wilt u deze app sluiten?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> reageert niet.\n\nWilt u het sluiten?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> reageert niet"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> reageert niet"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> reageert niet"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> reageert niet"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Melden"</string>
     <string name="wait" msgid="7147118217226317732">"Wachten"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Simkaart aangesloten"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Start je apparaat opnieuw voor toegang tot het mobiele netwerk."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Opnieuw starten"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Je moet een app van je provider installeren en openen om te zorgen dat je nieuwe simkaart correct werkt."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"DE APP DOWNLOADEN"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NIET NU"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Nieuwe simkaart geplaatst"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Tik om dit in te stellen"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Tijd instellen"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum instellen"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Instellen"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Vraag pin voor losmaken"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Vraag patroon voor losmaken"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vraag wachtwoord voor losmaken"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Formaat van app kan niet worden aangepast, scroll met twee vingers."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Formaat van app kan niet worden aangepast, scrol met twee vingers."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"App biedt geen ondersteuning voor gesplitst scherm."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Geïnstalleerd door je beheerder"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Geüpdatet door je beheerder"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Verwijderd door je beheerder"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diversen"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Je stelt het belang van deze meldingen in."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Dit is belangrijk vanwege de betrokken mensen."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" probeert een nieuwe gebruiker toe te voegen, maar dit is momenteel niet toegestaan."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" probeert een nieuwe gebruiker toe te voegen, maar de gebruikerslimiet is al bereikt."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" probeert een nieuwe gebruiker toe te voegen, maar het account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" bestaat al op dit apparaat. Toch doorgaan?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" probeert een nieuwe gebruiker toe te voegen voor het account "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Doorgaan?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Toestaan dat <xliff:g id="APP">%1$s</xliff:g> een nieuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> maakt?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Toestaan dat <xliff:g id="APP">%1$s</xliff:g> een nieuwe gebruiker met <xliff:g id="ACCOUNT">%2$s</xliff:g> maakt (er is al een gebruiker met dit account)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Taalvoorkeur"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regiovoorkeur"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Typ een taalnaam"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Voorgesteld"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Alle talen"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Zoeken"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Werkmodus is UIT"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Functioneren van werkprofiel toestaan, waaronder apps, synchronisatie op de achtergrond en gerelateerde functies."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Inschakelen"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s is uitgeschakeld"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Uitgeschakeld door de beheerder van %1$s. Neem voor meer informatie contact op met de beheerder."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Je hebt nieuwe berichten"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Open je sms-app om ze te bekijken"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Sommige functies zijn mogelijk niet beschikbaar"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Tik om door te gaan"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Gebruikersprofiel vergrendeld"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Verbonden met <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Tik om bestanden te bekijken"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Vastzetten"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Losmaken"</string>
+    <string name="app_info" msgid="6856026610594615344">"App-info"</string>
 </resources>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 7e762b0..05f0ce2 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ਅੰਤਰਕਿਰਿਆਤਮਕ ਰਿਪੋਰਟ"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"ਜ਼ਿਆਦਾਤਰ ਹਾਲਾਤਾਂ ਵਿੱਚ ਇਸ ਦੀ ਵਰਤੋਂ ਕਰੋ। ਇਹ ਤੁਹਾਨੂੰ ਰਿਪੋਰਟ ਦੀ ਪ੍ਰਗਤੀ ਨੂੰ ਟਰੈਕ ਕਰਨ ਦਿੰਦਾ ਹੈ ਅਤੇ ਸਮੱਸਿਆ ਬਾਰੇ ਹੋਰ ਵੇਰਵੇ ਦਾਖਲ ਕਰਨ ਦਿੰਦਾ ਹੈ। ਇਹ ਉਹਨਾਂ ਘੱਟ-ਵਰਤੇ ਗਏ ਕੁਝ ਭਾਗਾਂ ਨੂੰ ਨਜ਼ਰ-ਅੰਦਾਜ਼ ਕਰ ਸਕਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਦੀ ਰਿਪੋਰਟ ਕਰਨ ਵਿੱਚ ਵੱਧ ਸਮਾਂ ਲੱਗ ਸਕਦਾ ਹੈ।"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"ਪੂਰੀ ਰਿਪੋਰਟ"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"ਜਦੋਂ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਪ੍ਰਤਿਕਿਰਿਆ ਨਾ ਕਰ ਰਹੀ ਹੋਵੇ ਜਾਂ ਬਹੁਤ ਹੀ ਹੌਲੀ ਹੋਵੇ, ਜਾਂ ਜਦੋਂ ਤੁਹਾਨੂੰ ਸਾਰੇ ਰਿਪੋਰਟ ਭਾਗਾਂ ਦੀ ਲੋੜ ਹੋਵੇ ਤਾਂ ਇਸ ਚੋਣ ਦੀ ਵਰਤੋਂ ਘੱਟ-ਤੋਂ-ਘੱਟ ਸਿਸਟਮ ਦਖ਼ਲ ਲਈ ਕਰੋ। ਸਕ੍ਰੀਨਸ਼ਾਟ ਨਹੀਂ ਲੈਣ ਦਿੰਦਾ ਹੈ ਜਾਂ ਤੁਹਾਨੂੰ ਹੋਰ ਵੇਰਵੇ ਦਾਖਲ ਨਹੀਂ ਕਰਨ ਦਿੰਦਾ ਹੈ।"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">ਬੱਗ ਰਿਪੋਰਟ ਲਈ <xliff:g id="NUMBER_1">%d</xliff:g> ਸਕਿੰਟ ਵਿੱਚ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਿਆ ਜਾ ਰਿਹਾ ਹੈ।</item>
       <item quantity="other">ਬੱਗ ਰਿਪੋਰਟ ਲਈ <xliff:g id="NUMBER_1">%d</xliff:g> ਸਕਿੰਟ ਵਿੱਚ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਿਆ ਜਾ ਰਿਹਾ ਹੈ।</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"ਸਮੱਗਰੀਆਂ ਲੁਕਾਈਆਂ ਗਈਆਂ"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ਨੀਤੀ ਦੁਆਰਾ ਸਮੱਗਰੀ ਲੁਕਾਈ ਗਈ"</string>
     <string name="safeMode" msgid="2788228061547930246">"ਸੁਰੱਖਿਅਤ ਮੋਡ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ਨਿੱਜੀ"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"ਇੱਕ ਕਿਰਿਆ ਚੁਣੋ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ਡਿਵਾਈਸ ਲਈ ਇੱਕ ਐਪ ਚੁਣੋ"</string>
     <string name="noApplications" msgid="2991814273936504689">"ਕੋਈ ਐਪਸ ਇਸ ਕਿਰਿਆ ਨੂੰ ਨਹੀਂ ਕਰ ਸਕਦੇ।"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"ਅਫ਼਼ਸੋਸ ਨਾਲ, <xliff:g id="APPLICATION">%1$s</xliff:g> ਰੁਕ ਗਈ ਹੈ।"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"ਅਫ਼਼ਸੋਸ ਨਾਲ, ਪ੍ਰਕਿਰਿਆ <xliff:g id="PROCESS">%1$s</xliff:g> ਰੁਕ ਗਈ ਹੈ।"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"ਜਦੋਂ ਤੱਕ ਰੀਬੂਟ ਨਹੀਂ ਹੁੰਦਾ ਤਾਂ <xliff:g id="PROCESS">%1$s</xliff:g> ਤੋਂ ਸਾਈਲੈਂਸ ਕ੍ਰੈਸ਼।"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ਰੁਕ ਗਈ ਹੈ"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ਰੁਕ ਗਿਆ ਹੈ"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ਵਾਰ-ਵਾਰ ਰੁਕ ਰਹੀ ਹੈ"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> ਵਾਰ-ਵਾਰ ਰੁਕ ਰਹੀ ਹੈ"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"ਐਪ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"ਐਪ ਨੂੰ ਰੀਸੈੱਟ ਅਤੇ ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"ਪ੍ਰਤੀਕਰਮ ਭੇਜੋ"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"ਬੰਦ ਕਰੋ"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"ਮਿਊਟ ਕਰੋ"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"ਉਡੀਕ ਕਰੋ"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"ਐਪ ਬੰਦ ਕਰੋ"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਿਹਾ ਹੈ।\n\nਕੀ ਤੁਸੀਂ ਇਸਨੂੰ ਬੰਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"ਗਤੀਵਿਧੀ <xliff:g id="ACTIVITY">%1$s</xliff:g> ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਹੀ ਹੈ।\n\nਕੀ ਤੁਸੀਂ ਇਸਨੂੰ ਬੰਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਿਹਾ ਹੈ। ਕੀ ਤੁਸੀਂ ਇਸਨੂੰ ਬੰਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"ਪ੍ਰਕਿਰਿਆ <xliff:g id="PROCESS">%1$s</xliff:g> ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਹੀ ਹੈ।\n\nਕੀ ਤੁਸੀਂ ਇਸਨੂੰ ਬੰਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ਪ੍ਰਤਿਕਿਰਿਆ ਨਹੀਂ ਦੇ ਰਹੀ ਹੈ"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ਪ੍ਰਤਿਕਿਰਿਆ ਨਹੀਂ ਦੇ ਰਹੀ ਹੈ"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ਪ੍ਰਤਿਕਿਰਿਆ ਨਹੀਂ ਦੇ ਰਹੀ ਹੈ"</string>
+    <string name="anr_process" msgid="6156880875555921105">"ਪ੍ਰਕਿਰਿਆ <xliff:g id="PROCESS">%1$s</xliff:g> ਪ੍ਰਤਿਕਿਰਿਆ ਨਹੀਂ ਦੇ ਰਹੀ ਹੈ"</string>
     <string name="force_close" msgid="8346072094521265605">"ਠੀਕ"</string>
     <string name="report" msgid="4060218260984795706">"ਰਿਪੋਰਟ ਕਰੋ"</string>
     <string name="wait" msgid="7147118217226317732">"ਉਡੀਕ ਕਰੋ"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM ਕਾਰਡ ਜੋੜਿਆ ਗਿਆ"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"ਸੈਲਿਊਲਰ ਨੈਟਵਰਕ ਤੱਕ ਪਹੁੰਚ ਲਈ ਆਪਣੀ ਡਿਵਾਈਸ ਰੀਸਟਾਰਟ ਕਰੋ।"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"ਰੀਸਟਾਰਟ ਕਰੋ"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"ਤੁਹਾਡੀ ਨਵੀਂ SIM ਦੇ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਤੋਂ ਇੱਕ ਐਪ ਸਥਾਪਤ ਕਰਨ ਅਤੇ ਖੋਲ੍ਹਣ ਦੀ ਲੋੜ ਪਵੇਗੀ।"</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ਐਪ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"ਹੁਣੇ ਨਹੀਂ"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"ਨਵੀਂ SIM ਦਾਖਲ ਕੀਤੀ ਗਈ"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"ਇਸ ਨੂੰ ਸੈੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ਸਮਾਂ ਸੈਟ ਕਰੋ"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ਤਾਰੀਖ ਸੈਟ ਕਰੋ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"ਸੈਟ ਕਰੋ"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ PIN ਮੰਗੋ"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪੈਟਰਨ ਅਨਲੌਕ ਕਰਨ ਲਈ ਪੁੱਛੋ"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ਐਪ ਮੁੜ-ਆਕਾਰ ਦੇਣਯੋਗ ਨਹੀਂ ਹੈ, ਇਸ ਨੂੰ ਦੋ ਉਂਗਲਾਂ ਨਾਲ ਸਕਰੋਲ ਕਰੋ।"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ਐਪ ਦਾ ਆਕਾਰ ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ, ਇਸ ਨੂੰ ਦੋ ਉਂਗਲਾਂ ਨਾਲ ਸਕਰੋਲ ਕਰੋ।"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ।"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ਤੁਹਾਡੇ ਪ੍ਰਬੰਧਕ ਵੱਲੋਂ ਇੰਸਟੌਲ ਕੀਤਾ ਗਿਆ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ਤੁਹਾਡੇ ਪ੍ਰਬੰਧਕ ਵੱਲੋਂ ਮਿਟਾਇਆ ਗਿਆ"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"ਵਿਵਿਧ"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"ਤੁਸੀਂ ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਦੀ ਮਹੱਤਤਾ ਸੈੱਟ ਕੀਤੀ।"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ਇਹ ਸ਼ਾਮਲ ਲੋਕਾਂ ਦੇ ਕਾਰਨ ਮਹੱਤਵਪੂਰਨ ਹੈ।"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ਇੱਕ ਨਵੇਂ ਵਰਤੋਂਕਾਰ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੈ, ਪਰ ਇਸ \'ਤੇ ਮੌਜੂਦਾ ਤੌਰ \'ਤੇ ਪਾਬੰਦੀ ਲਗਾਈ ਗਈ ਹੈ।"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ਇੱਕ ਨਵੇਂ ਵਰਤੋਂਕਾਰ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੈ, ਪਰ ਵਰਤੋਂਕਾਰ ਮਿਆਦ ਪੂਰੀ ਹੋ ਚੁੱਕੀ ਹੈ।"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ਇੱਕ ਨਵੇਂ ਵਰਤੋਂਕਾਰ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੈ, ਪਰ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ਖਾਤਾ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਮੌਜੂਦ ਹੈ। ਕੀ ਫਿਰ ਵੀ ਅੱਗੇ ਵੱਧਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ਖਾਤੇ ਵਿੱਚ ਇੱਕ ਨਵੇਂ ਵਰਤੋਂਕਾਰ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੈ। ਕੀ ਅੱਗੇ ਵੱਧਣਾ ਹੈ?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"ਕੀ <xliff:g id="APP">%1$s</xliff:g> ਨੂੰ <xliff:g id="ACCOUNT">%2$s</xliff:g> ਨਾਲ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਉਣ ਦੀ ਮਨਜ਼ੂਰੀ ਦੇਣੀ ਹੈ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"ਕੀ <xliff:g id="APP">%1$s</xliff:g> ਨੂੰ <xliff:g id="ACCOUNT">%2$s</xliff:g> ਨਾਲ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਉਣ ਦੀ ਮਨਜ਼ੂਰੀ ਦੇਣੀ ਹੈ (ਇਸ ਖਾਤੇ ਨਾਲ ਇੱਕ ਵਰਤੋਂਕਾਰ ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਮੌਜੂਦ ਹੈ) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"ਭਾਸ਼ਾ ਤਰਜੀਹ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ਖੇਤਰ ਤਰਜੀਹ"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"ਭਾਸ਼ਾ ਨਾਮ ਟਾਈਪ ਕਰੋ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"ਸੁਝਾਈਆਂ ਗਈਆਂ"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"ਖੋਜ"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"ਕੰਮ ਮੋਡ ਬੰਦ ਹੈ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"ਐਪਾਂ, ਬੈਕਗ੍ਰਾਊਂਡ ਸਮਕਾਲੀਕਰਨ, ਅਤੇ ਸਬੰਧਿਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋਏ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਕੰਮ ਕਰਨ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ।"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ਚਾਲੂ ਕਰੋ"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ। ਹੋਰ ਜਾਣਨ ਲਈ ਉਹਨਾਂ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"ਤੁਹਾਨੂੰ ਨਵੇਂ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਹੋਏ ਹਨ"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"ਵੇਖਣ ਲਈ SMS ਐਪ ਖੋਲ੍ਹੋ"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"ਹੋ ਸਕਦਾ ਹੈ ਕੁਝ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਉਪਲਬਧ ਨਾ ਹੋਣ"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਸਪਰਸ਼ ਕਰੋ"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"ਵਰਤੋਂਕਾਰ ਪ੍ਰੋਫਾਈਲ ਲੌਕ ਕੀਤੀ ਗਈ"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋਈ"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ਫ਼ਾਈਲਾਂ ਵੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
+    <string name="pin_target" msgid="3052256031352291362">"ਪਿੰਨ ਕਰੋ"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"ਅਨਪਿੰਨ ਕਰੋ"</string>
+    <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 8f475d5..7e320a6 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -216,8 +216,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Raport interaktywny"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Używaj tej opcji w większości przypadków. Umożliwia śledzenie postępów raportu i podanie dodatkowych szczegółów problemu. Raport może pomijać niektóre rzadko używane sekcje, których utworzenie zajmuje dużo czasu."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Pełny raport"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Użyj tej opcji, jeśli chcesz zminimalizować zakłócenia pracy systemu, gdy urządzenie nie reaguje, działa wolno lub gdy potrzebujesz wszystkich sekcji raportu. Nie jest wykonywany zrzutu ekranu i nie można podać więcej szczegółów."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="few">Zrzut ekranu do raportu o błędzie zostanie zrobiony za <xliff:g id="NUMBER_1">%d</xliff:g> sekundy.</item>
       <item quantity="many">Zrzut ekranu do raportu o błędzie zostanie zrobiony za <xliff:g id="NUMBER_1">%d</xliff:g> sekund.</item>
@@ -237,6 +236,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Treści ukryte"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Treść ukryta z powodu zasad"</string>
     <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
     <string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osobiste"</string>
@@ -921,15 +921,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Wybierz czynność"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Wybierz aplikację dla urządzenia USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Żadna z aplikacji nie może wykonać tej czynności."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Niestety, aplikacja <xliff:g id="APPLICATION">%1$s</xliff:g> została zatrzymana."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Niestety, proces <xliff:g id="PROCESS">%1$s</xliff:g> został zatrzymany."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Ignoruj awarie aplikacji <xliff:g id="PROCESS">%1$s</xliff:g> do czasu zrestartowania."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Aplikacja <xliff:g id="APPLICATION">%1$s</xliff:g> przestała działać"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> przestał działać"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> wciąż przestaje działać"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> wciąż przestaje działać"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Uruchom aplikację ponownie"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Zresetuj aplikację i uruchom ją ponownie"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Prześlij opinię"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Zamknij"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignoruj"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Zaczekaj"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Zamknij aplikację"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Aplikacja <xliff:g id="APPLICATION">%2$s</xliff:g> nie reaguje.\n\nCzy chcesz ją zamknąć?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Działanie <xliff:g id="ACTIVITY">%1$s</xliff:g> nie odpowiada.\n\nCzy chcesz je zakończyć?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Aplikacja <xliff:g id="APPLICATION">%1$s</xliff:g> nie reaguje. Czy chcesz ją zamknąć?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> nie odpowiada.\n\nCzy chcesz go zakończyć?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> nie odpowiada"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"Działanie <xliff:g id="ACTIVITY">%1$s</xliff:g> nie odpowiada"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> nie odpowiada"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> nie odpowiada"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Zgłoś"</string>
     <string name="wait" msgid="7147118217226317732">"Czekaj"</string>
@@ -1040,6 +1047,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Dodano kartę SIM"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Uruchom urządzenie ponownie, by uzyskać dostęp do sieci komórkowej."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Uruchom ponownie"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Aby nowa karta SIM działała prawidłowo, musisz zainstalować i otworzyć aplikację udostępnioną przez operatora."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"POBIERZ APLIKACJĘ"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NIE TERAZ"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Włożono nową kartę SIM"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Kliknij, by skonfigurować"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ustaw godzinę"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ustaw datę"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ustaw"</string>
@@ -1475,7 +1487,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Podaj PIN, aby odpiąć"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Aby odpiąć, poproś o wzór odblokowania"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Aby odpiąć, poproś o hasło"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Rozmiaru tej aplikacji nie można zmienić. Przewiń ją dwoma palcami."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Rozmiaru tej aplikacji nie można zmienić. Przewiń ją dwoma palcami."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacja nie obsługuje dzielonego ekranu."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Zainstalowany przez administratora"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Zaktualizowane przez administratora"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Usunięty przez administratora"</string>
@@ -1565,14 +1578,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Inne"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Ustawiłeś ważność tych powiadomień."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Ta wiadomość jest ważna ze względu na osoby uczestniczące w wątku."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"Aplikacja "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" próbuje dodać nowego użytkownika, ale jest obecnie zabroniona."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"Aplikacja "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" próbuje dodać nowego użytkownika, ale osiągnięto już limit użytkowników."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"Aplikacja "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" próbuje dodać nowego użytkownika, ale na tym urządzeniu istnieje już konto "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Kontynuować mimo to?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392">"Aplikacja "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" próbuje dodać nowego użytkownika do konta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Kontynuować?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Zezwalasz aplikacji <xliff:g id="APP">%1$s</xliff:g> na utworzenie nowego użytkownika dla konta <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Zezwalasz aplikacji <xliff:g id="APP">%1$s</xliff:g> na utworzenie nowego użytkownika dla konta <xliff:g id="ACCOUNT">%2$s</xliff:g>)? Użytkownik z tym kontem już istnieje."</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Ustawienie języka"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Ustawienie regionu"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Wpisz nazwę języka"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugerowane"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Wszystkie języki"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Szukaj"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Tryb pracy jest WYŁĄCZONY"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Włącz profil do pracy, w tym aplikacje, synchronizację w tle i inne funkcje."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Włącz"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Wyłączono pakiet %1$s"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Wyłączone przez administratora organizacji %1$s. Skontaktuj się z nim, by dowiedzieć się więcej."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Masz nowe wiadomości"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Otwórz aplikację do SMS-ów, by wyświetlić wiadomość"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Niektóre funkcje mogą być niedostępne"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Kliknij, by kontynuować"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil użytkownika zablokowany"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Połączono z: <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Dotknij, by wyświetlić pliki"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Przypnij"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Odepnij"</string>
+    <string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 60d4860..1e3a887 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Relatório interativo"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Use este recurso na maioria das circunstâncias. Ele permite que você acompanhe o progresso do relatório e informe mais detalhes sobre o problema. É possível que ele omita algumas seções menos utilizadas que levam muito tempo na emissão dos relatórios."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Use esta opção para ter o mínimo de interferência do sistema quando seu dispositivo não estiver respondendo ou estiver muito lento, ou quando você precisar de todas as seções de relatórios. Ela não faz uma captura de tela ou permite que você informe mais detalhes."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
       <item quantity="other">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Conteúdo oculto"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pessoal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Escolher uma ação"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Selecione um app para o dispositivo USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Nenhum app pode realizar esta ação."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"O <xliff:g id="APPLICATION">%1$s</xliff:g> parou."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> parou."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silenciar falhas de <xliff:g id="PROCESS">%1$s</xliff:g> até a reinicialização."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> parou"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> parou"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> apresenta falhas continuamente"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> apresenta falhas continuamente"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Reiniciar app"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Redefinir e reiniciar app"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Enviar feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Fechar"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorar"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Aguarde"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Fechar app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> não está respondendo.\n\nDeseja fechá-lo?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"A atividade <xliff:g id="ACTIVITY">%1$s</xliff:g> não está respondendo.\n\nDeseja fechá-la?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> não está respondendo. Deseja encerrar o app?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> não está respondendo.\n\nDeseja fechá-lo?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> não está respondendo"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> não está respondendo"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> não está respondendo"</string>
+    <string name="anr_process" msgid="6156880875555921105">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> não está respondendo"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Informar"</string>
     <string name="wait" msgid="7147118217226317732">"Aguardar"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Cartão SIM adicionado"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Reinicie o dispositivo para acessar a rede celular."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Para que seu novo SIM funcione corretamente, instale e abra um app da sua operadora."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"FAZER O DOWNLOAD DO APP"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"AGORA NÃO"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Novo SIM inserido"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Toque para configurar"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Definir"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"O app não é redimensionável. Desloque-o com dois dedos."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"O app não é redimensionável. Desloque-o com dois dedos."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"O app não é compatível com a divisão de tela."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo seu administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Excluído pelo seu administrador"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diversos"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Você definiu a importância dessas notificações."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Isso é importante por causa das pessoas envolvidas."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando adicionar um novo usuário, mas isso não é permitido no momento."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando adicionar um novo usuário, mas o limite de usuários foi atingido."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando adicionar um novo usuário, mas a conta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" já existe neste dispositivo. Continuar mesmo assim?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando adicionar um novo usuário à conta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Continuar?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g> (já existe um usuário com essa conta)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferência de idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferência de região"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Digitar nome do idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Pesquisa"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Permitir que o perfil de trabalho funcione, incluindo apps, sincronização em segundo plano e recursos relacionados"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s desativado"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Desativado pelo administrador de %1$s. Entre em contato com ele para saber mais."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Você tem mensagens novas"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Abra o app de SMS para ver"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Algumas funções podem não estar disponíveis."</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Toque para continuar"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Perfil do usuário bloqueado"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Toque para ver os arquivos"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fixar guia"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e58e693..2855e9b 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Relatório interativo"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Utilize esta opção na maioria das circunstâncias. Permite monitorizar o progresso do relatório e introduzir mais detalhes acerca do problema. Pode omitir algumas secções menos utilizadas que demoram muito tempo a comunicar."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Utilize esta opção para uma interferência mínima do sistema quando o dispositivo não responder ou estiver demasiado lento, ou quando precisar de todas as secções de relatório. Não tira uma captura de ecrã, nem permite introduzir mais detalhes."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
       <item quantity="one">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_0">%d</xliff:g> segundo.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Conteúdo oculto"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pessoal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Escolha uma ação"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Escolher uma aplicação para o dispositivo USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Nenhuma aplicação pode efetuar esta ação."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Lamentamos, o <xliff:g id="APPLICATION">%1$s</xliff:g> foi interrompido."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Lamentamos, o processo <xliff:g id="PROCESS">%1$s</xliff:g> foi interrompido."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silenciar falhas de <xliff:g id="PROCESS">%1$s</xliff:g> até reiniciar."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> sofreu uma falha de sistema."</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> sofreu uma falha de sistema."</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> continua a parar"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> continua a parar"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Reiniciar aplicação"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Repor e reiniciar aplicação"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Enviar comentários"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Fechar"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorar"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Aguardar"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Fechar aplicação"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> não está a responder. \n\nPretende fechá-la?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"A atividade <xliff:g id="ACTIVITY">%1$s</xliff:g> não está a responder. \n\n Pretende fechá-la?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> não está a responder. Pretende fechá-la?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> não está a responder. \n\n Pretende fechá-lo?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> não está a responder"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> não está a responder"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> não está a responder"</string>
+    <string name="anr_process" msgid="6156880875555921105">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> não está a responder"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Relatório"</string>
     <string name="wait" msgid="7147118217226317732">"Esperar"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Cartão SIM adicionado"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Reinicie o dispositivo para aceder à rede móvel."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Para que o novo SIM funcione corretamente, tem de instalar e abrir uma aplicação do seu operador."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"OBTER A APLICAÇÃO"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"AGORA NÃO"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Novo SIM inserido"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Toque para configurar"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Definir"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de soltar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir sequência de desbloqueio antes de soltar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir palavra-passe antes de soltar"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"A aplicação não é redimensionável. Desloque-a com dois dedos."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"A aplicação não é redimensionável. Desloque-a com dois dedos."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"A aplicação não é compatível com o ecrã dividido."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado pelo administrador"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diversos"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Definiu a importância destas notificações."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"É importante devido às pessoas envolvidas."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está a tentar adicionar um novo utilizador, mas está atualmente proibido(a)."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está a tentar adicionar um novo utilizador, mas foi atingido o limite de utilizadores."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está a tentar adicionar um novo utilizador, mas a conta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" já existe neste dispositivo. Pretende continuar mesmo assim?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está a tentar adicionar um novo utilizador à conta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Pretende continuar?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Pretende permitir que o <xliff:g id="APP">%1$s</xliff:g> crie um novo utilizador com <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Pretende permitir que o <xliff:g id="APP">%1$s</xliff:g> crie um novo utilizador com <xliff:g id="ACCOUNT">%2$s</xliff:g> (já existe um utilizador com esta conta)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferência de idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferência de região"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Intr. nome do idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Pesquisa"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Permitir o funcionamento do perfil de trabalho, incluindo as aplicações, a sincronização em segundo plano e as funcionalidades relacionadas."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s desativado"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Desativado pelo administrador de %1$s. Contacte-o para saber mais."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Tem mensagens novas"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Abra a aplicação de SMS para ver"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Algumas funções podem não estar disp."</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Toque para continuar"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Perfil de utilizador bloqueado"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Ligado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Tocar para ver ficheiros"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fixar"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 60d4860..1e3a887 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Relatório interativo"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Use este recurso na maioria das circunstâncias. Ele permite que você acompanhe o progresso do relatório e informe mais detalhes sobre o problema. É possível que ele omita algumas seções menos utilizadas que levam muito tempo na emissão dos relatórios."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Use esta opção para ter o mínimo de interferência do sistema quando seu dispositivo não estiver respondendo ou estiver muito lento, ou quando você precisar de todas as seções de relatórios. Ela não faz uma captura de tela ou permite que você informe mais detalhes."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
       <item quantity="other">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Conteúdo oculto"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conteúdo ocultado pela política"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pessoal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Escolher uma ação"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Selecione um app para o dispositivo USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Nenhum app pode realizar esta ação."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"O <xliff:g id="APPLICATION">%1$s</xliff:g> parou."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> parou."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silenciar falhas de <xliff:g id="PROCESS">%1$s</xliff:g> até a reinicialização."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> parou"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> parou"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> apresenta falhas continuamente"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> apresenta falhas continuamente"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Reiniciar app"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Redefinir e reiniciar app"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Enviar feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Fechar"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorar"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Aguarde"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Fechar app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> não está respondendo.\n\nDeseja fechá-lo?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"A atividade <xliff:g id="ACTIVITY">%1$s</xliff:g> não está respondendo.\n\nDeseja fechá-la?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> não está respondendo. Deseja encerrar o app?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> não está respondendo.\n\nDeseja fechá-lo?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> não está respondendo"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> não está respondendo"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> não está respondendo"</string>
+    <string name="anr_process" msgid="6156880875555921105">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> não está respondendo"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Informar"</string>
     <string name="wait" msgid="7147118217226317732">"Aguardar"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Cartão SIM adicionado"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Reinicie o dispositivo para acessar a rede celular."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Para que seu novo SIM funcione corretamente, instale e abra um app da sua operadora."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"FAZER O DOWNLOAD DO APP"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"AGORA NÃO"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Novo SIM inserido"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Toque para configurar"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Definir"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"O app não é redimensionável. Desloque-o com dois dedos."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"O app não é redimensionável. Desloque-o com dois dedos."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"O app não é compatível com a divisão de tela."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalado pelo seu administrador"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Excluído pelo seu administrador"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diversos"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Você definiu a importância dessas notificações."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Isso é importante por causa das pessoas envolvidas."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando adicionar um novo usuário, mas isso não é permitido no momento."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando adicionar um novo usuário, mas o limite de usuários foi atingido."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando adicionar um novo usuário, mas a conta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" já existe neste dispositivo. Continuar mesmo assim?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" está tentando adicionar um novo usuário à conta "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Continuar?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Permitir que <xliff:g id="APP">%1$s</xliff:g> crie um novo usuário com <xliff:g id="ACCOUNT">%2$s</xliff:g> (já existe um usuário com essa conta)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferência de idioma"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferência de região"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Digitar nome do idioma"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Pesquisa"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Permitir que o perfil de trabalho funcione, incluindo apps, sincronização em segundo plano e recursos relacionados"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s desativado"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Desativado pelo administrador de %1$s. Entre em contato com ele para saber mais."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Você tem mensagens novas"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Abra o app de SMS para ver"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Algumas funções podem não estar disponíveis."</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Toque para continuar"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Perfil do usuário bloqueado"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Conectado a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Toque para ver os arquivos"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fixar guia"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 4db1209..9ad5a5a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -49,7 +49,7 @@
     <string name="serviceEnabled" msgid="8147278346414714315">"Serviciul a fost activat."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Serviciul a fost activat pentru:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Serviciul a fost dezactivat."</string>
-    <string name="serviceRegistered" msgid="6275019082598102493">"Înregistrarea a reuşit."</string>
+    <string name="serviceRegistered" msgid="6275019082598102493">"Înregistrarea a reușit."</string>
     <string name="serviceErased" msgid="1288584695297200972">"Ștergerea a reușit."</string>
     <string name="passwordIncorrect" msgid="7612208839450128715">"Parolă incorectă."</string>
     <string name="mmiComplete" msgid="8232527495411698359">"MMI finalizat."</string>
@@ -79,7 +79,7 @@
     <string name="PinMmi" msgid="3113117780361190304">"Cod PIN modificat"</string>
     <string name="CnipMmi" msgid="3110534680557857162">"Se apelează numărul prezent"</string>
     <string name="CnirMmi" msgid="3062102121430548731">"Se apelează un număr restricţionat"</string>
-    <string name="ThreeWCMmi" msgid="9051047170321190368">"Apelare de tip conferinţă"</string>
+    <string name="ThreeWCMmi" msgid="9051047170321190368">"Apelare de tip conferință"</string>
     <string name="RuacMmi" msgid="7827887459138308886">"Respingere apeluri supărătoare nedorite"</string>
     <string name="CndMmi" msgid="3116446237081575808">"Se apelează serviciul de furnizare a numerelor"</string>
     <string name="DndMmi" msgid="1265478932418334331">"Nu deranjaţi"</string>
@@ -88,7 +88,7 @@
     <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"ID-ul apelantului este nerestricționat în mod prestabilit. Apelul următor: Restricționat."</string>
     <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID-ul apelantului este nerestricționat în mod prestabilit. Apelul următor: nerestricționat"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"Nu se asigură accesul la acest serviciu."</string>
-    <string name="CLIRPermanent" msgid="3377371145926835671">"Nu puteți să modificaţi setarea pentru ID-ul apelantului."</string>
+    <string name="CLIRPermanent" msgid="3377371145926835671">"Nu puteți să modificați setarea pentru ID-ul apelantului."</string>
     <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Acces restricționat modificat"</string>
     <string name="RestrictedOnData" msgid="8653794784690065540">"Serviciul de date este blocat."</string>
     <string name="RestrictedOnEmergency" msgid="6581163779072833665">"Serviciul de urgență este blocat."</string>
@@ -138,8 +138,8 @@
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecționată"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> după <xliff:g id="TIME_DELAY">{2}</xliff:g> (de) secunde"</string>
-    <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecţionat"</string>
-    <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecţionat"</string>
+    <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecționat"</string>
+    <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecționat"</string>
     <string name="fcComplete" msgid="3118848230966886575">"Cod de funcție complet."</string>
     <string name="fcError" msgid="3327560126588500777">"Problemă de conectare sau cod de funcție nevalid."</string>
     <string name="httpErrorOk" msgid="1191919378083472204">"OK"</string>
@@ -147,7 +147,7 @@
     <string name="httpErrorLookup" msgid="4711687456111963163">"Nu s-a putut găsi adresa URL."</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"Schema de autentificare a site-ului nu este acceptată."</string>
     <string name="httpErrorAuth" msgid="1435065629438044534">"Nu s-a realizat autentificarea."</string>
-    <string name="httpErrorProxyAuth" msgid="1788207010559081331">"Autentificarea prin intermediul serverului proxy nu a reuşit."</string>
+    <string name="httpErrorProxyAuth" msgid="1788207010559081331">"Autentificarea prin intermediul serverului proxy nu a reușit."</string>
     <string name="httpErrorConnect" msgid="8714273236364640549">"Nu s-a putut stabili conexiunea cu serverul."</string>
     <string name="httpErrorIO" msgid="2340558197489302188">"Nu s-a putut efectua comunicarea cu serverul. Încercați din nou mai târziu."</string>
     <string name="httpErrorTimeout" msgid="4743403703762883954">"Conexiunea la server a expirat."</string>
@@ -162,10 +162,10 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Sincronizare"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizare"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Prea multe ştergeri <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
-    <string name="low_memory" product="tablet" msgid="6494019234102154896">"Stocarea pe tabletă este plină. Ștergeți câteva fișiere pentru a elibera spaţiu."</string>
+    <string name="low_memory" product="tablet" msgid="6494019234102154896">"Stocarea pe tabletă este plină. Ștergeți câteva fișiere pentru a elibera spațiu."</string>
     <string name="low_memory" product="watch" msgid="4415914910770005166">"Spațiul de stocare de pe ceas este plin! Ștergeți câteva fișiere pentru a elibera spațiu."</string>
     <string name="low_memory" product="tv" msgid="516619861191025923">"Spațiul de stocare al televizorului este plin. Ștergeți câteva fișiere pentru a elibera spațiu."</string>
-    <string name="low_memory" product="default" msgid="3475999286680000541">"Stocarea pe telefon este plină. Ștergeți câteva fișiere pentru a elibera spaţiu."</string>
+    <string name="low_memory" product="default" msgid="3475999286680000541">"Stocarea pe telefon este plină. Ștergeți câteva fișiere pentru a elibera spațiu."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Rețeaua poate fi monitorizată"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"De o terță parte necunoscută"</string>
     <string name="ssl_ca_cert_noti_by_administrator" msgid="550758088185764312">"De administratorul profilului de serviciu"</string>
@@ -199,7 +199,7 @@
     <string name="shutdown_confirm" product="tv" msgid="476672373995075359">"Televizorul se va închide."</string>
     <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ceasul dvs. se va închide."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonul dvs. se va închide."</string>
-    <string name="shutdown_confirm_question" msgid="2906544768881136183">"Doriți să închideţi?"</string>
+    <string name="shutdown_confirm_question" msgid="2906544768881136183">"Doriți să închideți?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reporniţi în modul sigur"</string>
     <string name="reboot_safemode_confirm" msgid="55293944502784668">"Doriți să reporniţi în modul sigur? Astfel vor fi dezactivate toate aplicațiile terţă parte pe care le-ați instalat. Acestea vor fi restabilite când reporniţi din nou."</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
@@ -215,8 +215,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Raport interactiv"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Folosiți această opțiune în majoritatea situațiilor. Astfel, puteți să urmăriți progresul raportului și să introduceți mai multe detalii în privința problemei. Pot fi omise unele secțiuni mai puțin folosite pentru care raportarea durează prea mult."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Raport complet"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Folosiți această opțiune pentru a reduce la minimum interferențele cu sistemul când dispozitivul nu răspunde, funcționează prea lent sau când aveți nevoie de toate secțiunile raportului. Nu se creează o captură de ecran și nu se pot introduce detalii suplimentare."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="few">Peste <xliff:g id="NUMBER_1">%d</xliff:g> secunde se va realiza o captură de ecran pentru raportul de eroare.</item>
       <item quantity="other">Peste <xliff:g id="NUMBER_1">%d</xliff:g> de secunde se va realiza o captură de ecran pentru raportul de eroare.</item>
@@ -235,6 +234,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Conținutul este ascuns"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Conținutul este ascuns conform politicii"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -290,7 +290,7 @@
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"citire feeduri abonat"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Permite aplicației să obţină detalii despre feedurile sincronizate în prezent."</string>
     <string name="permlab_sendSms" msgid="7544599214260982981">"trimită și să vadă mesajele SMS"</string>
-    <string name="permdesc_sendSms" msgid="7094729298204937667">"Permite aplicației să trimită mesaje SMS, ceea ce ar putea determina apariția unor taxe neaşteptate. Aplicaţiile rău intenţionate pot acumula costuri prin trimiterea mesajelor fără confirmarea dvs."</string>
+    <string name="permdesc_sendSms" msgid="7094729298204937667">"Permite aplicației să trimită mesaje SMS, ceea ce ar putea determina apariția unor taxe neașteptate. Aplicaţiile rău intenţionate pot acumula costuri prin trimiterea mesajelor fără confirmarea dvs."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"citeşte mesajele text (SMS sau MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Permite aplicației să citească mesajele SMS stocate pe tabletă sau pe cardul SIM. În acest fel, aplicația poate citi toate mesajele SMS, indiferent de conţinutul sau de gradul de confidenţialitate al acestora."</string>
     <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"Permite aplicației să citească mesajele SMS stocate pe televizor sau pe cardul SIM. Cu această permisiune, aplicația poate citi toate mesajele SMS, indiferent de conținutul sau de gradul de confidențialitate al acestora."</string>
@@ -313,7 +313,7 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Permite aplicației să declare persistente în memorie anumite părți ale sale. Acest lucru poate limita memoria disponibilă pentru alte aplicații și poate încetini funcționarea tabletei."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Permite aplicației să declare persistente în memorie anumite părți ale sale. Acest lucru poate limita memoria disponibilă pentru alte aplicații și poate încetini funcționarea televizorului."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Permite aplicației să declare persistente în memorie anumite părți ale sale. Acest lucru poate limita memoria disponibilă pentru alte aplicații și poate încetini funcționarea telefonului."</string>
-    <string name="permlab_getPackageSize" msgid="7472921768357981986">"măsurare spaţiu de stocare al aplicației"</string>
+    <string name="permlab_getPackageSize" msgid="7472921768357981986">"măsurare spațiu de stocare al aplicației"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Permite aplicației să preia dimensiunile codului, ale datelor și ale memoriei cache"</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"modifică setări de sistem"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"Permite aplicației să modifice datele din setările sistemului. Aplicaţiile rău intenţionate pot corupe configuraţia sistemului dvs."</string>
@@ -326,13 +326,13 @@
     <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcții poate să încetinească sau să destabilizeze televizorul, determinându-l să utilizeze prea multă memorie."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Permite aplicației să trimită mesaje difuzate persistente, care se păstrează după terminarea difuzării mesajului. Utilizarea excesivă a acestei funcții poate să încetinească sau să destabilizeze telefonul, determinându-l să utilizeze prea multă memorie."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"citeşte agenda"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Permite aplicației să citească datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvența cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenţionate pot distribui datele de contact fără știrea dvs."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Permite aplicației să citească datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenţionate pot distribui datele de contact fără știrea dvs."</string>
     <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Permite aplicației să citească datele despre persoanele de contact salvate pe televizor, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune, aplicațiile pot salva datele de contact, iar aplicațiile rău-intenționate pot permite accesul la datele de contact fără cunoștința dvs."</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permite aplicației să citească datele despre persoanele din agenda stocată pe telefon, inclusiv frecvența cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenţionate pot distribui datele de contact fără știrea dvs."</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Permite aplicației să citească datele despre persoanele din agenda stocată pe telefon, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane. Cu această permisiune aplicația salvează datele dvs. de contact, iar aplicațiile rău intenţionate pot distribui datele de contact fără știrea dvs."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"modifică agenda"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvența cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe tabletă, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
     <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Permite aplicației să modifice datele despre persoanele de contact salvate pe televizor, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane de contact. Cu această permisiune, aplicația poate șterge datele de contact."</string>
-    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe telefon, inclusiv frecvența cu care aţi apelat, aţi trimis e-mailuri sau aţi comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
+    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Permite aplicației să modifice datele despre persoanele din agenda stocată pe telefon, inclusiv frecvența cu care ați apelat, ați trimis e-mailuri sau ați comunicat în alte moduri cu anumite persoane din agendă. Cu această permisiune aplicația poate șterge datele de contact."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"citeşte jurnalul de apeluri"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Permite aplicației să citească jurnalul de apeluri al tabletei, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune aplicația salvează datele dvs. din jurnalul de apeluri, iar aplicațiile rău intenţionate pot distribui aceste date fără știrea dvs."</string>
     <string name="permdesc_readCallLog" product="tv" msgid="5611770887047387926">"Permite aplicației să citească jurnalul de apeluri al televizorului, inclusiv datele despre apelurile primite și efectuate. Cu această permisiune, aplicațiile pot să salveze datele din jurnalul de apeluri, iar aplicațiile rău-intenționate pot permite accesul la datele din jurnalul de apeluri fără cunoștința dvs."</string>
@@ -368,7 +368,7 @@
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlează vibrarea"</string>
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Permite aplicației să controleze mecanismul de vibrare."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"apelare directă numere de telefon"</string>
-    <string name="permdesc_callPhone" msgid="3740797576113760827">"Permite aplicației să apeleze numere de telefon fără intervenţia dvs. Acest lucru poate determina apariția unor taxe sau a unor apeluri neaşteptate. Cu această permisiune aplicația nu poate apela numerele de urgenţă. Aplicaţiile rău intenţionate pot acumula costuri prin efectuarea unor apeluri fără confirmare."</string>
+    <string name="permdesc_callPhone" msgid="3740797576113760827">"Permite aplicației să apeleze numere de telefon fără intervenţia dvs. Acest lucru poate determina apariția unor taxe sau a unor apeluri neașteptate. Cu această permisiune aplicația nu poate apela numerele de urgenţă. Aplicaţiile rău intenţionate pot acumula costuri prin efectuarea unor apeluri fără confirmare."</string>
     <string name="permlab_accessImsCallService" msgid="3574943847181793918">"accesează serviciul de apelare IMS"</string>
     <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Permite aplicației să folosească serviciul IMS pentru apeluri, fără intervenția dvs."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"citeşte starea și identitatea telefonului"</string>
@@ -391,7 +391,7 @@
     <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"Permite aplicației să schimbe fusul orar al tabletei."</string>
     <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"Permite aplicației să modifice fusul orar al televizorului."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Permite aplicației să schimbe fusul orar al telefonului."</string>
-    <string name="permlab_getAccounts" msgid="1086795467760122114">"găseşte conturi pe dispozitiv"</string>
+    <string name="permlab_getAccounts" msgid="1086795467760122114">"găsește conturi pe dispozitiv"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Permite aplicației să obţină lista de conturi cunoscute de tabletă. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat."</string>
     <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Permite aplicației să obțină lista de conturi cunoscute de televizor. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Permite aplicației să obţină lista de conturi cunoscute de telefon. Aceasta poate include conturile create de aplicațiile pe care le-ați instalat."</string>
@@ -417,7 +417,7 @@
     <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permite aplicației să configureze telefonul Bluetooth local, să descopere și să se împerecheze cu dispozitive la distanță."</string>
     <string name="permlab_accessWimaxState" msgid="4195907010610205703">"se conectează și se deconectează de la WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permite aplicației să stabilească dacă o rețea WiMAX este activată și să vadă informațiile cu privire la toate reţelele WiMAX conectate."</string>
-    <string name="permlab_changeWimaxState" msgid="340465839241528618">"schimbaţi starea WiMAX"</string>
+    <string name="permlab_changeWimaxState" msgid="340465839241528618">"schimbați starea WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite aplicației să conecteze și să deconecteze tableta la și de la reţelele WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"Permite aplicației să conecteze și să deconecteze televizorul la și de la rețelele WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite aplicației să conecteze și să deconecteze telefonul la și de la reţelele WiMAX."</string>
@@ -482,7 +482,7 @@
     <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Permite aplicației să citească utilizarea statistică a rețelei pentru anumite rețele și aplicații."</string>
     <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"gestionează politica de rețea"</string>
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite aplicației să gestioneze politicile de rețea și să definească regulile specifice aplicațiilor."</string>
-    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificaţi modul de calcul al utilizării rețelei"</string>
+    <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificați modul de calcul al utilizării rețelei"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite aplicației să modifice modul în care este calculată utilizarea rețelei pentru aplicații. Nu se utilizează de aplicațiile obişnuite."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"accesare notificări"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite aplicației să recupereze, să examineze și să șteargă notificări, inclusiv pe cele postate de alte aplicații."</string>
@@ -663,12 +663,12 @@
     <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Introduceţi parola pentru a debloca"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Introduceţi codul PIN pentru a debloca"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Cod PIN incorect."</string>
-    <string name="keyguard_label_text" msgid="861796461028298424">"Pentru a debloca, apăsaţi Meniu, apoi 0."</string>
+    <string name="keyguard_label_text" msgid="861796461028298424">"Pentru a debloca, apăsați Meniu, apoi 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Număr de urgență"</string>
     <string name="lockscreen_carrier_default" msgid="6169005837238288522">"Fără semnal"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Ecranul este blocat."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Apăsați Meniu pentru a debloca sau pentru a efectua apeluri de urgență."</string>
-    <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Apăsaţi Meniu pentru deblocare."</string>
+    <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Apăsați Meniu pentru deblocare."</string>
     <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Desenaţi modelul pentru a debloca"</string>
     <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Urgență"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Reveniţi la apel"</string>
@@ -700,9 +700,9 @@
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> (de) secunde."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Aţi introdus incorect parola de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> (de) secunde."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Aţi introdus incorect codul PIN de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori.\n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> (de) secunde."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi tableta cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați tableta cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați televizorul cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi telefonul cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați telefonul cu ajutorul datelor de conectare la Google.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Aţi efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a tabletei. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, aceasta va fi resetată la setările prestabilite din fabrică, iar toate datele de utilizator vor fi pierdute."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a televizorului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, televizorul va reveni la setările prestabilite din fabrică, iar toate datele de utilizator se vor pierde."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Aţi efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, acesta va fi resetat la setările prestabilite din fabrică, iar toate datele de utilizator vor fi pierdute."</string>
@@ -757,7 +757,7 @@
     <string name="granularity_label_word" msgid="7075570328374918660">"cuvânt"</string>
     <string name="granularity_label_link" msgid="5815508880782488267">"link"</string>
     <string name="granularity_label_line" msgid="5764267235026120888">"rând"</string>
-    <string name="factorytest_failed" msgid="5410270329114212041">"Testarea de fabrică nu a reuşit"</string>
+    <string name="factorytest_failed" msgid="5410270329114212041">"Testarea de fabrică nu a reușit"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Acţiunea FACTORY_TEST este acceptată doar pentru pachetele instalate în /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nu s-a găsit niciun pachet care să ofere acțiunea FACTORY_TEST."</string>
     <string name="factorytest_reboot" msgid="6320168203050791643">"Reporniți"</string>
@@ -799,7 +799,7 @@
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite aplicației să adauge mesaje în Mesaje primite în mesageria vocală."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificare permisiuni pentru locația geografică a browserului"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite aplicației să modifice permisiunile privind locația geografică a browserului. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a permite trimiterea informaţiilor privind locația către site-uri web arbitrare."</string>
-    <string name="save_password_message" msgid="767344687139195790">"Doriți ca browserul să reţină această parolă?"</string>
+    <string name="save_password_message" msgid="767344687139195790">"Doriți ca browserul să rețină această parolă?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Nu acum"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Reţineţi"</string>
     <string name="save_password_never" msgid="8274330296785855105">"Niciodată"</string>
@@ -915,19 +915,26 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Alegeți o acţiune"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Alegeți o aplicație pentru dispozitivul USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Această acţiune nu poate fi efectuată de nicio aplicație."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Din păcate, <xliff:g id="APPLICATION">%1$s</xliff:g> s-a oprit."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Din păcate, procesul <xliff:g id="PROCESS">%1$s</xliff:g> s-a oprit."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Nu mai afișa blocările aplicației <xliff:g id="PROCESS">%1$s</xliff:g> până la repornire."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> s-a oprit"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> s-a oprit"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> se oprește încontinuu"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> se oprește încontinuu"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Reporniți aplicația"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Resetați și reporniți aplicația"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Trimiteți feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Închideți"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Dezactivați"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Așteptați"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Închideți aplicația"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Aplicaţia <xliff:g id="APPLICATION">%2$s</xliff:g> nu răspunde.\n\nDoriți să o închideţi?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Activitatea <xliff:g id="ACTIVITY">%1$s</xliff:g> nu răspunde.\n\nDoriți să o închideţi?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Aplicaţia <xliff:g id="APPLICATION">%1$s</xliff:g> nu răspunde. Doriți să o închideţi?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Procesul <xliff:g id="PROCESS">%1$s</xliff:g> nu răspunde.\n\nDoriți să îl închideţi?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> nu răspunde"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nu răspunde"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> nu răspunde"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Procesul <xliff:g id="PROCESS">%1$s</xliff:g> nu răspunde"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
-    <string name="report" msgid="4060218260984795706">"Raportaţi"</string>
+    <string name="report" msgid="4060218260984795706">"Raportați"</string>
     <string name="wait" msgid="7147118217226317732">"Aşteptaţi"</string>
-    <string name="webpage_unresponsive" msgid="3272758351138122503">"Pagina a devenit inactivă.\n\nDoriți să o închideţi?"</string>
+    <string name="webpage_unresponsive" msgid="3272758351138122503">"Pagina a devenit inactivă.\n\nDoriți să o închideți?"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"Aplicaţie redirecţionată"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> funcţionează acum."</string>
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> a fost lansată iniţial."</string>
@@ -1022,7 +1029,7 @@
     <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Acest lucru va genera costuri în contul dvs. mobil."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Trimiteți"</string>
     <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Anulați"</string>
-    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Doresc să se reţină opțiunea"</string>
+    <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Doresc să se rețină opțiunea"</string>
     <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Puteți modifica ulterior în Setări &gt; Aplicații"</string>
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permiteți întotdeauna"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nu permiteți niciodată"</string>
@@ -1032,6 +1039,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Card SIM adăugat"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Reporniți dispozitivul pentru a accesa rețeaua mobilă."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reporniţi"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Pentru ca noul SIM să funcționeze corect, va trebui să instalați și să deschideți o aplicație de la operatorul dvs."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"DESCĂRCAȚI APLICAȚIA"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"NU ACUM"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"S-a introdus un card SIM nou"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Atingeți pentru a-l configura"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Setaţi ora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setaţi data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Setați"</string>
@@ -1155,7 +1167,7 @@
     <string name="next_button_label" msgid="1080555104677992408">"Înainte"</string>
     <string name="skip_button_label" msgid="1275362299471631819">"Omiteţi"</string>
     <string name="no_matches" msgid="8129421908915840737">"Nicio potrivire"</string>
-    <string name="find_on_page" msgid="1946799233822820384">"Găsiţi pe pagină"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Găsiți pe pagină"</string>
     <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
       <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> din <xliff:g id="TOTAL">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> din <xliff:g id="TOTAL">%d</xliff:g></item>
@@ -1164,8 +1176,8 @@
     <string name="action_mode_done" msgid="7217581640461922289">"Terminat"</string>
     <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Se șterge stocarea USB..."</string>
     <string name="progress_erasing" product="default" msgid="6596988875507043042">"Se șterge cardul SD..."</string>
-    <string name="share" msgid="1778686618230011964">"Distribuiţi"</string>
-    <string name="find" msgid="4808270900322985960">"Găsiţi"</string>
+    <string name="share" msgid="1778686618230011964">"Distribuiți"</string>
+    <string name="find" msgid="4808270900322985960">"Găsiți"</string>
     <string name="websearch" msgid="4337157977400211589">"Căutare pe web"</string>
     <string name="find_next" msgid="5742124618942193978">"Următorul rezultat"</string>
     <string name="find_previous" msgid="2196723669388360506">"Rezultatul anterior"</string>
@@ -1175,7 +1187,7 @@
     <string name="gpsVerifYes" msgid="2346566072867213563">"Da"</string>
     <string name="gpsVerifNo" msgid="1146564937346454865">"Nu"</string>
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"Limita pentru ştergere a fost depăşită"</string>
-    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Există <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> (de) elemente şterse pentru <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, contul <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Ce doriți să faceţi?"</string>
+    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Există <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> (de) elemente şterse pentru <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, contul <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Ce doriți să faceți?"</string>
     <string name="sync_really_delete" msgid="2572600103122596243">"Ștergeți elementele"</string>
     <string name="sync_undo_deletes" msgid="2941317360600338602">"Anulați aceste ştergeri"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"Nu trebuie să luați nicio măsură deocamdată"</string>
@@ -1228,7 +1240,7 @@
     <string name="storage_usb" msgid="3017954059538517278">"Dsipozitiv de stocare USB"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editați"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"Avertisment de utiliz. a datelor"</string>
-    <string name="data_usage_warning_body" msgid="2814673551471969954">"Atingeți pt. a afişa utiliz./set."</string>
+    <string name="data_usage_warning_body" msgid="2814673551471969954">"Atingeți pt. a afișa utiliz./set."</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Ați atins limita de date 2G-3G"</string>
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Ați atins limita de date 4G"</string>
     <string name="data_usage_mobile_limit_title" msgid="557158376602636112">"Ați atins limita de date mobile"</string>
@@ -1255,11 +1267,11 @@
     <string name="fingerprints" msgid="4516019619850763049">"Amprente:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"Amprentă SHA-256:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"Amprentă SHA-1:"</string>
-    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Afişaţi-le pe toate"</string>
+    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Afișați-le pe toate"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Alegeți activitatea"</string>
-    <string name="share_action_provider_share_with" msgid="5247684435979149216">"Distribuiţi pentru"</string>
+    <string name="share_action_provider_share_with" msgid="5247684435979149216">"Distribuiți pentru"</string>
     <string name="sending" msgid="3245653681008218030">"Se trimite..."</string>
-    <string name="launchBrowserDefault" msgid="2057951947297614725">"Lansaţi browserul?"</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Lansați browserul?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Acceptați apelul?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Întotdeauna"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Numai o dată"</string>
@@ -1291,7 +1303,7 @@
     <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", securizat"</string>
     <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Model uitat"</string>
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Model greşit"</string>
-    <string name="kg_wrong_password" msgid="2333281762128113157">"Parolă greşită"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Parolă greșită"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Cod PIN greşit"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Încercați din nou peste <xliff:g id="NUMBER">%1$d</xliff:g> (de) secunde."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Desenaţi modelul"</string>
@@ -1324,13 +1336,13 @@
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Aţi efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Tableta va fi acum resetată la setările prestabilite din fabrică."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a televizorului. Televizorul va reveni acum la setările prestabilite din fabrică."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Aţi efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Telefonul va fi acum resetat la setările prestabilite din fabrică."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați televizorul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Eliminaţi"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Ridicați volumul mai sus de nivelul recomandat?\n\nAscultarea la volum ridicat pe perioade lungi de timp vă poate afecta auzul."</string>
-    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Menţineţi două degete pe ecran pentru a activa accesibilitatea."</string>
+    <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Mențineți două degete pe ecran pentru a activa accesibilitatea."</string>
     <string name="accessibility_enabled" msgid="1381972048564547685">"S-a activat accesibilitatea."</string>
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Accesibilitatea a fost anulată"</string>
     <string name="user_switched" msgid="3768006783166984410">"Utilizator curent: <xliff:g id="NAME">%1$s</xliff:g>."</string>
@@ -1465,7 +1477,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Solicită codul PIN înainte de a anula fixarea"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Solicită modelul pentru deblocare înainte de a anula fixarea"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicită parola înainte de a anula fixarea"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Aplicația nu poate fi redimensionată. Derulați în ea cu două degete."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Aplicația nu poate fi redimensionată. Derulați în ea cu două degete."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplicația nu acceptă ecranul împărțit."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Instalat de administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizat de un administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Șters de administrator"</string>
@@ -1546,14 +1559,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Dvs. setați importanța acestor notificări."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Notificarea este importantă având în vedere persoanele implicate."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" încearcă să adauge un nou utilizator, dar momentan nu îi este permis."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" încearcă să adauge un nou utilizator, dar a fost atinsă limita de utilizatori."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" încearcă să adauge un nou utilizator, dar contul "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" există deja pe acest dispozitiv. Continuați oricum?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" încearcă să adauge un nou utilizator pentru contul "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Continuați?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Permiteți ca <xliff:g id="APP">%1$s</xliff:g> să creeze un nou utilizator folosind <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Permiteți ca <xliff:g id="APP">%1$s</xliff:g> să creeze un nou utilizator folosind <xliff:g id="ACCOUNT">%2$s</xliff:g>? (există deja un utilizator cu acest cont)"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Limba preferată"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regiunea preferată"</string>
-    <string name="search_language_hint" msgid="7042102592055108574">"Scrieți nume limbă"</string>
+    <string name="search_language_hint" msgid="7042102592055108574">"Numele limbii"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugerate"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Toate limbile"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Căutați"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Modul de serviciu e DEZACTIVAT"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Permiteți profilului de serviciu să funcționeze, inclusiv aplicațiile, sincronizarea în fundal și funcțiile asociate."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Activați"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Dezactivat de %1$s"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Dezactivat de administratorul companiei %1$s. Contactați-l pentru a afla mai multe."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Aveți mesaje noi"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Deschideți aplicația pentru SMS-uri ca să vizualizați"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Este posibil ca unele funcții să nu fie disponibile"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Atingeți pentru a continua"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil utilizator: blocat"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Conectat la <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Atingeți pentru a vedea fișierele"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fixați"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Anulați fixarea"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 1185422..bdbeb54 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -214,10 +214,9 @@
     <string name="bugreport_title" msgid="2667494803742548533">"Отчет об ошибке"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Информация о текущем состоянии вашего устройства будет собрана и отправлена по электронной почте. Подготовка отчета займет некоторое время."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактивный отчет"</string>
-    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Рекомендуем пользоваться этой функцией, чтобы отслеживать статус отчета и указывать дополнительные данные о проблеме. Показываются только основные разделы (чтобы отправка отчета об ошибке занимала меньше времени)."</string>
+    <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Рекомендуем пользоваться этой функцией, чтобы отслеживать статус отчета и указывать дополнительные данные о проблеме. Некоторые разделы могут быть исключены, чтобы сократить время подготовки отчета."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Подробный отчет"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Выберите этот вариант, если устройство не реагирует на ваши действия или работает слишком медленно, а также если вы хотите включить все разделы. Вы не сможете сделать скриншот или указать дополнительные сведения."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Скриншот будет сделан через <xliff:g id="NUMBER_1">%d</xliff:g> секунду</item>
       <item quantity="few">Скриншот будет сделан через <xliff:g id="NUMBER_1">%d</xliff:g> секунды</item>
@@ -237,6 +236,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Содержимое скрыто"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Содержимое скрыто в соответствии с заданными правилами"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Личные данные"</string>
@@ -921,15 +921,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Выберите действие"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Выбор приложения для USB-устройства"</string>
     <string name="noApplications" msgid="2991814273936504689">"Действие не поддерживается ни в одном приложении."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"В приложении \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" произошла ошибка."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"В приложении \"<xliff:g id="PROCESS">%1$s</xliff:g>\" произошла ошибка."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"В режиме полной тишины происходят сбои при запуске приложения \"<xliff:g id="PROCESS">%1$s</xliff:g>\". Они прекращаются после перезагрузки."</string>
+    <string name="aerr_application" msgid="250320989337856518">"В работе приложения \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" произошел сбой"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Во время процесса \"<xliff:g id="PROCESS">%1$s</xliff:g>\" произошел сбой"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"В приложении \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" снова произошел сбой"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"В приложении \"<xliff:g id="PROCESS">%1$s</xliff:g>\" снова произошел сбой"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Перезапустить приложение"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Сбросить и перезапустить"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Отправить отзыв"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Закрыть"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Скрыть"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Подождать"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Закрыть приложение"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Приложение \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" не отвечает.\n\nЗакрыть его?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Приложение \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\" не отвечает.\n\nЗакрыть его?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" не отвечает. Закрыть его?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Приложение \"<xliff:g id="PROCESS">%1$s</xliff:g>\" не отвечает.\n\nЗакрыть его?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"Приложение \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" не отвечает"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"Приложение \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\" не отвечает"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"Приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" не отвечает"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Приложение \"<xliff:g id="PROCESS">%1$s</xliff:g> не отвечает"</string>
     <string name="force_close" msgid="8346072094521265605">"ОК"</string>
     <string name="report" msgid="4060218260984795706">"Отправить отчет"</string>
     <string name="wait" msgid="7147118217226317732">"Подождать"</string>
@@ -1040,6 +1047,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-карта добавлена"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Перезагрузите устройство, чтобы подключиться к мобильной сети."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Перезапуск"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Настройка времени"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Настройка даты"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Установить"</string>
@@ -1475,7 +1492,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-код для отключения"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запрашивать графический ключ для отключения блокировки"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запрашивать пароль для отключения блокировки"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Размер окна нельзя изменить. Прокрутите страницу двумя пальцами."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Размер окна нельзя изменить. Прокрутите страницу двумя пальцами."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Приложение не поддерживает разделение экрана."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Установлено администратором"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Обновлено администратором"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Удалено администратором"</string>
@@ -1565,14 +1583,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Другое"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Вы определяете важность этих уведомлений."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Важное (люди)"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"Приложение "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" хочет добавить пользователя, однако в настоящее время это действие запрещено."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"Приложение "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" хочет добавить пользователя, однако лимит уже достигнут."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"Приложение "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" хочет добавить пользователя, однако аккаунт "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" уже есть на этом устройстве. Продолжить?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392">"Приложение "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" хочет добавить пользователя для аккаунта "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Продолжить?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Разрешить приложению \"<xliff:g id="APP">%1$s</xliff:g>\" создать пользователя для аккаунта <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Разрешить приложению \"<xliff:g id="APP">%1$s</xliff:g>\" создать нового пользователя для аккаунта <xliff:g id="ACCOUNT">%2$s</xliff:g> (пользователь c таким аккаунтом уже есть)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Языковые настройки"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Региональные настройки"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Введите язык"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Рекомендуемые"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Все языки"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Поиск"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Рабочий режим отключен"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Включить рабочий профиль: приложения, фоновую синхронизацию и связанные функции."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Включить"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Пакет \"%1$s\" заблокирован"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Пакет заблокирован администратором компании \"%1$s\". Обратитесь к нему за дополнительной информацией."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Новые сообщения"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Чтобы просмотреть, откройте приложение для обмена SMS"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Некоторые функции недоступны"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Нажмите, чтобы продолжить"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Профиль заблокирован"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Подключено к <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Нажмите, чтобы просмотреть файлы"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Закрепить"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Открепить"</string>
+    <string name="app_info" msgid="6856026610594615344">"О приложении"</string>
 </resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 2cbf5ad..9bbab56 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"අන්තර්ක්‍රියා වාර්."</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"බොහොමයක් වාතාවරණ යටතේ මෙය භාවිත කරන්න. එය ඔබට වාර්තාවේ ප්‍රගතිය හඹා යාමට සහ ගැටලුව පිළිබඳ වැඩිපුර විස්තර ඇතුළත් කිරීමට ඉඩ දෙයි. එය වාර්තා කිරීමට දිගු වේලාවක් ගන්නා සමහර අඩුවෙන්-භාවිත වන කොටස් මග හැරීමට හැකිය."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"සම්පූර්ණ වාර්තාව"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"ඔබේ උපාංගය ප්‍රතිචාර නොදක්වන විට හෝ ඉතා මන්දගාමි විට, හෝ ඔබට සියලු වාර්තා කොටස් අවශ්‍ය විට අවම පද්ධති බාධාව සඳහා මෙම විකල්පය භාවිත කරන්න. තිර රුවක් ගැනීමට හෝ ඔබට වැඩි විස්තර ඇතුළත් කිරීමට ඉඩ නොදේ."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">තත්පර <xliff:g id="NUMBER_1">%d</xliff:g>කින් දෝෂ වාර්තාව සඳහා තිර රුවක් ලබා ගනිමින්</item>
       <item quantity="other">තත්පර <xliff:g id="NUMBER_1">%d</xliff:g>කින් දෝෂ වාර්තාව සඳහා තිර රුවක් ලබා ගනිමින්</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"සැඟවුණු සම්බන්ධතා"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"ප්‍රතිපත්තිය විසින් අන්තර්ගතය සඟවන ලදී"</string>
     <string name="safeMode" msgid="2788228061547930246">"ආරක්‍ෂිත ආකාරය"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android පද්ධතිය"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"පෞද්ගලික"</string>
@@ -911,15 +911,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"ක්‍රියාවක් තෝරන්න"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB උපාංගය සඳහා යෙදුමක් තෝරන්න"</string>
     <string name="noApplications" msgid="2991814273936504689">"මෙම ක්‍රියාව සිදු කිරීමට කිසිදු යෙදුමකට නොහැකිය."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"අවාසනාවන්ත ලෙස <xliff:g id="APPLICATION">%1$s</xliff:g> නැවතී ඇත."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"අවාසනාවන්ත ලෙස, <xliff:g id="PROCESS">%1$s</xliff:g> ක්‍රියාවලිය නතර විණි."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"නැවත පණ ගන්වන තෙක් <xliff:g id="PROCESS">%1$s</xliff:g> වෙතින් නිහඬ බිඳ වැටීම්"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> නැවතී ඇත"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> නැවතී ඇත"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> නැවතෙමින් ඇත"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> නැවතෙමින් ඇත"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"යෙදුම නැවත ආරම්භ කරන්න"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"යෙදුම නැවත සකසා නැවත ආරම්භ කරන්න"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"ප්‍රතිපෝෂණය යවන්න"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"වසන්න"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"නිහඬ කරන්න"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"රැඳී සිටින්න"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"යෙදුම වසන්න"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ප්‍රතිචාර නොදක්වයි.\n\nඔබට එය නතර කිරීමට අවශ්‍යද?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ක්‍රියාකාරකම ප්‍රතිචාර නොදක්වයි.\n\nඑය වසා දැමීමට ඔබට අවශ්‍යද?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ප්‍රතිචාර නොදක්වයි. එය වසා දැමීමට ඔබට අවශ්‍යද?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> ක්‍රියාවලිය ප්‍රතිචාර නොදක්වයි.\n\nඔබට එය නතර කිරීමට අවශ්‍යද?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ප්‍රතිචාර නොදක්වයි"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ප්‍රතිචාර නොදක්වයි"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ප්‍රතිචාර නොදක්වයි"</string>
+    <string name="anr_process" msgid="6156880875555921105">"ක්‍රියාවලිය <xliff:g id="PROCESS">%1$s</xliff:g> ප්‍රතිචාර නොදක්වයි"</string>
     <string name="force_close" msgid="8346072094521265605">"හරි"</string>
     <string name="report" msgid="4060218260984795706">"වාර්තාව"</string>
     <string name="wait" msgid="7147118217226317732">"රැඳී සිටින්න"</string>
@@ -1026,6 +1033,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM පතක් එකතු කරන ලදි"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"සෙලියුලර් ජාලයට ප්‍රවේශ වීමට ඔබගේ උපාංගය නැවත අරඹන්න."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"යළි අරඹන්න"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"ඔබේ නව SIM නිසි ලෙස වැඩ කිරීමට, ඔබ ඔබේ වාහකය වෙතින් යෙදුමක් ස්ථාපනය කර විවෘත කිරීම අවශ්‍යය."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"යෙදුම ලබා ගන්න"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"දැන්ම නොවේ"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"නව SIM ඇතුළු කරන්න"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"එය පිහිටුවීමට තට්ටු කරන්න"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"වේලාව සකසන්න"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"දිනය සැකසීම"</string>
     <string name="date_time_set" msgid="5777075614321087758">"සකසන්න"</string>
@@ -1457,7 +1469,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ගැලවීමට පෙර PIN විමසන්න"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ගැලවීමට පෙර අගුළු අරින රටාව සඳහා අසන්න"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ගැලවීමට පෙර මුරපදය විමසන්න"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"යෙදුම ප්‍රතිප්‍රමාණ කළ හැකි නොවේ, එය ඇඟිලි දෙකකින් අනුචලනය කරන්න."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"යෙදුම ප්‍රතිප්‍රමාණ කළ හැකි නොවේ, එය ඇඟිලි දෙකකින් අනුචලනය කරන්න."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"යෙදුම බෙදුණු-තිරය සඳහා සහාය නොදක්වයි."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ඔබගේ පරිපාලක විසින් ස්ථාපනය කරන ලද"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ඔබගේ පරිපාලක විසින් යාවත්කාලීන කරන ලදී"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ඔබගේ පරිපාලක විසින් මකන ලද"</string>
@@ -1529,14 +1542,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"විවිධාකාර"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"ඔබ මෙම දැනුම්දීම්වල වැදගත්කම සකසා ඇත."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"සම්බන්ධ වූ පුද්ගලයන් නිසා මෙය වැදගත් වේ."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" නව පරිශීලකයෙකු එක් කිරීමට උත්සාහ කරමින් සිටින නමුත්, දැනට තහනම්ය."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" නව පරිශීලකයෙකු එක් කිරීමට උත්සාහ කරමින් සිටින නමුත්, පරිශීලක සීමාවට ළඟා වී ඇත."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" නව පරිශීලකයෙකු එක් කිරීමට උත්සාහ කරමින් සිටී, නමුත් "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ගිණුම මෙම උපාංගය මත දැනටමත් පවතී. කෙසේ වෙතත් ඉදිරියට යන්නද?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" නව පරිශීලකයෙකු "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ගිණුම සඳහා එක් කිරීමට උත්සාහ කරමින් සිටී. ඉදිරියට යන්නද?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> හට <xliff:g id="ACCOUNT">%2$s</xliff:g> සමගින් නව පරිශීලකයෙකු සෑදීමට ඉඩ දෙන්නද?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> හට <xliff:g id="ACCOUNT">%2$s</xliff:g> සමගින් නව පරිශීලකයෙකු සෑදීමට ඉඩ දෙන්නද (මෙම ගිණුම සහිත පරිශීලකයෙකු දැනටමත් සිටී) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"භාෂා මනාප"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ප්‍රදේශ මනාපය"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"භාෂා නම ටයිප් කරන්න"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"යෝජිත"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"සියලු භාෂා"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"සෙවීම"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"වැඩ ප්‍රකාරය ක්‍රියාවිරහිතයි"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"යෙදුම්, පසුබිම සමමුහුර්ත කිරීම, සහ සම්බන්ධිත විශේෂාංග ඇතුළුව, ක්‍රියා කිරීමට කාර්යාල පැතිකඩට ඉඩ දෙන්න"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ක්‍රියාත්මක කරන්න"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s අබල කරන ලදී"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s පරිපාලක විසින් අබල කරන ලදී. තව දැන ගැනීමට ඔවුන් අමතන්න."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"ඔබට නව පණිවිඩ තිබේ"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"බැලීමට විවෘත SMS යෙදුම විවෘත කරන්න"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"සමහර කාර්ය නොතිබිය හැකිය"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"දිගටම කරගෙන යාමට ස්පර්ශ කරන්න"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"පරිශීලක පැතිකඩ අගුලු දමා ඇත"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> වෙත සම්බන්ධ විය"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ගොනු බැලීමට තට්ටු කරන්න"</string>
+    <string name="pin_target" msgid="3052256031352291362">"අමුණන්න"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"ගලවන්න"</string>
+    <string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 8e08adc..4369374 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -216,8 +216,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktívne nahlásenie"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Táto možnosť je vhodná pre väčšinu prípadov. Umožňuje sledovať priebeh nahlásenia a zadať ďalšie podrobnosti o probléme. Môžu byť vynechané niektoré menej používané sekcie, ktorých nahlásenie trvá dlho."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Úplné nahlásenie"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Táto možnosť slúži na minimalizáciu zásahov do systému, keď zariadenie neodpovedá, je príliš pomalé alebo potrebujete zahrnúť všetky sekcie prehľadu. Týmto spôsobom nie je možné vytvoriť snímku obrazovky ani zadať ďalšie podrobnosti."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="few">Snímka obrazovky pre hlásenie chyby sa vytvorí o <xliff:g id="NUMBER_1">%d</xliff:g> sekundy.</item>
       <item quantity="many">Snímka obrazovky pre hlásenie chyby sa vytvorí o <xliff:g id="NUMBER_1">%d</xliff:g> sekundy.</item>
@@ -237,6 +236,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Skrytý obsah"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Obsah je na základe pravidiel skrytý"</string>
     <string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osobné"</string>
@@ -921,15 +921,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Zvoľte akciu"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Zvoľte aplikáciu pre zariadenie USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Túto akciu nemôžu vykonávať žiadne aplikácie."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Aplikácia <xliff:g id="APPLICATION">%1$s</xliff:g> bohužiaľ prestala pracovať."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> bohužiaľ prestal pracovať."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Stíšenie zlyháva od procesu <xliff:g id="PROCESS">%1$s</xliff:g> až po reštartovanie."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Aplikácia <xliff:g id="APPLICATION">%1$s</xliff:g> sa zastavila"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> sa zastavil"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> sa opakovane zastavuje"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> sa opakovane zastavuje"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Reštartovať aplikáciu"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Resetovať a reštartovať aplikáciu"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Odoslať spätnú väzbu"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Zavrieť"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Ignorovať"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Čakať"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Zavrieť aplikáciu"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Aplikácia <xliff:g id="APPLICATION">%2$s</xliff:g> neodpovedá.\n\nChcete ju zavrieť?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktivita <xliff:g id="ACTIVITY">%1$s</xliff:g> neodpovedá.\n\nChcete ju zavrieť?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Aplikácia <xliff:g id="APPLICATION">%1$s</xliff:g> neodpovedá. Chcete ju zavrieť?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> neodpovedá. \n\nChcete ho zavrieť?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> nereaguje"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nereaguje"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> nereaguje"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> nereaguje"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Nahlásiť"</string>
     <string name="wait" msgid="7147118217226317732">"Čakajte"</string>
@@ -1040,6 +1047,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Bola pridaná SIM karta"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Ak chcete získať prístup k mobilnej sieti, reštartujte svoje zariadenie."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Reštartovať"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Ak chcete, aby vaša nová SIM karta fungovala správne, musíte nainštalovať a spustiť aplikáciu od operátora."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ZÍSKAŤ APLIKÁCIU"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"TERAZ NIE"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Bola vložená nová SIM karta"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Nastavte ju klepnutím"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastaviť čas"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastaviť dátum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nastaviť"</string>
@@ -1475,7 +1487,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pred uvoľnením požiadať o číslo PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pred uvoľnením požiadať o bezpečnostný vzor"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred uvoľnením požiadať o heslo"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Veľkosť aplikácie nie je možné zmeniť. Zobrazenie môžete posúvať dvoma prstami."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Veľkosť aplikácie nie je možné zmeniť. Zobrazenie môžete posúvať dvoma prstami."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikácia nepodporuje rozdelenú obrazovku."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Inštalovaný správcom"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Aktualizované správcom"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Odstránený správcom"</string>
@@ -1565,14 +1578,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Rôzne"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Nastavili ste dôležitosť týchto upozornení."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Táto správa je dôležitá vzhľadom na osoby, ktorých sa to týka."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"Aplikácia "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" sa pokúša pridať nového používateľa, avšak momentálne je zakázaná."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"Aplikácia "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" sa pokúša pridať nového používateľa, bol však prekročený limit počtu používateľov."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"Aplikácia "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" sa pokúša pridať nového používateľa, účet "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" však na tomto zariadení už existuje. Chcete napriek tomu pokračovať?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392">"Aplikácia "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" sa pokúša pridať nového používateľa pre účet "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Chcete pokračovať?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Povoliť aplikácii <xliff:g id="APP">%1$s</xliff:g> vytvoriť nového používateľa pomocou účtu <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Povoliť aplikácii <xliff:g id="APP">%1$s</xliff:g> vytvoriť nového používateľa pomocou účtu <xliff:g id="ACCOUNT">%2$s</xliff:g> (používateľ s týmto účtom už existuje)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Jazykové predvoľby"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferovaný región"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Zadajte názov jazyka"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Navrhované"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Všetky jazyky"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Vyhľadávanie"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Pracovný režim je VYPNUTÝ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Povoľte fungovanie pracovného profilu vrátane aplikácií, synchronizácie na pozadí a súvisiacich funkcií."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Zapnúť"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Balík %1$s bol zakázaný"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Zakázané správcom %1$s. Ak chcete získať ďalšie informácie, kontaktujte ho."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Máte nové správy."</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorte aplikáciu pre SMS a zobrazte správu"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Niektoré funkcie nemusia byť dostupné"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Pokračujte klepnutím"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil používateľa je zamknutý"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Pripojené k zariadeniu <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Klepnutím zobrazíte súbory"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Pripnúť"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Uvoľniť"</string>
+    <string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c85f7b5..00c47e7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -216,8 +216,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivno poročilo"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"To možnost uporabite v večini primerov. Omogoča sledenje napredka poročila in vnos več podrobnosti o težavi. Morda bodo izpuščeni nekateri redkeje uporabljani razdelki, za katere je poročanje dolgotrajno."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Celotno poročilo"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"To možnost uporabite za najmanj motenj sistema, če je naprava neodzivna ali prepočasna oziroma ko potrebujete vse razdelke poročila. Ne naredi posnetka zaslona in ne omogoča vnosa več podrobnosti."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Posnetek zaslona za poročilo o napakah bo narejen čez <xliff:g id="NUMBER_1">%d</xliff:g> s.</item>
       <item quantity="two">Posnetek zaslona za poročilo o napakah bo narejen čez <xliff:g id="NUMBER_1">%d</xliff:g> s.</item>
@@ -237,6 +236,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Vsebina je skrita"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Pravilnik je skril vsebino"</string>
     <string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osebno"</string>
@@ -921,15 +921,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Izberite dejanje"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Izberite aplikacijo za napravo USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Tega dejanja ne more izvesti nobena aplikacija."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Žal se je aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> ustavila."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Žal se je postopek <xliff:g id="PROCESS">%1$s</xliff:g> ustavil."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Utišanje obvestil o zrušitvah procesa <xliff:g id="PROCESS">%1$s</xliff:g> do vnovičnega zagona."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> se je ustavila"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> se je ustavil"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> se stalno ustavlja"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> se stalno ustavlja"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Vnovični zagon aplikacije"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Ponastavitev in vnovični zagon aplikacije"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Pošlji povratne informacije"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Zapri"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Prezri"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Počakajte"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Zapri aplikacijo"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Aplikacija <xliff:g id="APPLICATION">%2$s</xliff:g> se ne odziva.\n\nAli jo želite zapreti?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Dejavnost <xliff:g id="ACTIVITY">%1$s</xliff:g> se ne odziva.\n\nAli jo želite zapreti?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> se ne odziva. Ali jo želite zapreti?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> se ne odziva.\n\nAli ga želite zapreti?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"Aplikacija <xliff:g id="APPLICATION">%2$s</xliff:g> se ne odziva"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"Dejavnost <xliff:g id="ACTIVITY">%1$s</xliff:g> se ne odziva"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> se ne odziva"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> se ne odziva"</string>
     <string name="force_close" msgid="8346072094521265605">"V redu"</string>
     <string name="report" msgid="4060218260984795706">"Poročaj"</string>
     <string name="wait" msgid="7147118217226317732">"Čakaj"</string>
@@ -1040,6 +1047,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Kartica SIM dodana"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Za dostop do mobilnega omrežja znova zaženite napravo."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Vnovičen zagon"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastavi uro"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavi datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nastavi"</string>
@@ -1475,7 +1492,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Zahtevaj PIN pred odpenjanjem"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pred odpenjanjem vprašaj za vzorec za odklepanje"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred odpenjanjem vprašaj za geslo"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Velikosti aplikacije ni mogoče spremeniti. Po njej se pomikajte z dvema prstoma."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Velikosti aplikacije ni mogoče spremeniti. Po njej se pomikajte z dvema prstoma."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacija ne podpira načina razdeljenega zaslona."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Namestil skrbnik"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Posodobil skrbnik"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisal skrbnik"</string>
@@ -1565,14 +1583,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Razno"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Vi določite raven pomembnosti teh obvestil."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Pomembno zaradi udeleženih ljudi."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"Aplikacija "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" poskuša dodati novega uporabnika, vendar trenutno nima dovoljenja."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"Aplikacija "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" poskuša dodati novega uporabnika, vendar je dosežena omejitev števila uporabnikov."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"Aplikacija "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" poskuša dodati novega uporabnika, vendar račun "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" v napravi že obstaja. Ali želite kljub temu nadaljevati?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392">"Aplikacija "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" poskuša dodati novega uporabnika za račun "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Ali želite nadaljevati?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Dovolite, da aplikacija <xliff:g id="APP">%1$s</xliff:g> ustvari novega uporabnika za račun <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Dovolite aplikaciji <xliff:g id="APP">%1$s</xliff:g>, da ustvari novega uporabnika za račun <xliff:g id="ACCOUNT">%2$s</xliff:g> (uporabnik s tem računom že obstaja)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Nastavitev jezika"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Nastavitev območja"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Vnesite ime jezika"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Predlagano"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Vsi jeziki"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Išči"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Delovni način IZKLOPLJEN"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Dovoljeno delovanje delovnega profila, vključno z aplikacijami, sinhronizacijo v ozadju in povezanimi funkcijami."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Vklop"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s – onemogočeno"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Onemogočil skrbnik %1$s. Za več informacij se obrnite nanj."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nova sporočila."</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Za ogled odprite aplikacijo za SMS-je"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Nek. funk. morda niso na voljo"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Dotaknite se za nadaljevanje"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profil uporabnika zaklenjen"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Vzpostavljena povezava z napravo <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Dotaknite se, če si želite ogledati datoteke"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Pripenjanje"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Odpenjanje"</string>
+    <string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
 </resources>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 65156f0..70164be 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Raport interaktiv"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Përdore këtë në shumicën e rrethanave. Të lejon të gjurmosh progresin e raportit dhe të fusësh më shumë detaje rreth problemit. Mund të fshijë disa seksione që përdoren më pak të cilat kërkojnë shumë kohë për t\'u raportuar."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Raporti i plotë"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Përdore këtë opsion për interferencë minimale kur pajisja nuk përgjigjet ose është tepër e ngadaltë, ose kur të nevojiten të gjitha seksionet. Nuk regjistron pamje të ekranit ose nuk të lejon që të fusësh më shumë të dhëna."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Marrja e pamjes së ekranit për raportin e defektit në kod në <xliff:g id="NUMBER_1">%d</xliff:g> sekonda.</item>
       <item quantity="one">Marrja e pamjes së ekranit për raportin e defektit në kod në <xliff:g id="NUMBER_0">%d</xliff:g> sekondë.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Përmbajtjet janë të fshehura"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Përmbajtja është e fshehur për shkak të politikës"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modaliteti i sigurisë"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemi \"android\""</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Zgjidh një veprim"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Zgjidh një aplikacion për pajisjen \"USB\""</string>
     <string name="noApplications" msgid="2991814273936504689">"Asnjë aplikacion nuk mund ta kryejë këtë veprim."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Fatkeqësisht, <xliff:g id="APPLICATION">%1$s</xliff:g> ka ndaluar."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Fatkeqësisht, procesi <xliff:g id="PROCESS">%1$s</xliff:g> ka ndaluar."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Ka një heshtje të <xliff:g id="PROCESS">%1$s</xliff:g> deri në rindezje."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ka ndaluar"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ka ndaluar"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> vazhdon të ndalojë"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> vazhdon të ndalojë"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Rinis aplikacionin"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Rivendos dhe rinis aplikacionin"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Dërgo komentin"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Mbyll"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Çaktivizo audion"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Prit!"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Mbyll aplikacionin"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> nuk po përgjigjet.\n\nDëshiron ta mbyllësh?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktiviteti <xliff:g id="ACTIVITY">%1$s</xliff:g> nuk përgjigjet.\n\nDëshiron ta mbyllësh?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> nuk po përgjigjet. Dëshiron ta mbyllësh?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Procesi <xliff:g id="PROCESS">%1$s</xliff:g> nuk po përgjigjet.\n\nDëshiron ta mbyllësh?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> nuk përgjigjet"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nuk përgjigjet"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> nuk përgjigjet"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Përpunimi i <xliff:g id="PROCESS">%1$s</xliff:g> nuk përgjigjet"</string>
     <string name="force_close" msgid="8346072094521265605">"Në rregull"</string>
     <string name="report" msgid="4060218260984795706">"Raporto"</string>
     <string name="wait" msgid="7147118217226317732">"Prit!"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Karta SIM u shtua"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Rinise pajisjen për të pasur qasje në rrjetin celular."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Rifillo"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Që karta e re SIM të funksionojë siç duhet, duhet të instalosh dhe të hapësh një aplikacion nga operatori yt."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"MERR APLIKACIONIN"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"JO TANI"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Është futur kartë e re SIM"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Trokit për ta konfiguruar"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Cakto kohën"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Vendos datën"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Cakto"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Zhgozhdimi kërkon PIN-in"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Kërko model shkyçjeje para heqjes së gozhdimit"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Kërko fjalëkalim para heqjes nga gozhdimi."</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Përmasa e apl. nuk mund të ndryshohet, lëvize atë me të dy gishtat."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Përmasa e apl. nuk mund të ndryshohet, lëvize atë me të dy gishtat."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikacioni nuk mbështet ekranin e ndarë."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"U instalua nga administratori yt"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Përditësuar nga administratori"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"U fshi nga administratori yt"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Të ndryshme"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Ke caktuar rëndësinë e këtyre njoftimeve."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Është i rëndësishëm për shkak të personave të përfshirë."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" po përpiqet të shtojë një përdorues të ri, por aktualisht nuk i lejohet."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" po përpiqet të shtojë një përdorues të ri, por është arritur limiti i përdoruesve."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" po provon të shtojë një përdorues të ri, por llogaria "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ekziston tashmë në këtë pajisje. Dëshiron të vazhdosh gjithsesi?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" po provon të shtojë një përdorues të ri për llogarinë "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Dëshiron të vazhdosh?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Dëshiron të lejosh <xliff:g id="APP">%1$s</xliff:g> që të krijojë një përdorues të ri me <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Dëshiron të lejosh <xliff:g id="APP">%1$s</xliff:g> që të krijojë një përdorues të ri me <xliff:g id="ACCOUNT">%2$s</xliff:g> (një përdorues me këtë llogari ekziston tashmë) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Preferenca për gjuhën"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Preferenca e rajonit"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Shkruaj emrin e gjuhës"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugjeruar"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Të gjitha gjuhët"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Kërko"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Modaliteti i punës është JOAKTIV"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Lejoje profilin e punës të funksionojë, duke përfshirë aplikacionet, sinkronizimin në sfond dhe funksionet e lidhura."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivizo"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s është çaktivizuar"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Çaktivizuar nga administratori i %1$s. Kontaktoje për të mësuar më shumë."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Ke mesazhe të reja"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Hap aplikacionin SMS për ta parë"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Disa funksione mund të mos jenë të disponueshme"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Preke për të vazhduar"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Profili i përdoruesit i kyçur"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"U lidh me <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Trokit për të parë skedarët"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Gozhdo"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Zhgozhdo"</string>
+    <string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index fe7b0d7..cb17123 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -215,8 +215,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Интерактив. извештај"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Користите ово у већини случајева. То вам омогућава да пратите напредак извештаја и да уносите додатне детаље о проблему. Вероватно ће изоставити неке мање коришћене одељке за које прављење извештаја дуго траје."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Комплетан извештај"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Користите ову опцију ради минималних системских сметњи када уређај не реагује, преспор је или су вам потребни сви одељци извештаја. Не прави снимак екрана нити вам дозвољава унос додатних детаља."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Направићемо снимак екрана ради извештаја о грешци за <xliff:g id="NUMBER_1">%d</xliff:g> секунду.</item>
       <item quantity="few">Направићемо снимак екрана ради извештаја о грешци за <xliff:g id="NUMBER_1">%d</xliff:g> секунде.</item>
@@ -235,6 +234,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Садржај је сакривен"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Садржај је сакривен смерницама"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Лично"</string>
@@ -915,15 +915,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Изаберите радњу"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Избор апликације за USB уређај"</string>
     <string name="noApplications" msgid="2991814273936504689">"Ниједна апликација не може да обавља ову радњу."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Нажалост, апликација <xliff:g id="APPLICATION">%1$s</xliff:g> је престала с радом."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Нажалост, процес <xliff:g id="PROCESS">%1$s</xliff:g> је заустављен."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Нечујна отказивања од процеса <xliff:g id="PROCESS">%1$s</xliff:g> до рестартовања."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Апликација <xliff:g id="APPLICATION">%1$s</xliff:g> је заустављена"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> је заустављен"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> се стално зауставља"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> се стално зауставља"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Поново покрени апликацију"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Ресетуј и поново покрени апликацију"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Пошаљите повратне информације"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Затвори"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Игнориши"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Чекај"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Затвори апликацију"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> не реагује.\n\nДа ли желите да је затворите?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Активност <xliff:g id="ACTIVITY">%1$s</xliff:g> не рeагује.\n\nДа ли желите да је затворите?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> не реагује. Да ли желите да је затворите?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> не раегује.\n\nДа ли желите да га затворите?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> не реагује"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> не реагује"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> не реагује"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> не реагује"</string>
     <string name="force_close" msgid="8346072094521265605">"Потврди"</string>
     <string name="report" msgid="4060218260984795706">"Пријави"</string>
     <string name="wait" msgid="7147118217226317732">"Сачекај"</string>
@@ -1032,6 +1039,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM картица је додата"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Поново покрените уређај да бисте приступили мобилној мрежи."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Поново покрени"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Подешавање времена"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Подешавање датума"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Подеси"</string>
@@ -1465,7 +1482,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Тражи PIN пре откачињања"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Тражи шаблон за откључавање пре откачињања"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тражи лозинку пре откачињања"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Величина апликације не може да се мења, померајте је помоћу два прста."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Величина апликације не може да се мења. Померајте је помоћу два прста."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Апликација не подржава подељени екран."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Инсталирао је ваш администратор"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирао је администратор"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Избрисао је ваш адмиистратор"</string>
@@ -1546,14 +1564,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Разно"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Ви подешавате важност ових обавештења."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Ово је важно због људи који учествују."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" покушава да дода новог корисника, али то је тренутно забрањено."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" покушава да дода новог корисника, али је ограничење за број корисника достигнуто."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" покушава да дода новог корисника, али налог "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" већ постоји на овом уређају. Желите ли ипак да наставите?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" покушава да дода новог корисника за налог "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Желите ли да наставите?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Желите ли да дозволите апликацији <xliff:g id="APP">%1$s</xliff:g> да направи новог корисника за <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Желите ли да дозволите апликацији <xliff:g id="APP">%1$s</xliff:g> да направи новог корисника за <xliff:g id="ACCOUNT">%2$s</xliff:g> (корисник са овим налогом већ постоји)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Подешавање језика"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Подешавање региона"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Унесите назив језика"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Сви језици"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Претражи"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Режим за Work је ИСКЉУЧЕН"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Дозвољава профилу за Work да функционише, укључујући апликације, синхронизацију у позадини и сродне функције."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Укључи"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Пакет %1$s је онемогућен"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Онемогућио је администратор компаније %1$s. Контактирајте га да бисте сазнали више."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Имате нове поруке"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Отворите апликацију за SMS да бисте прегледали"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Неке функције нису доступне"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Додирните да бисте наставили"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Профил корисника је закључан"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Повезано је са производом <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Додирните за преглед датотека"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Закачи"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Откачи"</string>
+    <string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index d80b4c2..f90f95c 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv rapport"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Bör användas i de flesta fall. Då kan du spåra rapportförloppet och ange mer information om problemet. En del mindre använda avsnitt, som det tar lång tid att rapportera om, kan uteslutas."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Fullständig rapport"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Alternativet innebär minsta möjliga störning när enheten inte svarar eller är långsam, eller när alla avsnitt ska ingå i rapporten. Inget skärmdump tas och du kan inte ange mer information."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Tar en skärmdump till felrapporten om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder.</item>
       <item quantity="one">Tar en skärmdump till felrapporten om <xliff:g id="NUMBER_0">%d</xliff:g> sekund.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Innehåll har dolts"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Innehåll har dolts p.g.a. en policy"</string>
     <string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personligt"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Välj en åtgärd"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Välja en app för USB-enheten"</string>
     <string name="noApplications" msgid="2991814273936504689">"Inga appar kan utföra den här åtgärden."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"<xliff:g id="APPLICATION">%1$s</xliff:g> har tyvärr stoppats."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> har tyvärr stoppats."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Ignorera krascher från <xliff:g id="PROCESS">%1$s</xliff:g> fram till omstart."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> har kraschat"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> har kraschat"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> kraschar gång på gång"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> kraschar gång på gång"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Starta om appen"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Återställ och starta om appen"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Skicka feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Stäng"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Dölj"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Vänta"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Stäng appen"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> svarar inte.\n\nVill du stänga den?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Aktiviteten <xliff:g id="ACTIVITY">%1$s</xliff:g> svarar inte.\n \nVill du stänga den?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> svarar inte. Vill du stänga den?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> svarar inte.\n\nVill du stänga den?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> svarar inte"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> svarar inte"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> svarar inte"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> svarar inte"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Rapportera"</string>
     <string name="wait" msgid="7147118217226317732">"Vänta"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-kort lades till"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Starta om enheten om du vill få tillgång till mobilnätet."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Starta om"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Du måste installera och öppna en app från operatören om SIM-kortet ska fungera korrekt."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"HÄMTA APPEN"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"INTE NU"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Nytt SIM-kort har satts in"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Tryck om du vill konfigurera"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ange tid"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ange datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ställ in"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Be om pinkod innan skärmen slutar fästas"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Be om upplåsningsmönster innan skärmen slutar fästas"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Be om lösenord innan skärmen slutar fästas"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Det går inte att ändra appens storlek. Rulla med två fingrar."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Det går inte att ändra appens storlek. Rulla med två fingrar."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen har inte stöd för delad skärm."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Paketet har installerats av administratören"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Uppdaterat av administratören"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Paketet har raderats av administratören"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Du anger hur viktiga aviseringarna är."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Detta är viktigt på grund av personerna som deltar."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" försöker lägga till en ny användare, men får inte göra det för närvarande."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" försöker lägga till en ny användare, men gränsen för antal användare har uppnåtts."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" försöker lägga till en ny användare, men kontot "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" finns redan på den här enheten. Vill du fortsätta ändå?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" försöker lägga till en ny användare för kontot "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Vill du fortsätta?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Tillåter du att <xliff:g id="APP">%1$s</xliff:g> skapar en ny användare för <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Tillåter du att <xliff:g id="APP">%1$s</xliff:g> skapar en ny användare för <xliff:g id="ACCOUNT">%2$s</xliff:g> (det finns redan en användare med det här kontot)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Språkinställning"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Regionsinställningar"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Ange språket"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Förslag"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Alla språk"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Söka"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Arbetsläget är inaktiverat"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Tillåt att jobbprofilen är aktiv, inklusive appar, bakgrundssynkronisering och andra tillhörande funktioner."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivera"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s har inaktiverats"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Inaktiverat av administratören för %1$s. Kontakta administratören om du vill veta mer."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nya meddelanden"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Öppna sms-appen och visa meddelandet"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Vissa funktioner är inte tillgängliga"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Tryck om du vill fortsätta"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Användarprofilen är låst"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Ansluten till <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Filerna visas om du trycker här"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Fäst"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Lossa"</string>
+    <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 5ae50b8..1c7f2e2 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -216,8 +216,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Ripoti ya kushirikiana"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Itumie katika hali nyingi. Inakuruhusu kufuatilia maendeleo ya ripoti na kuweka maelezo zaidi kuhusu tatizo. Huenda ikaondoa sehemu ambazo hazitumiki sana, ambazo huchukua muda mrefu kuripoti."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Ripoti kamili"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Tumia chaguo hili ili upunguze kukatizwa wakati kifaa chako kinapokwama au kinapofanya kazi pole pole sana, au unapohitaji sehemu zote za ripoti. Haipigi picha ya skrini wala kukuruhusu kuweka maelezo zaidi."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Inapiga picha ya skrini ili iripoti hitilafu baada ya sekunde <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
       <item quantity="one">Inapiga picha ya skrini ili iripoti hitilafu baada ya sekunde <xliff:g id="NUMBER_0">%d</xliff:g>.</item>
@@ -235,6 +234,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Maudhui yamefichwa"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Maudhui yamefichwa kulingana na sera"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Binafsi"</string>
@@ -911,15 +911,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Chagua kitendo"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Chagua programu ya kifaa cha USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Hakuna programu zinazoweza kufanya tendo hili."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Kwa bahati mbaya, <xliff:g id="APPLICATION">%1$s</xliff:g> imeacha kufanya kazi."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Kwa bahati mbaya, mchakato wa <xliff:g id="PROCESS">%1$s</xliff:g> umekoma."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Programu imekoma kufanya kazi kuanzia <xliff:g id="PROCESS">%1$s</xliff:g> mpaka iwashwe tena."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> imeacha kufanya kazi"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> imeacha kufanya kazi"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> inaacha kufanya kazi kila mara"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> inaacha kufanya kazi kila mara"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Anzisha upya programu"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Weka na uanzishe upya programu"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Tuma maoni yako"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Funga"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Komesha"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Subiri"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Funga programu"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> haifanyi kazi.\n\nUnataka kuifunga?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Shughuli ya <xliff:g id="ACTIVITY">%1$s</xliff:g> haifanyi kazi.\n\nJe, ungependa kuifunga?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> haifanyi kazi. Je, ungependa kuifunga?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Mchakato wa <xliff:g id="PROCESS">%1$s</xliff:g> haufanyi kazi. \n\nJe, ungependa kuifunga?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> haifanyi kazi"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> haifanyi kazi"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> haifanyi kazi"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Mchakato wa <xliff:g id="PROCESS">%1$s</xliff:g> haufanyi kazi"</string>
     <string name="force_close" msgid="8346072094521265605">"Sawa"</string>
     <string name="report" msgid="4060218260984795706">"Ripoti"</string>
     <string name="wait" msgid="7147118217226317732">"Subiri"</string>
@@ -1026,6 +1033,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM kadi imeongezwa"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Zima na uwashe kifaa chako tena ili ufikie mitandao ya simu za mkononi."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Anza upya"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Weka muda"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Weka tarehe"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Weka"</string>
@@ -1457,7 +1474,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Omba PIN kabla hujabandua"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Omba mchoro wa kufungua kabla hujabandua"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Omba nenosiri kabla hujabandua"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Programu haiwezi kurekebishwa ukubwa, sogeza kwa kutumia vidole viwili."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Programu haiwezi kurekebishwa ukubwa, sogeza kwa kutumia vidole viwili."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Programu haiwezi kutumia skrini iliyogawanywa."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Kilisakinishwa na msimamizi wako"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Kimesasiswa na msimamizi wako"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Kilifutwa na msimamizi wako"</string>
@@ -1529,14 +1547,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Anuwai"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Uliweka umuhimu wa arifa hizi."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Hii ni muhimu kwa sababu ya watu waliohusika."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" inajaribu kuongeza mtumiaji mpya, lakini hatua hii hairuhusiwi kwa sasa."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" inajaribu kuongeza mtumiaji mpya, lakini idadi ya juu ya watumiaji imefikiwa."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" inajaribu kuongeza mtumiaji mpya, lakini akaunti ya "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" tayari ipo kwenye kifaa hiki. Ungependa kundelea?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" inajaribu kuongeza mtumiaji mpya kwenye akaunti ya "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Ungependa kuendelea?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Ungependa kuruhusu <xliff:g id="APP">%1$s</xliff:g> iunde Mtumiaji mpya ikitumia <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Ungependa kuruhusu <xliff:g id="APP">%1$s</xliff:g> iunde Mtumiaji mpya ikitumia <xliff:g id="ACCOUNT">%2$s</xliff:g> (Je, akaunti hii tayari ina Mtumiaji)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Lugha ninayopendelea"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Mapendeleo ya eneo"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Weka jina la lugha"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Inayopendekezwa"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Lugha zote"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Tafuta"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Hali ya kazi IMEZIMWA"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Ruhusu wasifu wa kazini utumike, ikiwa ni pamoja na programu, usawazishaji wa chini chini na vipengele vinavyohusiana."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Washa"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Imezimwa na %1$s"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Imezimwa na msimamizi wa %1$s. Wasiliana naye ili upate maelezo zaidi."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Una ujumbe mpya"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Fungua programu ya SMS ili uweze kuangalia"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Huenda baadhi ya vipengele visipatikane"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Gusa ili uendelee"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Wasifu wa mtumiaji umefungwa"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Imeunganishwa na <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Gonga ili uangalie faili"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Bandika"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Bandua"</string>
+    <string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string>
 </resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 4671344..8366985 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ஊடாடத்தக்க அறிக்கை"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"பெரும்பாலான சூழ்நிலைகளில் இதைப் பயன்படுத்தவும். இது அறிக்கையின் நிலையைக் கண்காணிக்கவும், சிக்கலைப் பற்றிய மேலும் விவரங்களை உள்ளிடவும் அனுமதிக்கும். அறிக்கையிட நீண்ட நேரம் எடுக்கக்கூடிய குறைவாகப் பயன்படுத்தப்படும் பிரிவுகள் சிலவற்றை இது தவிர்க்கக்கூடும்."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"முழு அறிக்கை"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"சாதனம் செயல்படாமல் இருக்கும் போது அல்லது மெதுவாகச் செயல்படும் போது அல்லது உங்களுக்கு எல்லா அறிக்கைப் பிரிவுகளும் தேவைப்படும் போது குறைவான முறைமைக் குறுக்கீடுகளுக்கு, இந்த விருப்பத்தைப் பயன்படுத்தவும். இந்த விருப்பம் ஸ்கிரீன் ஷாட்டை எடுக்காது அல்லது மேலும் விவரங்களை உள்ளிட அனுமதிக்காது."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகளில் பிழை அறிக்கைக்கான ஸ்கிரீன் ஷாட் எடுக்கப்படும்.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> வினாடியில் பிழை அறிக்கைக்கான ஸ்கிரீன் ஷாட் எடுக்கப்படும்.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"மறைந்துள்ள உள்ளடக்கம்"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"கொள்கையின்படி உள்ளடக்கம் மறைக்கப்பட்டது"</string>
     <string name="safeMode" msgid="2788228061547930246">"பாதுகாப்பு பயன்முறை"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android அமைப்பு"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"தனிப்பட்ட"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"செயலைத் தேர்ந்தெடுக்கவும்"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB சாதனத்திற்கான பயன்பாட்டைத் தேர்வுசெய்க"</string>
     <string name="noApplications" msgid="2991814273936504689">"இந்தச் செயலைச் செய்ய பயன்பாடுகள் எதுவுமில்லை."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"துரதிருஷ்டவசமாக, <xliff:g id="APPLICATION">%1$s</xliff:g> நிறுத்தப்பட்டது."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"துரதிருஷ்டவசமாக, <xliff:g id="PROCESS">%1$s</xliff:g> செயல்முறை நிறுத்தப்பட்டது."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"<xliff:g id="PROCESS">%1$s</xliff:g> இன் செயலிழப்புகளை மறுதொடக்கம் செய்யும் வரை தெரிவிக்காதே."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> செயலிழந்தது"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> செயலிழந்தது"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> தொடர்ந்து நிறுத்தப்படுகிறது"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> தொடர்ந்து நிறுத்தப்படுகிறது"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"பயன்பாட்டை மீண்டும் தொடங்கு"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"பயன்பாட்டை மீட்டமைத்து மீண்டும் தொடங்கு"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"கருத்து தெரிவி"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"மூடு"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"முடக்கு"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"காத்திரு"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"பயன்பாட்டை மூடு"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> பதிலளிக்கவில்லை.\n\nஇதை மூட விருப்பமா?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> செயல்பாடு பதிலளிக்கவில்லை.\n\nஇதை மூடவா?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> பதிலளிக்கவில்லை. இதை மூடவா?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> செயல்முறை பதிலளிக்கவில்லை.\n\nஇதை மூடவா?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> பதிலளிக்கவில்லை"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> பதிலளிக்கவில்லை"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> பதிலளிக்கவில்லை"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> செயல்முறை பதிலளிக்கவில்லை"</string>
     <string name="force_close" msgid="8346072094521265605">"சரி"</string>
     <string name="report" msgid="4060218260984795706">"புகாரளி"</string>
     <string name="wait" msgid="7147118217226317732">"காத்திரு"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"சிம் கார்டு சேர்க்கப்பட்டது"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"செல்லுலார் நெட்வொர்க்கை அணுக உங்கள் சாதனத்தை மறுதொடக்கம் செய்யவும்."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"மறுதொடக்கம்"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"புதிய சிம் சரியாக இயங்குவதற்கு, நீங்கள் பயன்படுத்தும் மொபைல் நிறுவனத்திலிருந்து பயன்பாட்டை நிறுவி, திறக்கவும்."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"பயன்பாட்டைப் பெறுக"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"இப்போது வேண்டாம்"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"புதிய சிம் செருகப்பட்டது"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"அமைக்க, தட்டவும்"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"நேரத்தை அமை"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"தேதியை அமை"</string>
     <string name="date_time_set" msgid="5777075614321087758">"அமை"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"அகற்றும் முன் PINஐக் கேள்"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"அகற்றும் முன் திறத்தல் வடிவத்தைக் கேள்"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"அகற்றும் முன் கடவுச்சொல்லைக் கேள்"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"பயன்பாடு அளவுமாறக்கூடியது அல்ல, இருவிரல்களைப் பயன்படுத்தி அதை உருட்டவும்."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"பயன்பாடு அளவுமாறக்கூடியது அல்ல. இருவிரல்களைப் பயன்படுத்தி, அதை உருட்டவும்."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"திரையைப் பிரிப்பதைப் பயன்பாடு ஆதரிக்கவில்லை."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"நிர்வாகி நிறுவினார்"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"உங்கள் நிர்வாகி புதுப்பித்துள்ளார்"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"நிர்வாகி நீக்கிவிட்டார்"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"இதர அமைப்பு"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"இந்த அறிவிப்புகளின் முக்கியத்துவத்தை அமைத்துள்ளீர்கள்."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ஈடுபட்டுள்ளவர்களின் காரணமாக, இது முக்கியமானது."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" பயன்பாடு புதிய பயனரைச் சேர்க்க முயல்கிறது, ஆனால் பயனரைச் சேர்ப்பது தற்போது தடுக்கப்பட்டுள்ளது."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" பயன்பாடு புதிய பயனரைச் சேர்க்க முயல்கிறது, ஆனால் பயனருக்கான வரம்பு முடிந்துவிட்டது."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" பயன்பாடு புதிய பயனரைச் சேர்க்க முயல்கிறது. ஆனால் "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" கணக்கு ஏற்கனவே இந்தச் சாதனத்தில் உள்ளது. தொடரவா?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" பயன்பாடு "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" கணக்கிற்குப் புதிய பயனரைச் சேர்க்க முயல்கிறது. தொடரவா?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g> மூலம் புதிய பயனரை உருவாக்க <xliff:g id="APP">%1$s</xliff:g>ஐ அனுமதிக்கவா?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g> (இந்தக் கணக்கில் ஏற்கனவே ஒரு பயனர் உள்ளார்) மூலம் புதிய பயனரை உருவாக்க <xliff:g id="APP">%1$s</xliff:g>ஐ அனுமதிக்கவா?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"மொழி விருப்பம்"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"மண்டல விருப்பம்"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"மொழி பெயரை உள்ளிடுக"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"பரிந்துரைகள்"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"எல்லா மொழிகளும்"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"தேடு"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"பணிப் பயன்முறை முடக்கப்பட்டது"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"செயல்பட, பணி சுயவிவரத்தை அனுமதி. இதில் பயன்பாடுகள், பின்னணி ஒத்திசைவு மற்றும் தொடர்புடைய அம்சங்கள் அடங்கும்."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"இயக்கு"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s முடக்கப்பட்டது"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s நிர்வாகி முடக்கியுள்ளார். மேலும் அறிய, அவரைத் தொடர்புகொள்ளவும்."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"புதிய செய்திகள் வந்துள்ளன"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"பார்க்க, SMS பயன்பாட்டைத் திறக்கவும்"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"சில செயல்பாடு கிடைக்காமல் போகலாம்"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"தொடர, தொடவும்"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"பயனர் சுயவிவரம் பூட்டப்பட்டது"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> உடன் இணைக்கப்பட்டது"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"கோப்புகளைப் பார்க்க, தட்டவும்"</string>
+    <string name="pin_target" msgid="3052256031352291362">"பின் செய்"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"பின்னை அகற்று"</string>
+    <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
 </resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 8535b9c..6d42955 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ప్రభావశీల నివేదిక"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"చాలా సందర్భాల్లో ఇది ఉపయోగించబడుతుంది. ఇది మిమ్మల్ని నివేదిక ప్రోగ్రెస్ ట్రాక్ చేయడానికి మరియు సమస్య గురించి మరిన్ని వివరాలను నమోదు చేయడానికి అనుమతిస్తుంది. ఇది నివేదించడానికి అధిక సమయం పట్టే తక్కువగా వినియోగించే విభాగాలను విడిచిపెట్టవచ్చు."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"పూర్తి నివేదిక"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"మీ పరికరం ప్రతిస్పందించనప్పుడు లేదా చాలా నెమ్మదిగా ఉన్నప్పుడు లేదా మీకు అన్ని నివేదిక విభాగాలు అవసరమైనప్పుడు ఏర్పడే కనీస స్థాయి సిస్టమ్ అంతరాయానికి ఈ ఎంపిక ఉపయోగించబడుతుంది. ఇది స్క్రీన్‌షాట్ తీయదు లేదా మరిన్ని వివరాలను నమోదు చేయడానికి మిమ్మల్ని అనుమతించదు."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">బగ్ నివేదిక కోసం <xliff:g id="NUMBER_1">%d</xliff:g> సెకన్లలో స్క్రీన్‌షాట్ తీయబోతోంది.</item>
       <item quantity="one">బగ్ నివేదిక కోసం <xliff:g id="NUMBER_0">%d</xliff:g> సెకనులో స్క్రీన్‌షాట్ తీయబోతోంది.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"కంటెంట్‌లు దాచబడ్డాయి"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"విధానం ద్వారా కంటెంట్‌లు దాచబడ్డాయి"</string>
     <string name="safeMode" msgid="2788228061547930246">"సురక్షిత మోడ్"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android సిస్టమ్"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"వ్యక్తిగతం"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"చర్యను ఎంచుకోండి"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB పరికరం కోసం అనువర్తనాన్ని ఎంచుకోండి"</string>
     <string name="noApplications" msgid="2991814273936504689">"ఈ చర్యను అమలు చేయగల అనువర్తనాలు ఏవీ లేవు."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"దురదృష్టవశాత్తూ, <xliff:g id="APPLICATION">%1$s</xliff:g> ఆపివేయబడింది."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"దురదృష్టవశాత్తూ, ప్రక్రియ <xliff:g id="PROCESS">%1$s</xliff:g> ఆపివేయబడింది."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"రీబూట్ చేసే వరకు <xliff:g id="PROCESS">%1$s</xliff:g> నుండి నిశ్శబ్ద క్రాష్‌లు."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ఆపివేయబడింది"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ఆపివేయబడింది"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> పునరావృతంగా ఆపివేయబడుతోంది"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> పునరావృతంగా ఆపివేయబడుతోంది"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"అనువర్తనాన్ని పునఃప్రారంభించు"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"రీసెట్ చేసి, అనువర్తనాన్ని పునఃప్రారంభించు"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"అభిప్రాయాన్ని పంపు"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"మూసివేయి"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"మ్యూట్ చేయి"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"వేచి ఉండండి"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"అనువర్తనాన్ని మూసివేయి"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ప్రతిస్పందించలేదు.\n\nమీరు దీన్ని మూసివేయాలనుకుంటున్నారా?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> కార్యాచరణ ప్రతిస్పందించలేదు.\n\nమీరు దీన్ని మూసివేయాలనుకుంటున్నారా?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ప్రతిస్పందించలేదు. మీరు దీన్ని మూసివేయాలనుకుంటున్నారా?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> ప్రాసెస్ ప్రతిస్పందించలేదు.\n\nమీరు దీన్ని మూసివేయాలనుకుంటున్నారా?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ప్రతిస్పందించడం లేదు"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ప్రతిస్పందించడం లేదు"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ప్రతిస్పందించడం లేదు"</string>
+    <string name="anr_process" msgid="6156880875555921105">"ప్రాసెస్ <xliff:g id="PROCESS">%1$s</xliff:g> ప్రతిస్పందించడం లేదు"</string>
     <string name="force_close" msgid="8346072094521265605">"సరే"</string>
     <string name="report" msgid="4060218260984795706">"నివేదించు"</string>
     <string name="wait" msgid="7147118217226317732">"వేచి ఉండు"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"సిమ్ కార్డు జోడించబడింది"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"సెల్యులార్ నెట్‌వర్క్‌ను ప్రాప్యత చేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"పునఃప్రారంభించు"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"మీ SIM సక్రమంగా పని చేస్తుండటానికి, మీరు మీ క్యారియర్ నుండి ఒక అనువర్తనాన్ని ఇన్‌స్టాల్ చేసుకొని, తెరవాలి."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"అనువర్తనాన్ని పొందండి"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"ఇప్పుడు కాదు"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"కొత్త SIM చొప్పించారు"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"దీన్ని సెటప్ చేయడానికి నొక్కండి"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"సమయాన్ని సెట్ చేయండి"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"తేదీని సెట్ చేయండి"</string>
     <string name="date_time_set" msgid="5777075614321087758">"సెట్ చేయి"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"అన్‌పిన్ చేయడానికి ముందు పిన్‌ కోసం అడుగు"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"అన్‌పిన్ చేయడానికి ముందు అన్‌లాక్ నమూనా కోసం అడుగు"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"అన్‌పిన్ చేయడానికి ముందు పాస్‌వర్డ్ కోసం అడుగు"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"అనువర్తన పరిమాణాన్ని మార్చడం సాధ్యపడదు, రెండు వేళ్లతో దీన్ని స్క్రోల్ చేయండి."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"అనువర్తన పరిమాణాన్ని మార్చడం సాధ్యపడదు, రెండు వేళ్లతో దీన్ని స్క్రోల్ చేయండి."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"అనువర్తనంలో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"మీ నిర్వాహకులు ఇన్‌స్టాల్ చేసారు"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"మీ నిర్వాహకుడు నవీకరించారు"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"మీ నిర్వాహకులు తొలగించారు"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"ఇతరాలు"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"మీరు ఈ నోటిఫికేషన్‌ల ప్రాముఖ్యతను సెట్ చేసారు."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ఇందులో పేర్కొనబడిన వ్యక్తులను బట్టి ఇది చాలా ముఖ్యమైనది."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" కొత్త వినియోగదారుని జోడించడానికి ప్రయత్నిస్తోంది, కానీ ప్రస్తుతం ఇది నిషిద్ధం."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" కొత్త వినియోగదారుని జోడించడానికి ప్రయత్నిస్తోంది, కానీ వినియోగదారు పరిమితి చేరుకుంది."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" కొత్త వినియోగదారుని జోడించడానికి ప్రయత్నిస్తోంది, కానీ ఖాతా "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ఇప్పటికే ఈ పరికరంలో ఉంది. ఏదేమైనా కొనసాగించాలా?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ఖాతా "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" కోసం కొత్త వినియోగదారుని జోడించడానికి ప్రయత్నిస్తోంది. కొనసాగించాలా?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="ACCOUNT">%2$s</xliff:g>తో కొత్త వినియోగదారుని సృష్టించడానికి <xliff:g id="APP">%1$s</xliff:g>ని అనుమతించాలా ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="ACCOUNT">%2$s</xliff:g>తో (ఈ ఖాతాతో ఇప్పటికే ఒక వినియోగదారు ఉన్నారు) కొత్త వినియోగదారుని సృష్టించడానికి <xliff:g id="APP">%1$s</xliff:g>ని అనుమతించాలా?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"భాష ప్రాధాన్యత"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ప్రాంతం ప్రాధాన్యత"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"భాష పేరును టైప్ చేయండి"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"సూచించినవి"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"అన్ని భాషలు"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"శోధించు"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"కార్యాలయ మోడ్ ఆఫ్ చేయబడింది"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"అనువర్తనాలు, నేపథ్య సమకాలీకరణ మరియు సంబంధిత లక్షణాలతో సహా కార్యాలయ ప్రొఫైల్‌ను పని చేయడానికి అనుమతించండి."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"ఆన్ చేయి"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$sని నిలిపివేసారు"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$sని నిర్వాహకుడు నిలిపివేసారు. మరింత తెలుసుకోవడానికి వారిని సంప్రదించండి."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"మీకు కొత్త సందేశాలు ఉన్నాయి"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"వీక్షించడానికి SMS అనువర్తనాన్ని తెరవండి"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"కొన్ని విధులు ఉండకపోవచ్చు"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"కొనసాగడానికి తాకండి"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"వినియోగ. ప్రొఫైల్ లాక్ అయింది"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ఫైల్‌లను వీక్షించడానికి నొక్కండి"</string>
+    <string name="pin_target" msgid="3052256031352291362">"పిన్ చేయి"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"అన్‌‌పిన్‌ ‌చేయి"</string>
+    <string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index a759145..6aa3b8a 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"รายงานแบบอินเทอร์แอกทีฟ"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"ใช้ตัวเลือกนี้ได้เกือบทุกสถานการณ์ โดยจะอนุญาตให้คุณติดตามความคืบหน้าของรายงานและป้อนรายละเอียดเพิ่มเติมของปัญหา หัวข้อที่ใช้งานน้อยแต่ใช้เวลานานในการรายงานอาจถูกข้ามไป"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"รายงานฉบับเต็ม"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"ใช้ตัวเลือกนี้เพื่อให้มีการรบกวนระบบน้อยที่สุดเมื่ออุปกรณ์ของคุณไม่ตอบสนองหรือตอบสนองช้ามาก หรือเมื่อคุณต้องการทุกหัวข้อในรายงาน ตัวเลือกนี้จะไม่ถ่ายภาพหน้าจอหรืออนุญาตให้คุณป้อนรายละเอียดเพิ่มเติม"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">จะจับภาพหน้าจอสำหรับรายงานข้อบกพร่องใน <xliff:g id="NUMBER_1">%d</xliff:g> วินาที</item>
       <item quantity="one">จะจับภาพหน้าจอสำหรับรายงานข้อบกพร่องใน <xliff:g id="NUMBER_0">%d</xliff:g> วินาที</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"เนื้อหาถูกซ่อนไว้"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"มีการซ่อนเนื้อหาโดยนโยบาย"</string>
     <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ส่วนตัว"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"เลือกการทำงาน"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"เลือกแอปพลิเคชันสำหรับอุปกรณ์ USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"ไม่มีแอปพลิเคชันใดทำงานนี้ได้"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"ขออภัย <xliff:g id="APPLICATION">%1$s</xliff:g> หยุดการทำงานแล้ว"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"ขออภัย กระบวนการ <xliff:g id="PROCESS">%1$s</xliff:g> หยุดการทำงานแล้ว"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"เกิดข้อขัดข้องกับ Silence จากขั้นตอน <xliff:g id="PROCESS">%1$s</xliff:g> จนกว่าจะเริ่มต้นใหม่"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> หยุดทำงาน"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> หยุดทำงาน"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> หยุดทำงานอยู่เรื่อยๆ"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> หยุดทำงานอยู่เรื่อยๆ"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"เปิดแอปใหม่"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"รีเซ็ตแอปและเปิดใหม่"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"ส่งความคิดเห็น"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"ปิด"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"ปิด"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"รอ"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"ปิดแอป"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ไม่ตอบสนอง\n\nคุณต้องการปิดหรือไม่"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"กิจกรรม <xliff:g id="ACTIVITY">%1$s</xliff:g> ไม่ตอบสนอง\n\nคุณต้องการปิดหรือไม่"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ไม่ตอบสนอง คุณต้องการปิดหรือไม่"</string>
-    <string name="anr_process" msgid="6513209874880517125">"กระบวนการ <xliff:g id="PROCESS">%1$s</xliff:g> ไม่ตอบสนอง\n\nคุณต้องการปิดหรือไม่"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> ไม่ตอบสนอง"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ไม่ตอบสนอง"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> ไม่ตอบสนอง"</string>
+    <string name="anr_process" msgid="6156880875555921105">"กระบวนการ <xliff:g id="PROCESS">%1$s</xliff:g> ไม่ตอบสนอง"</string>
     <string name="force_close" msgid="8346072094521265605">"ตกลง"</string>
     <string name="report" msgid="4060218260984795706">"รายงาน"</string>
     <string name="wait" msgid="7147118217226317732">"รอ"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"เพิ่มซิมการ์ดแล้ว"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"รีสตาร์ทอุปกรณ์เพื่อเข้าถึงเครือข่ายมือถือ"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"รีสตาร์ท"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ตั้งเวลา"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ตั้งวันที่"</string>
     <string name="date_time_set" msgid="5777075614321087758">"ตั้งค่า"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ขอ PIN ก่อนเลิกตรึง"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ขอรูปแบบการปลดล็อกก่อนเลิกตรึง"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ขอรหัสผ่านก่อนเลิกตรึง"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"แอปไม่สามารถปรับขนาดได้ เลื่อนแอปด้วยนิ้ว 2 นิ้ว"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"แอปไม่สามารถปรับขนาดได้ เลื่อนแอปด้วยนิ้ว 2 นิ้ว"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"แอปไม่สนับสนุนการแยกหน้าจอ"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"ติดตั้งโดยผู้ดูแลระบบของคุณ"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"อัปเดตโดยผู้ดูแลระบบ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ลบโดยผู้ดูแลระบบของคุณ"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"เบ็ดเตล็ด"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"คุณตั้งค่าความสำคัญของการแจ้งเตือนเหล่านี้"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ข้อความนี้สำคัญเนื่องจากบุคคลที่เกี่ยวข้อง"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" กำลังพยายามเพิ่มผู้ใช้ใหม่ แต่ระบบไม่อนุญาตในขณะนี้"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" กำลังพยายามเพิ่มผู้ใช้ใหม่ แต่ถึงขีดจำกัดของผู้ใช้แล้ว"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" กำลังพยายามเพิ่มผู้ใช้ใหม่ แต่มีบัญชี "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" อยู่แล้วบนอุปกรณ์เครื่องนี้ ดำเนินการต่อไหม"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" กำลังพยายามเพิ่มผู้ใช้ใหม่สำหรับบัญชี "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" ดำเนินการต่อไหม"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"อนุญาตให้ <xliff:g id="APP">%1$s</xliff:g> สร้างผู้ใช้ใหม่ด้วย <xliff:g id="ACCOUNT">%2$s</xliff:g> ไหม"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"อนุญาตให้ <xliff:g id="APP">%1$s</xliff:g> สร้างผู้ใช้ใหม่ด้วย <xliff:g id="ACCOUNT">%2$s</xliff:g> (มีผู้ใช้ที่มีบัญชีนี้อยู่แล้ว) ไหม"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"ค่ากำหนดภาษา"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"ค่ากำหนดภูมิภาค"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"พิมพ์ชื่อภาษา"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"แนะนำ"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ทุกภาษา"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"ค้นหา"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"โหมดทำงานปิดอยู่"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"อนุญาตให้โปรไฟล์งานทำงานได้ ซึ่งรวมถึงแอป การซิงค์ในพื้นหลัง และคุณลักษณะอื่นที่เกี่ยวข้อง"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"เปิด"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"ปิดใช้ %1$s แล้ว"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"ผู้ดูแลระบบ %1$s ได้ปิดใช้แล้ว โปรดสอบถามข้อมูลเพิ่มเติมจากเขา"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"คุณมีข้อความใหม่"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"เปิดแอป SMS เพื่อดู"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"บางฟังก์ชันอาจไม่พร้อมใช้งาน"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"แตะเพื่อดำเนินการต่อ"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"โปรไฟล์ผู้ใช้ถูกล็อก"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"เชื่อมต่อ <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> แล้ว"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"แตะเพื่อดูไฟล์"</string>
+    <string name="pin_target" msgid="3052256031352291362">"ปักหมุด"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"เลิกปักหมุด"</string>
+    <string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index b5e1de8..9be3b2b 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interactive na ulat"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Gamitin ito sa karamihan ng sitwasyon. Nagbibigay-daan ito sa iyo na subaybayan ang pag-usad ng ulat at magbigay ng higit pang mga detalye tungkol sa problema. Maaari itong mag-alis ng ilan sa mga hindi masyadong ginagamit na seksyon na nangangailangan ng mahabang panahon upang iulat."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Buong ulat"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Gamitin ang opsyong ito para sa kaunting pagkaantala sa system kapag hindi tumutugon o masyadong mabagal ang iyong device, o kapag kailangan mo ang lahat ng seksyon ng ulat. Hindi ito kukuha ng screenshot o magbibigay-daan sa iyo na maglagay ng higit pang mga detalye."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Kukuha ng screenshot para sa ulat ng bug sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> segundo.</item>
       <item quantity="other">Kukuha ng screenshot para sa ulat ng bug sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> na segundo.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Nakatago ang mga content"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Itinago ang mga content alinsunod sa patakaran"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Pumili ng pagkilos"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Pumili ng isang app para sa USB device"</string>
     <string name="noApplications" msgid="2991814273936504689">"Walang apps ang makakapagsagawa ng pagkilos na ito."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Sa kasamaang palad, huminto ang <xliff:g id="APPLICATION">%1$s</xliff:g>."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Sa kasamaang palad, nahinto ang prosesong <xliff:g id="PROCESS">%1$s</xliff:g>."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Nag-crash ang Silence mula sa <xliff:g id="PROCESS">%1$s</xliff:g> hanggang sa pag-reboot."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Huminto ang <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Huminto ang <xliff:g id="PROCESS">%1$s</xliff:g>"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"Paulit-ulit na humihinto ang <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Paulit-ulit na humihinto ang <xliff:g id="PROCESS">%1$s</xliff:g>"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"I-restart ang app"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"I-reset at i-restart ang app"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Magpadala ng feedback"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Isara"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"I-mute"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Maghintay"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Isara ang app"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Hindi tumutugon ang <xliff:g id="APPLICATION">%2$s</xliff:g>.\n\nNais mo ba itong isara?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Hindi tumutugon ang aktibidad na <xliff:g id="ACTIVITY">%1$s</xliff:g>.\n\nNais mo ba itong isara?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Hindi tumutugon ang <xliff:g id="APPLICATION">%1$s</xliff:g>. Nais mo ba itong isara?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Hindi tumutugon ang prosesong <xliff:g id="PROCESS">%1$s</xliff:g>.\n\nNais mo ba itong isara?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"Hindi tumutugon ang <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"Hindi tumutugon ang <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"Hindi tumutugon ang <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Hindi tumutugon ang prosesong <xliff:g id="PROCESS">%1$s</xliff:g>"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Ulat"</string>
     <string name="wait" msgid="7147118217226317732">"Maghintay"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Idinagdag ang SIM card"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"I-restart ang iyong device upang ma-access ang cellular network."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"I-restart"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Magtakda ng oras"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Itakda ang petsa"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Itakda"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Humingi ng PIN bago mag-unpin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Humingi ng pattern sa pag-unlock bago mag-unpin"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Humingi ng password bago mag-unpin"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Hindi nare-resize ang app, mag-scroll dito gamit ang dalawang daliri."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Hindi nare-resize ang app, mag-scroll dito gamit ang dalawang daliri."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Hindi sinusuportahan ng app ang split-screen."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Na-install ng iyong administrator"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Na-update ng iyong administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Na-delete ng iyong administrator"</string>
@@ -1527,14 +1545,29 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Iba Pa"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Ikaw ang magtatakda ng kahalagahan ng mga notification na ito."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Mahalaga ito dahil sa mga taong kasangkot."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315">"Sinusubukan ng "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" na magdagdag ng bagong user, ngunit kasalukuyan itong ipinagbabawal."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266">"Sinusubukan ng "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" na magdagdag ng bagong user, ngunit naabot na ang limitasyon sa user."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789">"Sinusubukan ng "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" na magdagdag ng bagong user, ngunit nasa device na ito na ang account na "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Magpatuloy pa rin?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392">"Sinusubukan ng "<b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" na magdagdag ng bagong user para sa account na "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Magpatuloy?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Payagan ang <xliff:g id="APP">%1$s</xliff:g> na gumawa ng bagong User sa <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Payagan ang <xliff:g id="APP">%1$s</xliff:g> na gumawa ng bagong User sa <xliff:g id="ACCOUNT">%2$s</xliff:g> (mayroon nang User sa account na ito) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Kagustuhan sa wika"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Kagustuhan sa rehiyon"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"I-type ang wika"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Iminumungkahi"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Lahat ng wika"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Maghanap"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"NAKA-OFF ang work mode"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Payagang gumana ang profile sa trabaho, kasama na ang mga app, pag-sync sa background at mga may kaugnayang feature."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"I-on"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"Na-disable ang %1$s"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Na-disable ng administrator ng %1$s. Makipag-ugnayan sa administrator upang matuto nang higit pa."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Mayroon kang mga bagong mensahe"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Buksan ang SMS app upang tingnan"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Maaaring hindi available ang ilang function"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Pindutin upang magpatuloy"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Naka-lock ang profile ng user"</string>
+    <!-- no translation found for usb_mtp_launch_notification_title (8359219638312208932) -->
+    <skip />
+    <!-- no translation found for usb_mtp_launch_notification_description (8541876176425411358) -->
+    <skip />
+    <string name="pin_target" msgid="3052256031352291362">"I-pin"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"I-unpin"</string>
+    <string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 79a5c54..60e1b89 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Etkileşimli rapor"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Çoğu durumda bunu kullanın. Bu seçenek, raporun ilerleme durumunu takip etmenize ve sorunla ilgili daha fazla ayrıntı girmenize olanak sağlar. Rapor edilmesi uzun süren ve az kullanılan bazı bölümleri yok sayabilir."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Tam rapor"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Cihazınız yanıt vermediğinde veya çok yavaş çalıştığında ya da tüm rapor bölümlerine ihtiyacınız olduğunda, sistemle minimum etkileşim için bu seçeneği kullanın. Bu seçenekte ekran görüntüsü alınmaz veya daha fazla ayrıntı girmenize izin verilmez."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> saniye içinde hata raporu ekran görüntüsü alınıyor.</item>
       <item quantity="one">Hata raporu ekran görüntüsü <xliff:g id="NUMBER_0">%d</xliff:g> saniye içinde alınacak.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"İçerik gizlendi"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"İçerikler politika nedeniyle gizlendi"</string>
     <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Kişisel"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"İşlem seçin"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB cihazı için bir uygulama seçin"</string>
     <string name="noApplications" msgid="2991814273936504689">"Bu eylemi hiçbir uygulama gerçekleştiremez."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Maalesef <xliff:g id="APPLICATION">%1$s</xliff:g> durdu."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Maalesef <xliff:g id="PROCESS">%1$s</xliff:g> işlemi durdu."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Yeniden başlatılana kadar <xliff:g id="PROCESS">%1$s</xliff:g> kilitlenmelerini yoksay."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> durdu"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> durdu"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> sürekli olarak duruyor"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> sürekli olarak duruyor"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Uygulamayı yeniden başlat"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Uygulamayı sıfırla ve yeniden başlat"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Geri bildirim gönder"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Kapat"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Yok say"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Bekle"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Uygulamayı kapat"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> yanıt vermiyor.\n\nKapatmak ister misiniz?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> yanıt vermiyor.\n\nKapatmak ister misiniz?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> yanıt vermiyor. Kapatmak ister misiniz?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> işlemi yanıt vermiyor.\n\nKapatmak ister misiniz?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> yanıt vermiyor"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> yanıt vermiyor"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> yanıt vermiyor"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> işlemi yanıt vermiyor"</string>
     <string name="force_close" msgid="8346072094521265605">"Tamam"</string>
     <string name="report" msgid="4060218260984795706">"Bildir"</string>
     <string name="wait" msgid="7147118217226317732">"Bekle"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM kart eklendi"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Hücresel ağa erişmek için cihazınızı yeniden başlatın."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Yeniden başlat"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Saati ayarlayın"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarihi ayarlayın"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ayarla"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Sabitlemeyi kaldırmadan önce PIN\'i sor"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sabitlemeyi kaldırmadan önce kilit açma desenini sor"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Uygulama yeniden boyutlandırılamaz. İki parmağınızla kaydırın."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Uygulama yeniden boyutlandırılamaz. İki parmağınızla kaydırın."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Uygulama bölünmüş ekranı desteklemiyor."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Yöneticiniz tarafından yüklendi"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Yöneticiniz tarafından güncellendi"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Yöneticiniz tarafından silindi"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Çeşitli"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Bu bildirimlerin önem derecesini ayarladınız."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Bu, dahil olan kişiler nedeniyle önemlidir."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>", yeni bir kullanıcı eklemeye çalışıyor, ancak şu anda bunu yapmak için izni yok."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>", yeni bir kullanıcı eklemeye çalışıyor, ancak kullanıcı sınırına ulaşıldı."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>", yeni bir kullanıcı eklemeye çalışıyor, ancak "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" hesabı bu cihazda zaten var. Yine de devam edilsin mi?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>", "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" hesabı için yeni bir kullanıcı eklemeye çalışıyor. Devam edilsin mi?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> uygulamasının <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabına sahip yeni bir Kullanıcı eklemesine izin verilsin mi?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> uygulamasının <xliff:g id="ACCOUNT">%2$s</xliff:g> hesabına sahip yeni bir Kullanıcı eklemesine izin verilsin mi (bu hesaba sahip bir kullanıcı zaten var)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Dil tercihi"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Bölge tercihi"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Dil adını yazın"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Önerilen"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Tüm diller"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Ara"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"İş modu KAPALI"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Uygulamalar, arka planda senkronizasyon ve ilgili özellikler dahil olmak üzere iş profilinin çalışmasına izin ver."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Aç"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s devre dışı bırakıldı"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s yöneticisi tarafından devre dışı bırakıldı. Daha fazla bilgi edinmek için kendileriyle iletişime geçin."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Yeni mesajlarınız var"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Görüntülemek için SMS uygulamasını açın"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Bazı işlevler kullanılamayabilir"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Devam etmek için dokunun"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Kullanıcı profili kilitli"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> cihazına bağlandı"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Dosyaları görüntülemek için hafifçe dokunun"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Sabitle"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Sabitlemeyi kaldır"</string>
+    <string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f4ba226..3eb3fd8 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -216,8 +216,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Інтерактивний звіт"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Підходить для більшості випадків. Можна відстежувати, як створюється звіт, і вводити більше деталей про проблему. Можуть опускатися деякі розділи, які рідко використовуються, але довго створюються."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Повний звіт"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Підходить для мінімального втручання в систему, коли пристрій не відповідає, працює повільно або вам потрібні всі розділи звіту. Не можна робити знімки екрана та вводити більше деталей."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Знімок екрана для звіту про помилки буде зроблено через <xliff:g id="NUMBER_1">%d</xliff:g> секунду.</item>
       <item quantity="few">Знімок екрана для звіту про помилки буде зроблено через <xliff:g id="NUMBER_1">%d</xliff:g> секунди.</item>
@@ -237,6 +236,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Вміст сховано"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Вміст сховано згідно з правилом"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Особисті дані"</string>
@@ -921,15 +921,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Виберіть дію"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Вибрати програму для пристрою USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Жодна програма не може виконати цю дію."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"На жаль, програма <xliff:g id="APPLICATION">%1$s</xliff:g> припинила роботу."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"На жаль, програма <xliff:g id="PROCESS">%1$s</xliff:g> припинила роботу."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Не показувати інформацію про збої додатка <xliff:g id="PROCESS">%1$s</xliff:g> до перезавантаження."</string>
+    <string name="aerr_application" msgid="250320989337856518">"Додаток <xliff:g id="APPLICATION">%1$s</xliff:g> перестав працювати"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> перестав працювати"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"Додаток <xliff:g id="APPLICATION">%1$s</xliff:g> періодично перестає працювати"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"Процес \"<xliff:g id="PROCESS">%1$s</xliff:g>\" періодично перестає працювати"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Перезапустити додаток"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Скинути та перезапустити додаток"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Надіслати відгук"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Закрити"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Вимкнути звук"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Чекати"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Закрити додаток"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"Програма <xliff:g id="APPLICATION">%2$s</xliff:g> не відповідає.\n\nЗакрити її?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Дія <xliff:g id="ACTIVITY">%1$s</xliff:g> не відповідає.\n\nЗакінчити її?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"Програма <xliff:g id="APPLICATION">%1$s</xliff:g> не відповідає. Закрити її?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> не відповідає.\n\nЗавершити його?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"Додаток <xliff:g id="APPLICATION">%2$s</xliff:g> не відповідає"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"Дія \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\" не відповідає"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"Додаток <xliff:g id="APPLICATION">%1$s</xliff:g> не відповідає"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Процес \"<xliff:g id="PROCESS">%1$s</xliff:g>\" не відповідає"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Відгук"</string>
     <string name="wait" msgid="7147118217226317732">"Чекати"</string>
@@ -1040,6 +1047,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-карту додано"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Щоб з’єднатися з мобільною мережею, перезавантажте пристрій."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Перезапуск"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Щоб ваша нова SIM-карта працювала правильно, установіть і відкрийте додаток від оператора."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ЗАВАНТАЖИТИ ДОДАТОК"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"НЕ ЗАРАЗ"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Вставлено нову SIM-карту"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Торкніться, щоб налаштувати"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Установити час"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Установити дату"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Застосувати"</string>
@@ -1475,7 +1487,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"PIN-код для відкріплення"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Запитувати ключ розблокування перед відкріпленням"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитувати пароль перед відкріпленням"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Розмір додатка не можна змінити. Прокручуйте його двома пальцями."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Розмір додатка не можна змінити. Прокручуйте його двома пальцями."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Додаток не підтримує розділення екрана."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Установив адміністратор"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Оновлено адміністратором"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Видалив адміністратор"</string>
@@ -1565,14 +1578,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Інше"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Ви вказуєте пріоритет цих сповіщень."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Важливе з огляду на учасників."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" хоче додати нового користувача, але зараз це заборонено."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" хоче додати нового користувача, але вже додано максимальну кількість користувачів."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" хоче додати нового користувача, але обліковий запис "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" уже існує на цьому пристрої. Продовжити?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" хоче додати нового користувача облікового запису "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Продовжити?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> створити нового користувача з обліковим записом <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> створити нового користувача з обліковим записом <xliff:g id="ACCOUNT">%2$s</xliff:g> (користувач із таким обліковим записом уже існує)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Вибір мови"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Вибір регіону"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Введіть назву мови"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Пропозиції"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Усі мови"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Пошук"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Робочий профіль ВИМКНЕНО"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Увімкнути робочий профіль, зокрема додатки, фонову синхронізацію та пов’язані функції."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Увімкнути"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s вимкнено"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Вимкнув адміністратор %1$s. Зв’яжіться з ним, щоб дізнатися більше."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"У вас є нові повідомлення"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Щоб переглянути, відкрийте додаток для SMS"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Деякі функції можуть бути недоступні"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Торкніться, щоб продовжити"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Профіль користувача блокується"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Під’єднано до пристрою <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Торкніться, щоб переглянути файли"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Закріпити"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Відкріпити"</string>
+    <string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
 </resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index bf2f989..7b32a3c 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"متعامل رپورٹ"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"زیادہ تر حالات میں اسے استعمال کریں۔ یہ آپ کو رپورٹ کی پیش رفت ٹریک کرنے اور مسئلہ سے متعلق زیادہ تفصیلات میں جانے کی اجازت دیتا ہے۔ شاید یہ کچھ ایسے کم استعمال ہونے والے سیکشنز کو خارج کر دے جو رپورٹ کرنے میں زیادہ وقت لگاتے ہیں۔"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"مکمل رپورٹ"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"جب آپ کا آلہ غیر فعال یا بہت سست ہو یا جب آپ کو تمام رپورٹ سیکشنز درکار ہوں، تو کم سے کم مداخلت کیلئے یہ اختیار استعمال کریں۔ یہ اسکرین شاٹ نہیں لیتا یا آپ کو مزید تفصیلات میں جانے کی اجازت نہیں دیتا۔"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">بگ رپورٹ کیلئے <xliff:g id="NUMBER_1">%d</xliff:g> سیکنڈز میں اسکرین شاٹ لیا جائے گا۔</item>
       <item quantity="one">بگ رپورٹ کیلئے <xliff:g id="NUMBER_0">%d</xliff:g> سیکنڈ میں اسکرین شاٹ لیا جائے گا۔</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"‎999+‎"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"مواد مخفی ہیں"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"مواد پالیسی کے تحت مخفی ہے"</string>
     <string name="safeMode" msgid="2788228061547930246">"حفاظتی وضع"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏Android سسٹم"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ذاتی"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"ایک کارروائی منتخب کریں"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"‏USB آلہ کیلئے ایک ایپ منتخب کریں"</string>
     <string name="noApplications" msgid="2991814273936504689">"کوئی ایپس یہ کارروائی نہیں کر سکتی ہیں۔"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"بدقسمتی سے، <xliff:g id="APPLICATION">%1$s</xliff:g> بند ہو گیا۔"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"بدقسمتی سے، کارروائی <xliff:g id="PROCESS">%1$s</xliff:g> بند ہو گئی۔"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"<xliff:g id="PROCESS">%1$s</xliff:g> سے کریشز کو اس وقت تک خاموش کریں جب تک ریبوٹ نہیں ہو جاتا۔"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> بند ہو گئی ہے"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> بند ہو گیا ہے"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> بار بار بند ہوتی ہے"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> بار بار بند ہوتی ہے"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"ایپ دوبارہ شروع کریں"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"ایپ کو دوبارہ ترتیب دیں اور دوبارہ شروع کریں"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"تاثرات بھیجیں"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"بند کریں"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"خاموش کریں"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"انتظار کریں"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"ایپ بند کریں"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> جواب نہیں دے رہی ہے۔ \n\nکیا آپ اسے بند کرنا چاہتے ہیں؟"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"سرگرمی <xliff:g id="ACTIVITY">%1$s</xliff:g> جواب نہیں دے رہی ہے۔ \n\nکیا آپ اسے بند کرنا چاہتے ہیں؟"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> جواب نہیں دے رہی ہے۔ کیا آپ اسے بند کرنا چاہتے ہیں؟"</string>
-    <string name="anr_process" msgid="6513209874880517125">"کارروائی <xliff:g id="PROCESS">%1$s</xliff:g> جواب نہیں دے رہی ہے۔ \n\n کیا آپ اسے بند کرنا چاہتے ہیں؟"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> جواب نہیں دے رہی ہے"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> جواب نہیں دے رہی ہے"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> جواب نہیں دے رہی ہے"</string>
+    <string name="anr_process" msgid="6156880875555921105">"کارروائی <xliff:g id="PROCESS">%1$s</xliff:g> جواب نہیں دے رہی ہے"</string>
     <string name="force_close" msgid="8346072094521265605">"ٹھیک ہے"</string>
     <string name="report" msgid="4060218260984795706">"اطلاع دیں"</string>
     <string name="wait" msgid="7147118217226317732">"انتظار کریں"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"‏SIM شامل کیا گیا"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"سیلولر نیٹ ورک تک رسائی کیلئے اپنا آلہ دوبارہ سٹارٹ کریں۔"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"دوبارہ شروع کریں"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"وقت سیٹ کریں"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تاریخ سیٹ کریں"</string>
     <string name="date_time_set" msgid="5777075614321087758">"سیٹ کریں"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"‏پن ہٹانے سے پہلے PIN طلب کریں"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"پن ہٹانے سے پہلے غیر مقفل کرنے کا پیٹرن طلب کریں"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"ایپ ری سائز ایبل نہیں ہے، اسے دو انگلیوں کے ساتھ سکرول کریں۔"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"ایپ ری سائز ایبل نہیں ہے، اسے دو انگلیوں کے ساتھ سکرول کریں۔"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ایپ سپلٹ اسکرین کو سپورٹ نہیں کرتی۔"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"آپ کے منتظم کی جانب سے انسٹال کر دیا گیا"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"آپ کے منتظم نے اپ ڈيٹ کر دیا"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"آپ کے منتظم کی جانب سے حذف کر دیا گیا"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"متفرقات"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"ان اطلاعات کی اہمیت آپ مقرر کرتے ہیں۔"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"اس میں موجود لوگوں کی وجہ سے یہ اہم ہے۔"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ایک نیا صارف شامل کرنے کی کوشش کر رہی ہے مگر فی الحال ممنوع ہے۔"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ایک نیا صارف شامل کرنے کی کوشش کر رہی ہے، لیکن صارف کی حد پوری ہوگئی ہے۔"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ایک نیا صارف شامل کرنے کی کوشش کر رہی ہے لیکن اکاؤنٹ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" پہلے سے اس آلہ پر موجود ہے۔ بہر صورت آگے بڑھیں؟"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" اکاؤنٹ "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" کیلئے ایک نیا صارف شامل کرنے کی کوشش کر رہی ہے۔ آگے بڑھیں؟"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> کو <xliff:g id="ACCOUNT">%2$s</xliff:g> کے ساتھ ایک نیا صارف بنانے کی اجازت دیں؟"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> کو <xliff:g id="ACCOUNT">%2$s</xliff:g> کے ساتھ ایک نیا صارف بنانے کی اجازت دیں (اس اکاؤنٹ کے ساتھ ایک صارف پہلے سے موجود ہے) ؟"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"زبان کی ترجیح"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"علاقہ کی ترجیح"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"زبان کا نام ٹائپ کریں"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"تجویز کردہ"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"سبھی زبانیں"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"تلاش"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"کام موڈ آف ہے"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"دفتری پروفائل کو کام کرنے دیں، بشمول ایپس، پس منظر کی مطابقت پذیری اور متعلقہ خصوصیات۔"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"آن کریں"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"‏%1$s غیر فعال کردہ"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"‏%1$s منتظم کی جانب سے غیر فعال کر دیا گیا۔ مزید جاننے کیلئے ان سے رابطہ کریں۔"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"آپ کے پاس نئے پیغامات ہیں"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"‏دیکھنے کیلئے SMS ایپ کھولیں"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"ممکن ہے کچھ فنکشز دستیاب نہ ہوں"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"جاری رکھنے کیلئے تھپتھپائیں"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"صارف پروفائل مقفل ہو گئی"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> سے منسلک"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"فائلوں کو دیکھنے کیلئے تھپتھپائیں"</string>
+    <string name="pin_target" msgid="3052256031352291362">"پن کریں"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"پن ہٹائیں"</string>
+    <string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
 </resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index a33a283..d69df04 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktiv hisobot"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Bundan maxsus vaziyatlarda foydalaning. Bu hisobot jarayonini kuzatish imkonini beradi va muammo haqida batafsil ma’lumotlarni ko‘rishingiz mumkin bo‘ladi. Hisobot uchun ko‘p vaqt oladigan kam ishlatiladigan bo‘limlar qoldirib ketilishi mumkin."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"To‘liq hisobot"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Qurilma javob bermaganda, juda sekinlashganda yoki barcha hisobot bo‘limlari zarur bo‘lganda kamroq tizim aralashuvlarisiz mazkur variantdan foydalaning. Skrinshot olinmaydi yoki batafsil ma’lumotlar ko‘rishingizga ruxsat berilmaydi."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Xatoliklar hisoboti uchun skrinshot <xliff:g id="NUMBER_1">%d</xliff:g> soniyadan so‘ng olinadi.</item>
       <item quantity="one">Xatoliklar hisoboti uchun skrinshot <xliff:g id="NUMBER_0">%d</xliff:g> soniyadan so‘ng olinadi.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Kontent yashirildi"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Qoidaga muvofiq kontent yashirilgan"</string>
     <string name="safeMode" msgid="2788228061547930246">"Xavfsiz usul"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android tizimi"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Shaxsiy"</string>
@@ -313,7 +313,7 @@
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Ilovaga o‘zining komponentlarini xotirada doimiy saqlashga ruxsat beradi. Bu mavjud xotirani cheklashi va telefonni sekin ishlashiga sabab bo‘lishi mumkin."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"ilovalar egallagan xotira joyini hisoblash"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Ilova o‘zining kodi, ma’lumotlari va kesh o‘lchami to‘g‘risidagi ma’lumotlarni olishi mumkin"</string>
-    <string name="permlab_writeSettings" msgid="2226195290955224730">"tizim moslamalarini o‘zgartirish"</string>
+    <string name="permlab_writeSettings" msgid="2226195290955224730">"tizim sozlamalarini o‘zgartirish"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"Ilova tizim sozlamalarini o‘zgartirishi mumkin. Zararli dasturlar uning yordamida tizimni ishdan chiqarishi mumkin."</string>
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"tizim ishga tushganda bajarish"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Ilova tizim qayta yoqilganidan so‘ng o‘zini ishga tushirishi mumkin. Bu planshetning yonish vaqtini uzaytirishi va doimiy ishlab turivchi ilova tufayli uning tezkor ishlashini kamaytirishi mumkin."</string>
@@ -351,7 +351,7 @@
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Ilovaga telefoningizda o‘zgartirishingiz mumkin bo‘lgan, shuningdek, do‘stlaringiz va hamkasblaringizning tadbirlarini qo‘shish, o‘chirish va o‘zgartirish uchun ruxsat beradi. Bu ilovaga go‘yoki taqvim egalari nomidan kelgan xabarlarni jo‘natishga yoki egasiga bildirmasdan tadbirlarni o‘zgartirishga ruxsat berishi mumkin."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"qo‘shimcha manzillarga kirish buyruqlari"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ilovaga qo‘shimcha joylashuv xizmati buyruqlaridan foydalanishga ruxsat beradi. Uning yordamida ilova GPS yoki boshqa joylashuv ma’lumoti manbalarining ishlashiga xalaqit qilishi mumkin."</string>
-    <string name="permlab_accessFineLocation" msgid="251034415460950944">"aniq joylashuv (GPS va tarmoqqa asoslanib) ma’lumotlaridan foydalanishga ruxsat"</string>
+    <string name="permlab_accessFineLocation" msgid="251034415460950944">"aniq joylashuv ma’lumotiga kirish (GPS va tarmoq asosida)"</string>
     <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Ilovaga global joylashuvni aniqlash tizimi (GPS) yoki Wi-Fi va uyali tarmoq antennalari kabi tarmoq joylashuv manbalaridan foydalanib, aniq joylashuvingizni topishga ruxsat beradi. Ushbu joylashuv xizmatlari yoqib qo‘yilgan bo‘lishi va qurilmangizdagi ilovaga ulardan foydalanish uchun mavjud bo‘lishi kerak. Ilovalar bundan foydalanib, sizning joylashuvingizni aniqlaydi. Bu batareya quvvatini ko‘proq sarflaydi."</string>
     <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"taxminiy joylashuv (tarmoq asosida) ma’lumotlaridan foydalanishga ruxsat"</string>
     <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Ilovaga sizning taxminiy joylashuvingizni topishga ruxsat beradi. Ushbu joylashuv Wi-Fi va uyali tarmoq antennalari kabi tarmoq joylashuv manbalaridan foydlanuvchi joylashuv xizmatlari orqali aniqlanadi. Ushbu joylashuv xizmatlari yoqib qo‘yilgan bo‘lishi va qurilmangizdagi ilovaga ulardan foydalanish uchun mavjud bo‘lishi kerak. Ilovalar bundan foydalanib, sizning taxminiy joylashuvingizni aniqlaydi."</string>
@@ -389,7 +389,7 @@
     <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"Iloba planshetdagi vaqt zonasini o‘zgartirishi mumkin."</string>
     <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"Ilovaga televizorning vaqt zonasini o‘zgartirish huquqini beradi."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Ilova telefondagi vaqt zonasini o‘zgartirishi mumkin."</string>
-    <string name="permlab_getAccounts" msgid="1086795467760122114">"qurilmadagi hisoblarni topish"</string>
+    <string name="permlab_getAccounts" msgid="1086795467760122114">"qurilmadagi hisoblarni qidirish"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Ilovaga planshetdagi hisoblar ro‘yxatini olishga ruxsat beradi. Bunga siz o‘rnatgan ilovalar tomonidan yaratilgan har qanday hisoblar kirishi mumkin."</string>
     <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Ilovaga televizor tomonidan aniqlangan hisoblar ro‘yxatini olish huquqini beradi. Bunga siz o‘rnatgan ilovalar tomonidan yaratilgan har qanday hisoblar kiradi."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Ilovaga telefondagi hisoblar ro‘yxatini olishga ruxsat beradi. Bunga siz o‘rnatgan ilovalar tomonidan yaratilgan har qanday hisoblar kirishi mumkin."</string>
@@ -454,7 +454,7 @@
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Ilovaga hisobning sinxronlash sozlamalarini o‘zgartirish uchun ruxsat beradi. Masalan, bundan \"Odamlar\" ilovasini hisob bilan sinxronlanlash uchun foydalanish mumkin."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"sinxronlash statistikasini o‘qish"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Ilovaga hisobning sinxronlash statistikasini, shu jumladan, sinxronlangan hodisalar tarixi va qancha ma’lumot sinxronlanganligi haqidagi ma’lumotni o‘qishga ruxsat beradi."</string>
-    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"USB xotirasi tarkibidagilarni o‘qish"</string>
+    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"USB xotiradagi ma’lumotlarni ko‘rish"</string>
     <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"SD xotira kartasi tarkibidagilarni o‘qish"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"Dasturga USB xotiradagi ma’lumotlarini ko‘rib chiqish uchun ruxsat beradi."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"Dasturga SD kartadagi ma’lumotlarni ko‘rib chiqishga ruxsat berish."</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Amalni tanlash"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB qurilma uchun ilovani tanlang"</string>
     <string name="noApplications" msgid="2991814273936504689">"Hech qaysi ilova ushbu amalni bajara olmaydi."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Baxtga qarshi, <xliff:g id="APPLICATION">%1$s</xliff:g> to‘xtatildi."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Baxtga qarshi, <xliff:g id="PROCESS">%1$s</xliff:g> jarayoni to‘xtatildi."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"<xliff:g id="PROCESS">%1$s</xliff:g>: ilova ishlashdan to‘xtadi, qurilmani o‘chirib yoqing."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasi ishdan chiqdi"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> jarayoni ishdan chiqdi"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> yana ishdan chiqdi"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> yana ishdan chiqdi"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Ilovani qayta ishga tushirish"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Ilovani qayta tiklash va qayta ishga tushirish"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Fikr-mulohaza yuborish"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Yopish"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"E’tiborsiz qoldirish"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Kuting"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Ilovani yopish"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> javob bermayapti.\n\nUni yopishni xohlaysizmi?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> harakati javob bermayapti.\n\nUni yopishni xohlaysizmi?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> javob bermayapti. Uni yopishni xohlaysizmi?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> jarayoni javob bermayapti.\n\nUni yopishni xohlaysizmi?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> javob bermayapti"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> javob bermayapti"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> javob bermayapti"</string>
+    <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> ilovasi javob bermayapti"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Xabar berish"</string>
     <string name="wait" msgid="7147118217226317732">"Kuting"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM karta qo‘shildi"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Mobil tarmoqqa ulanish uchun qurilmangizni o‘chirib yoqing."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"O‘chirib-yoqish"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Vaqtni o‘rnatish"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Sanani kiritish"</string>
     <string name="date_time_set" msgid="5777075614321087758">"O‘rnatish"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Yechishda PIN-kod so‘ralsin"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bo‘shatishdan oldin chizmali parol so‘ralsin"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bo‘shatishdan oldin parol so‘ralsin"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Oyna o‘lchamini o‘zgartirib bo‘lmaydi. Sahifani ikkita barmoq bilan aylantiring."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Oyna o‘lchamini o‘zgartirib bo‘lmaydi. Sahifani ikkita barmoq bilan aylantiring."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Bu ilova ekranni bo‘lish xususiyatini qo‘llab-quvvatlamaydi."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Administratoringiz tomonidan o‘rnatilgan"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Administratoringiz tomonidan yangilandi"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratoringiz tomonidan o‘chirilgan"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Boshqa belgilar"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Siz ushbu bildirishnomalarning muhimligini belgilagansiz."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Bu odamlar siz uchun muhim."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ilovasi yangi foydalanuvchi qo‘shishga urinmoqda, lekin hozirda taqiqlangan."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ilovasi yangi foydalanuvchi qo‘shishga urinmqoda, lekin ortiq foydalanuvchi qo‘shib bo‘lmaydi."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ilovasi yangi foydalanuvchi qo‘shishga urinmoqda, lekin "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" hisobi allaqachon qurilmada mavjud. Baribir davom etilsinmi?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" ilovasi "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" hisobi uchun yangi foydalanuvchi qo‘shishga urinmoqda. Davom etilsinmi?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> ilovasiga <xliff:g id="ACCOUNT">%2$s</xliff:g> hisobi bilan yangi foydalanuvchi yaratishiga ruxsat berilsinmi ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> ilovasiga <xliff:g id="ACCOUNT">%2$s</xliff:g> hisobi bilan yangi foydalanuvchi yaratishiga ruxsat berilsinmi (bunday hisobdagi foydalanuvchi allaqachon mavjud) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Til sozlamalari"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Hudud sozlamalari"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Til nomini kiriting"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Taklif etiladi"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Barcha tillar"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Qidiruv"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Ish rejimi O‘CHIQ"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Ishchi profilini yoqish: ilovalar, fonda sinxronlash va bog‘liq funksiyalar."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Yoqish"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s o‘chirilgan"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s administratori tomonidan o‘chirilgan. Batafsil ma’lumot uchun bog‘laning."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Sizga yangi SMS keldi"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Ko‘rish uchun SMS ilovasini oching"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Ayrim funksiyalar mavjud bo‘lmasligi mumkin"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Davom etish uchun bosing"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Foydalanuvchi profili yopiq"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> mahsulotiga ulandi"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Fayllarni ko‘rish uchun bosing"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Qadash"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Olib tashlash"</string>
+    <string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 56af67d..bbfef63 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Báo cáo tương tác"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Sử dụng tùy chọn này trong hầu hết các trường hợp. Tùy chọn này cho phép bạn theo dõi tiến trình của báo cáo và nhập thêm thông tin chi tiết về sự cố. Tùy chọn này có thể bỏ qua một số phần ít được sử dụng mà mất nhiều thời gian để báo cáo."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Báo cáo đầy đủ"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Sử dụng tùy chọn này để giảm thiểu ảnh hưởng của hệ thống khi thiết bị của bạn không phản hồi hoặc quá chậm hoặc khi bạn cần tất cả các phần báo cáo. Không chụp ảnh màn hình hoặc cho phép bạn nhập thêm thông tin chi tiết."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">Sẽ chụp ảnh màn hình để báo cáo lỗi sau <xliff:g id="NUMBER_1">%d</xliff:g> giây.</item>
       <item quantity="one">Sẽ chụp ảnh màn hình để báo cáo lỗi sau <xliff:g id="NUMBER_0">%d</xliff:g> giây.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Nội dung bị ẩn"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Nội dung bị ẩn theo chính sách"</string>
     <string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Cá nhân"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Chọn một tác vụ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Chọn ứng dụng cho thiết bị USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Không ứng dụng nào có thể thực hiện tác vụ này."</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Rất tiếc, <xliff:g id="APPLICATION">%1$s</xliff:g> đã dừng lại."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Rất tiếc, quá trình <xliff:g id="PROCESS">%1$s</xliff:g> đã dừng lại."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Chế độ Im lặng gặp sự cố từ <xliff:g id="PROCESS">%1$s</xliff:g> cho tới khi khởi động lại."</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> đã dừng"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> đã dừng"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> tiếp tục dừng"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> tiếp tục dừng"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Khởi động lại ứng dụng"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Đặt lại và khởi động lại ứng dụng"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Gửi phản hồi"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Đóng"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Bỏ qua"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Đợi"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Đóng ứng dụng"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> hiện không phản hồi.\n\nBạn có muốn đóng ứng dụng này không?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Hoạt động <xliff:g id="ACTIVITY">%1$s</xliff:g> không phản hồi.\n\nBạn có muốn đóng ứng dụng này không?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> hiện không phản hồi. Bạn có muốn đóng ứng dụng không?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Quá trình <xliff:g id="PROCESS">%1$s</xliff:g> hiện không phản hồi.\n\nBạn có muốn đóng ứng dụng này không?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g> không phản hồi"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g> không phản hồi"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> không phản hồi"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Quá trình <xliff:g id="PROCESS">%1$s</xliff:g> không phản hồi"</string>
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Báo cáo"</string>
     <string name="wait" msgid="7147118217226317732">"Đợi"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Đã thêm thẻ SIM"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Khởi động lại thiết bị của bạn để truy cập mạng di động."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Khởi động lại"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Đặt giờ"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Đặt ngày"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Đặt"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Hỏi mã PIN trước khi bỏ ghim"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Hỏi hình mở khóa trước khi bỏ ghim"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Hỏi mật khẩu trước khi bỏ ghim"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Ứng dụng không đổi kích thước được, hãy cuộn ứng dụng bằng hai ngón tay."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Ứng dụng không đổi kích thước được, hãy cuộn ứng dụng bằng hai ngón tay."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Ứng dụng không hỗ trợ chia đôi màn hình."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Được cài đặt bởi quản trị viên của bạn"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Được cập nhật bởi quản trị viên của bạn"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Đã bị xóa bởi quản trị viên của bạn"</string>
@@ -1527,14 +1545,29 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Khác"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Bạn đặt tầm quan trọng của các thông báo này."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Thông báo này quan trọng vì những người có liên quan."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" đang cố thêm người dùng mới nhưng hiện không được cho phép."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" đang cố thêm người dùng mới nhưng đã đạt đến giới hạn người dùng."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" đang cố thêm người dùng mới nhưng tài khoản "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" đã tồn tại trên thiết bị này. Vẫn tiếp tục?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" đang cố thêm người dùng mới cho tài khoản "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Tiếp tục?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Cho phép <xliff:g id="APP">%1$s</xliff:g> tạo người dùng mới bằng <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Cho phép <xliff:g id="APP">%1$s</xliff:g> tạo người dùng mới bằng <xliff:g id="ACCOUNT">%2$s</xliff:g> (người dùng có tài khoản này đã tồn tại)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Tùy chọn ngôn ngữ"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Tùy chọn khu vực"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Nhập tên ngôn ngữ"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Ðược đề xuất"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Tất cả ngôn ngữ"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Tìm kiếm"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Chế độ làm việc đang TẮT"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Cho phép hồ sơ công việc hoạt động, bao gồm ứng dụng, đồng bộ hóa trong nền và các tính năng liên quan."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Bật"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s đã bị tắt"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Đã bị quản trị viên %1$s tắt. Hãy liên hệ với quản trị viên để tìm hiểu thêm."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Bạn có tin nhắn mới"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Mở ứng dụng SMS để xem"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Một số c.năng có thể ko k.dụng"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Chạm để tiếp tục"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Đã khóa hồ sơ người dùng"</string>
+    <!-- no translation found for usb_mtp_launch_notification_title (8359219638312208932) -->
+    <skip />
+    <!-- no translation found for usb_mtp_launch_notification_description (8541876176425411358) -->
+    <skip />
+    <string name="pin_target" msgid="3052256031352291362">"Ghim"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Bỏ ghim"</string>
+    <string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 45d13e8..938571e 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"互动式报告"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"在大多数情况下,建议您使用此选项,以便追踪报告的生成进度,以及输入与相应问题相关的更多详细信息。系统可能会省略掉一些不常用的区段,从而缩短生成报告的时间。"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"完整报告"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"如果您的设备无响应或运行速度缓慢,或者您需要查看所有区段的报告信息,则建议您使用此选项将系统干扰程度降到最低。系统不会截屏,也不支持您输入更多详细信息。"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">系统将在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后对错误报告进行截屏。</item>
       <item quantity="one">系统将在 <xliff:g id="NUMBER_0">%d</xliff:g> 秒后对错误报告进行截屏。</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g> 条)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"内容已隐藏"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"内容已隐藏(根据政策规定)"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"个人"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"选择操作"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"为USB设备选择一个应用"</string>
     <string name="noApplications" msgid="2991814273936504689">"没有应用可执行此操作。"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"很抱歉,“<xliff:g id="APPLICATION">%1$s</xliff:g>”已停止运行。"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"抱歉,进程“<xliff:g id="PROCESS">%1$s</xliff:g>”已停止运行。"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"关闭“<xliff:g id="PROCESS">%1$s</xliff:g>”的崩溃提醒,直到重新启动该应用。"</string>
+    <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g>已停止运行"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g>已停止运行"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g>屡次停止运行"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g>屡次停止运行"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"重启应用"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"重置并重启应用"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"发送反馈"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"关闭"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"忽略"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"等待"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"关闭应用"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g>无响应。\n\n要将其关闭吗?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g>活动无响应。\n\n要将其关闭吗?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g>无响应。要将其关闭吗?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g>进程无响应。\n\n要将其关闭吗?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"<xliff:g id="APPLICATION">%2$s</xliff:g>没有响应"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"<xliff:g id="ACTIVITY">%1$s</xliff:g>没有响应"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g>没有响应"</string>
+    <string name="anr_process" msgid="6156880875555921105">"进程“<xliff:g id="PROCESS">%1$s</xliff:g>”没有响应"</string>
     <string name="force_close" msgid="8346072094521265605">"确定"</string>
     <string name="report" msgid="4060218260984795706">"报告"</string>
     <string name="wait" msgid="7147118217226317732">"等待"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"已添加SIM卡"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"请重新启动您的设备,以便使用移动网络。"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"重新启动"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"设置时间"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"设置日期"</string>
     <string name="date_time_set" msgid="5777075614321087758">"设置"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消时要求输入PIN码"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消时要求绘制解锁图案"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消时要求输入密码"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"无法调整这个应用的大小,请用双指滚动应用。"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"无法调整该应用的大小,请用双指滚动该应用。"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"应用不支持分屏。"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理员安装"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"由您单位的管理员更新"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"已被管理员删除"</string>
@@ -1527,14 +1545,29 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"其他"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"这些通知的重要性由您来设置。"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"这条通知涉及特定的人,因此被归为重要通知。"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"正尝试添加新用户,但是系统目前禁止执行这项操作。"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"正尝试添加新用户,但已达到用户人数上限。"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"正尝试添加新用户,但这个设备上已经存在"<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>"这个帐号。仍要继续吗?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>"正尝试为"<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>"这个帐号添加新用户,要继续吗?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"允许<xliff:g id="APP">%1$s</xliff:g>使用 <xliff:g id="ACCOUNT">%2$s</xliff:g> 创建新用户吗?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"允许<xliff:g id="APP">%1$s</xliff:g>使用 <xliff:g id="ACCOUNT">%2$s</xliff:g>(目前已有用户使用此帐号)创建新用户吗?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"语言偏好设置"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"区域偏好设置"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"输入语言名称"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"建议语言"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"所有语言"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"搜索"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"工作模式已关闭"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"启用工作资料,包括应用、后台同步和相关功能。"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"开启"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s已被禁用"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"该软件包已被%1$s管理员禁用。请与管理员联系以了解详情。"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"您有新消息"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"打开短信应用查看"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"部分功能可能无法使用"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"触摸即可继续"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"用户个人资料已锁定"</string>
+    <!-- no translation found for usb_mtp_launch_notification_title (8359219638312208932) -->
+    <skip />
+    <!-- no translation found for usb_mtp_launch_notification_description (8541876176425411358) -->
+    <skip />
+    <string name="pin_target" msgid="3052256031352291362">"固定"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
+    <string name="app_info" msgid="6856026610594615344">"应用信息"</string>
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 2fe2228..620458c 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"互動報告"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"在大部分情況下,建議您使用此選項,以便追蹤報告進度,以及輸入更多與問題相關的的資訊。系統可能會省略部分不常用的區段,藉此縮短產生報告的時間。"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"完整報告"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"如果裝置沒有反應或運作速度較慢,或您需要所有區段的報告時,建議使用此選項將系統的干擾程度降至最低。此選項不會擷取螢幕畫面,亦不允許您輸入更多資訊。"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">系統將在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後擷取錯誤報告的螢幕畫面。</item>
       <item quantity="one">系統將在 <xliff:g id="NUMBER_0">%d</xliff:g> 秒後擷取錯誤報告的螢幕畫面。</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"已根據政策隱藏內容"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"個人"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"選擇操作"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"選取要以 USB 裝置存取的應用程式"</string>
     <string name="noApplications" msgid="2991814273936504689">"沒有應用程式可執行這項操作。"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"抱歉,<xliff:g id="APPLICATION">%1$s</xliff:g>已停止操作。"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"很抱歉,處理程序 <xliff:g id="PROCESS">%1$s</xliff:g> 已停止。"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"停止顯示「<xliff:g id="PROCESS">%1$s</xliff:g>」的當機資料 (除非重新啟動作業系統)。"</string>
+    <string name="aerr_application" msgid="250320989337856518">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」已經停止運作"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"「<xliff:g id="PROCESS">%1$s</xliff:g>」已經停止運作"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」不斷停止運作"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"「<xliff:g id="PROCESS">%1$s</xliff:g>」不斷停止運作"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"重新啟動應用程式"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"重設並重新啟動應用程式"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"傳送意見反映"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"關閉"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"忽略"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"等一下"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"關閉應用程式"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> 沒有回應。\n\n您要結束嗎?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"活動 <xliff:g id="ACTIVITY">%1$s</xliff:g> 沒有回應。\n\n您要結束嗎?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> 沒有回應。您要結束嗎?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"處理程序 <xliff:g id="PROCESS">%1$s</xliff:g> 沒有回應。\n\n您要結束嗎?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"「<xliff:g id="APPLICATION">%2$s</xliff:g>」沒有回應"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"「<xliff:g id="ACTIVITY">%1$s</xliff:g>」沒有回應"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」沒有回應"</string>
+    <string name="anr_process" msgid="6156880875555921105">"處理程序「<xliff:g id="PROCESS">%1$s</xliff:g>」沒有回應"</string>
     <string name="force_close" msgid="8346072094521265605">"確定"</string>
     <string name="report" msgid="4060218260984795706">"報告"</string>
     <string name="wait" msgid="7147118217226317732">"等待"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM 卡已新增"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"重新啟動裝置,才能使用流動網絡。"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"重新啟動"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"設定時間"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日期設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消固定時必須輸入 PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消固定時必須畫出解鎖圖案"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"不可更改應用程式尺寸,請使用兩隻手指捲動應用程式。"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"無法調整應用程式的大小,請用兩隻手指捲動此應用程式。"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"應用程式不支援分割畫面。"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理員安裝"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"已由您的管理員更新"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"已由管理員刪除"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"其他"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"您可以為這些通知設定重要性。"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"列為重要的原因:涉及的人。"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" 正在嘗試新增使用者,但系統目前禁止相關操作。"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" 正在嘗試新增使用者,但使用者人數已達上限。"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" 正在嘗試新增使用者,但此裝置上已有 "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" 這個帳戶。仍要繼續嗎?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" 正在嘗試為 "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" 這個帳戶新增使用者。要繼續嗎?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"要允許 <xliff:g id="APP">%1$s</xliff:g> 使用 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者嗎?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"要允許 <xliff:g id="APP">%1$s</xliff:g> 使用 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者 (此帳戶目前已有此使用者) 嗎?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"語言偏好設定"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"地區偏好設定"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"輸入語言名稱"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"推薦"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"所有語言"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"搜尋"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"工作模式已關閉"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"允許使用應用程式、背景同步及相關功能的工作設定檔。"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"開啟"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"已停用「%1$s」"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"「%1$s」管理員已停用此套件。請與管理員聯絡以瞭解詳情。"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"您有新的訊息"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"開啟短訊應用程式查看內容"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"部分功能可能無法使用"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"輕觸即可繼續"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"使用者個人檔案目前處於鎖定狀態"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"已連線至 <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"輕按即可查看檔案"</string>
+    <string name="pin_target" msgid="3052256031352291362">"固定"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
+    <string name="app_info" msgid="6856026610594615344">"應用程式資料"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 6554153..f56bc14 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"互動式報告"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"在一般情況下,建議您使用這個選項,以便追蹤報告產生進度,以及輸入更多與問題相關的資訊。系統可能會省略部分較少使用的區段,藉此縮短報告產生時間。"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"完整報告"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"如果您的裝置沒有回應或運行速度過慢,或是當您需要所有區段的報告時,建議您使用這個選項來減少系統干擾。這個選項不會擷取螢幕畫面,也不支援您輸入更多資訊。"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="other">系統將在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後擷取錯誤報告的螢幕畫面。</item>
       <item quantity="one">系統將在 <xliff:g id="NUMBER_0">%d</xliff:g> 秒後擷取錯誤報告的螢幕畫面。</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"超過 999"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"內容已隱藏"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"內容已依據政策隱藏"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"個人"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"選擇分享方式"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"選取要以 USB 裝置存取的應用程式"</string>
     <string name="noApplications" msgid="2991814273936504689">"沒有應用程式可執行這項操作。"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"很抱歉,<xliff:g id="APPLICATION">%1$s</xliff:g>已停止運作。"</string>
-    <string name="aerr_process" msgid="4507058997035697579">"很抱歉,處理程序 <xliff:g id="PROCESS">%1$s</xliff:g> 已停止。"</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Silence 執行<xliff:g id="PROCESS">%1$s</xliff:g>時發生當機問題,必須重新啟動。"</string>
+    <string name="aerr_application" msgid="250320989337856518">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」已停止運作"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"「<xliff:g id="PROCESS">%1$s</xliff:g>」已停止運作"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」屢次停止運作"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"「<xliff:g id="PROCESS">%1$s</xliff:g>」屢次停止運作"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"重新啟動應用程式"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"重設並重新啟動應用程式"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"提供意見"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"關閉"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"忽略"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"等一下"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"關閉應用程式"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> 沒有回應。\n\n您要結束嗎?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"<xliff:g id="ACTIVITY">%1$s</xliff:g> 活動沒有回應。\n\n您要結束嗎?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> 沒有回應。您要結束嗎?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"<xliff:g id="PROCESS">%1$s</xliff:g> 處理程序沒有回應。\n\n您要結束嗎?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"「<xliff:g id="APPLICATION">%2$s</xliff:g>」沒有回應"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"「<xliff:g id="ACTIVITY">%1$s</xliff:g>」沒有回應"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"「<xliff:g id="APPLICATION">%1$s</xliff:g>」沒有回應"</string>
+    <string name="anr_process" msgid="6156880875555921105">"「<xliff:g id="PROCESS">%1$s</xliff:g>」程序沒有回應"</string>
     <string name="force_close" msgid="8346072094521265605">"確定"</string>
     <string name="report" msgid="4060218260984795706">"回報"</string>
     <string name="wait" msgid="7147118217226317732">"等待"</string>
@@ -1024,6 +1031,16 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM 卡已新增"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"請重新啟動裝置,才能使用行動網路。"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"重新啟動"</string>
+    <!-- no translation found for carrier_app_dialog_message (7066156088266319533) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_button (7900235513678617329) -->
+    <skip />
+    <!-- no translation found for carrier_app_dialog_not_now (6361378684292268027) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_title (8921767385872554621) -->
+    <skip />
+    <!-- no translation found for carrier_app_notification_text (1132487343346050225) -->
+    <skip />
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"設定時間"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日期設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
@@ -1455,7 +1472,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消固定時必須輸入 PIN"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消固定時必須畫出解鎖圖案"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"無法調整這個應用程式的大小,請用雙指捲動該應用程式。"</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"無法調整這個應用程式的大小,請用雙指捲動該應用程式。"</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"這個應用程式不支援分割畫面。"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理員安裝"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"由您的管理員更新"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"已遭管理員刪除"</string>
@@ -1527,14 +1545,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"其他"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"這些通知的重要性由您決定。"</string>
     <string name="importance_from_person" msgid="9160133597262938296">"這則通知涉及特定人士,因此被歸為重要通知。"</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b></b>"「<xliff:g id="APP">%1$s</xliff:g>」正在嘗試新增使用者,但系統目前禁止相關操作。"</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b></b>"「<xliff:g id="APP">%1$s</xliff:g>」正在嘗試新增使用者,但已達到使用者人數上限。"</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b></b>"「<xliff:g id="APP">%1$s</xliff:g>」正在嘗試新增使用者,但這個裝置上已經有 <xliff:g id="ACCOUNT">%2$s</xliff:g> "<b></b>"這個帳戶。仍要繼續嗎?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b></b>"「<xliff:g id="APP">%1$s</xliff:g>」正在嘗試為 <xliff:g id="ACCOUNT">%2$s</xliff:g> "<b></b>"這個帳戶新增使用者。要繼續嗎?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"要允許 <xliff:g id="APP">%1$s</xliff:g> 為 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者嗎?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"要允許 <xliff:g id="APP">%1$s</xliff:g> 為 <xliff:g id="ACCOUNT">%2$s</xliff:g> 建立新使用者嗎 (這個帳戶目前已有使用者)?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"語言偏好設定"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"地區偏好設定"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"請輸入語言名稱"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"建議語言"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"所有語言"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"搜尋"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Work 模式已關閉"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"啟用 Work 設定檔,包括應用程式、背景同步處理和相關功能。"</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"開啟"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"已由「%1$s」停用"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"這個套件已由「%1$s」管理員停用。請與對方聯絡以瞭解詳情。"</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"您有新訊息"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"開啟簡訊應用程式來查看內容"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"部分功能可能無法使用"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"輕觸即可繼續作業"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"使用者個人資料目前處於鎖定狀態"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"已連線至 <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"輕按即可查看檔案"</string>
+    <string name="pin_target" msgid="3052256031352291362">"固定"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
+    <string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index b6a8039..9fd4725 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -214,8 +214,7 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Umbiko obandakanyayo"</string>
     <string name="bugreport_option_interactive_summary" msgid="8180152634022797629">"Sebenzisa lokhu ngaphansi kwezimo eziningi. Kukuvumela ukuthi ulandelele ukuqhubeka kombiko uphinde ufake imininingwane engaphezulu mayelana nenkinga. Kungakhipha ezinye izigaba ezisetshenziswe kancane ezithatha isikhathi eside ukuze zibikwe."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Umbiko ogcwele"</string>
-    <!-- no translation found for bugreport_option_full_summary (6687306111256813257) -->
-    <skip />
+    <string name="bugreport_option_full_summary" msgid="6687306111256813257">"Sebenzisa le nketho ukuze uthole ukuphazamiseka okuncane kwesistimu uma idivayisi yakho ingaphenduli noma ihamba kancane kakhulu, noma udinga zonke izigaba zombiko. Ayithathi isithombe-skrini noma ikuvumele ukuthi ufake imininingwane engaphezulu."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">Ithathela umbiko wesiphazamisi isithombe-skrini kumasekhondi angu-<xliff:g id="NUMBER_1">%d</xliff:g>.</item>
       <item quantity="other">Ithathela umbiko wesiphazamisi isithombe-skrini kumasekhondi angu-<xliff:g id="NUMBER_1">%d</xliff:g>.</item>
@@ -233,6 +232,7 @@
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"Okuqukethwe kufihliwe"</string>
+    <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"Okuqukethwe kufihlwe inqubomgomo"</string>
     <string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Okomuntu siqu"</string>
@@ -909,15 +909,22 @@
     <string name="chooseActivity" msgid="7486876147751803333">"Khetha okufanele kwenziwe"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Kheth uhlelo lokusebenza yedivayisi ye-USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Azikho izinhlelo zokusebenza ezingenza lokhu"</string>
-    <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"Ngeshwa, <xliff:g id="APPLICATION">%1$s</xliff:g> kumile."</string>
-    <string name="aerr_process" msgid="4507058997035697579">"Ngeshwa, uhlelo  <xliff:g id="PROCESS">%1$s</xliff:g> luvele lwama."</string>
-    <string name="aerr_process_silence" msgid="4226685530196000222">"Ukuphahlazeka okuthulile kusukela ku-<xliff:g id="PROCESS">%1$s</xliff:g> kuze kuqalise."</string>
+    <string name="aerr_application" msgid="250320989337856518">"I-<xliff:g id="APPLICATION">%1$s</xliff:g> imile"</string>
+    <string name="aerr_process" msgid="6201597323218674729">"I-<xliff:g id="PROCESS">%1$s</xliff:g> imile"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"I-<xliff:g id="APPLICATION">%1$s</xliff:g> ilokhu iyama"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"I-<xliff:g id="PROCESS">%1$s</xliff:g> ilokhu iyama"</string>
+    <string name="aerr_restart" msgid="9001379185665886595">"Qala kabusha uhlelo lokusebenza"</string>
+    <string name="aerr_reset" msgid="7645427603514220451">"Setha kabusha uphinde uqalise kabusha uhlelo lokusebenza"</string>
+    <string name="aerr_report" msgid="5371800241488400617">"Thumela impendulo"</string>
+    <string name="aerr_close" msgid="2991640326563991340">"Vala"</string>
+    <string name="aerr_mute" msgid="7698966346654789433">"Thulisa"</string>
+    <string name="aerr_wait" msgid="3199956902437040261">"Linda"</string>
+    <string name="aerr_close_app" msgid="3269334853724920302">"Vala uhlelo lokusebenza"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
-    <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> ayiphenduli.\n\nIngabe ufuna ukuyivala?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"Uhlelo <xliff:g id="ACTIVITY">%1$s</xliff:g> aluphenduli.\n\nIngabe ufuna ukuluvala?"</string>
-    <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> ayiphenduli. Ingabe ufuna ukuyivala?"</string>
-    <string name="anr_process" msgid="6513209874880517125">"Inqubo <xliff:g id="PROCESS">%1$s</xliff:g> ayisabeli.\n\nIngabe ufuna ukuyivala?"</string>
+    <string name="anr_activity_application" msgid="8493290105678066167">"I-<xliff:g id="APPLICATION">%2$s</xliff:g> ayiphenduli"</string>
+    <string name="anr_activity_process" msgid="1622382268908620314">"I-<xliff:g id="ACTIVITY">%1$s</xliff:g> ayiphenduli"</string>
+    <string name="anr_application_process" msgid="6417199034861140083">"I-<xliff:g id="APPLICATION">%1$s</xliff:g> ayiphenduli"</string>
+    <string name="anr_process" msgid="6156880875555921105">"Inqubo engu-<xliff:g id="PROCESS">%1$s</xliff:g> ayiphenduli"</string>
     <string name="force_close" msgid="8346072094521265605">"KULUNGILE"</string>
     <string name="report" msgid="4060218260984795706">"Umbiko"</string>
     <string name="wait" msgid="7147118217226317732">"Linda"</string>
@@ -1024,6 +1031,11 @@
     <string name="sim_added_title" msgid="3719670512889674693">"Ikhadi le-SIM lengeziwe"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"Qala kabusha idivayisi yakho ukuze ufinyelele inethiwekhi yeselula."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"Qala phansi"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Ukuze wenze i-SIM yakho entsha isebenze kahle, kuzomele ufake uphinde uvule uhlelo lokusebenza kusukela kunkampani yakho yenethiwekhi."</string>
+    <string name="carrier_app_dialog_button" msgid="7900235513678617329">"THOLA UHLELO LOKUSEBENZA"</string>
+    <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"HHAYI MANJE"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"Kufakwe i-SIM entsha"</string>
+    <string name="carrier_app_notification_text" msgid="1132487343346050225">"Thepha ukuze uyisethe"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Hlela isikhathi"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setha idethi"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Hlela"</string>
@@ -1455,7 +1467,8 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Cela iphinikhodi ngaphambi kokuphina"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Cela iphethini yokuvula ngaphambi kokususa ukuphina"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Cela iphasiwedi ngaphambi kokususa ukuphina"</string>
-    <string name="dock_non_resizeble_text" msgid="9156251681042762723">"Uhlelo lokusebenza alukwazi ukunikezwa usayizi omusha, liskrole ngeminwe emibili."</string>
+    <string name="dock_cropped_windows_text" msgid="6378424064779004428">"Uhlelo lokusebenza alukwazi ukunikezwa usayizi omusha, liskrole ngeminwe emibili."</string>
+    <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Uhlelo lokusebenza alusekeli isikrini esihlukanisiwe."</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Ifakwe ngumlawuli wakho"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ibuyekezwe ngumqondisi wakho"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Isuswe ngumlawuli wakho"</string>
@@ -1527,14 +1540,27 @@
     <string name="default_notification_topic_label" msgid="227586145791870829">"Okwahlukahlukene"</string>
     <string name="importance_from_topic" msgid="3572280439880023233">"Usethe ukubaluleka kwalezi zaziso."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"Lokhu kubalulekile ngenxa yabantu ababandakanyekayo."</string>
-    <string name="user_creation_cannot_add" msgid="7740333663230045315"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" izama ukungeza umsebenzisi omusha, kodwa okwamanje inqatshelewe."</string>
-    <string name="user_creation_cannot_add_any_more" msgid="6244197709981359266"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" izama ukungeza umsebenzisi omusha, kodwa umkhawulo womsebenzisi ufinyelelwe."</string>
-    <string name="user_creation_account_exists" msgid="4880171855014489789"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" izama ukungeza umsebenzisi omusha, kodwa i-akhawunti "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>" isivele ikhona kule divayisi. Qhubeka noma kunjalo?"</string>
-    <string name="user_creation_adding" msgid="3206420861363021392"><b>"<xliff:g id="APP">%1$s</xliff:g>"</b>" izama ukungeza umsebenzisi omusha we-akhawunti "<b>"<xliff:g id="ACCOUNT">%2$s</xliff:g>"</b>". Qhubeka?"</string>
+    <string name="user_creation_account_exists" msgid="1942606193570143289">"Vumela i-<xliff:g id="APP">%1$s</xliff:g> ukudala umsebenzisi omusha nge-<xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
+    <string name="user_creation_adding" msgid="4482658054622099197">"Vumela i-<xliff:g id="APP">%1$s</xliff:g> ukudala umsebenzisi omusha nge-<xliff:g id="ACCOUNT">%2$s</xliff:g> (umsebenzisi onale akhawunti usuvel ukhona) ?"</string>
     <string name="language_selection_title" msgid="7181332986330337171">"Okuncamelayo kolimi"</string>
     <string name="country_selection_title" msgid="2954859441620215513">"Okuncamelayo kwesifunda"</string>
     <string name="search_language_hint" msgid="7042102592055108574">"Thayipha igama lolimi"</string>
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"Okuphakanyisiwe"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"Zonke izilimi"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"Sesha"</string>
+    <string name="work_mode_off_title" msgid="8954725060677558855">"Imodi yomsebenzi IVALIWE"</string>
+    <string name="work_mode_off_message" msgid="3286169091278094476">"Vumela iphrofayela yomsebenzi ukuze isebenze, efaka izinhlelo zokusebenza, ukuvumelanisa kwangemuva, nezici ezisondelene."</string>
+    <string name="work_mode_turn_on" msgid="2062544985670564875">"Vula"</string>
+    <string name="suspended_package_title" msgid="3408150347778524435">"I-%1$s ikhutshaziwe"</string>
+    <string name="suspended_package_message" msgid="6341091587106868601">"Ikhutshazwe umlawuli we-%1$s. Xhumana nabo ukuze ufunde kabanzi."</string>
+    <string name="new_sms_notification_title" msgid="8442817549127555977">"Unemilayezo emisha"</string>
+    <string name="new_sms_notification_content" msgid="7002938807812083463">"Vula uhlelo lokusebenza lwe-SMS ukuze ubuke"</string>
+    <string name="user_encrypted_title" msgid="7664361246988454307">"Eminye imisebenzi ingahle ingatholakali"</string>
+    <string name="user_encrypted_message" msgid="7504541494700807850">"Thinta ukuze uqhubeke"</string>
+    <string name="user_encrypted_detail" msgid="979981584766912935">"Iphrofayela yomsebenzisi ikhiyiwe"</string>
+    <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"Kuxhumekile ku-<xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Thepha ukuze ubuke onke amafayela"</string>
+    <string name="pin_target" msgid="3052256031352291362">"Phina"</string>
+    <string name="unpin_target" msgid="3556545602439143442">"Susa ukuphina"</string>
+    <string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string>
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index a6a4564..c083a5e 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -402,4 +402,15 @@
         <item>@color/Red_700</item>
     </array>
 
+    <!-- Used in ResolverTargetActionsDialogFragment -->
+    <string-array name="resolver_target_actions_pin">
+        <item>@string/pin_target</item>
+        <item>@string/app_info</item>
+    </string-array>
+
+    <string-array name="resolver_target_actions_unpin">
+        <item>@string/unpin_target</item>
+        <item>@string/app_info</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 1f7206e..b9d8661 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2039,6 +2039,8 @@
         <attr name="listItemLayout" format="reference" />
         <attr name="progressLayout" format="reference" />
         <attr name="horizontalProgressLayout" format="reference" />
+        <!-- @hide Not ready for public use. -->
+        <attr name="showTitle" format="boolean" />
         <!-- @hide Whether fullDark, etc. should use default values if null. -->
         <attr name="needsDefaultBackgrounds" format="boolean" />
     </declare-styleable>
@@ -6355,34 +6357,9 @@
     <!-- ========================== -->
     <eat-comment />
 
-    <!-- Drawable states.
-         The mapping of Drawable states to a particular drawables is specified
-         in the "state" elements of a Widget's "selector" element.
-         Possible values:
-         <ul>
-         <li>"state_focused"
-         <li>"state_window_focused"
-         <li>"state_enabled"
-         <li>"state_checked"
-         <li>"state_selected"
-         <li>"state_active"
-         <li>"state_single"
-         <li>"state_first"
-         <li>"state_mid"
-         <li>"state_last"
-         <li>"state_only"
-         <li>"state_pressed"
-         <li>"state_activated"
-         <li>"state_error"
-         <li>"state_circle"
-         <li>"state_rect"
-         <li>"state_grow"
-         <li>"state_move"
-         <li>"state_hovered"
-         <li>"state_drag_can_accept"
-         <li>"state_drag_hovered"
-         <li>"state_accessibility_focused"
-         </ul>  -->
+    <!-- Set of framework-provided states that may be specified on a Drawable. Actual usage of
+         states may vary between view implementations, as documented on the individual state
+         attributes. -->
     <declare-styleable name="DrawableStates">
         <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
              set when a view has input focus. -->
@@ -6393,13 +6370,13 @@
         <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
              set when a view is enabled. -->
         <attr name="state_enabled" format="boolean" />
-        <!-- State identifier indicating that the object <var>may</var> display a check mark.
-             See {@link android.R.attr#state_checked} for the identifier that indicates whether it is
+        <!-- State identifier indicating that the object <var>may</var> display a check mark. See
+             {@link android.R.attr#state_checked} for the identifier that indicates whether it is
              actually checked. -->
         <attr name="state_checkable" format="boolean"/>
         <!-- State identifier indicating that the object is currently checked.  See
-             {@link android.R.attr#state_checkable} for an additional identifier that can indicate if
-             any object may ever display a check, regardless of whether state_checked is
+             {@link android.R.attr#state_checkable} for an additional identifier that can indicate
+             if any object may ever display a check, regardless of whether state_checked is
              currently set. -->
         <attr name="state_checked" format="boolean"/>
         <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
@@ -6413,15 +6390,25 @@
              marked it as being of interest.  This is an alternative representation of
              state_checked for when the state should be propagated down the view hierarchy. -->
         <attr name="state_activated" format="boolean" />
-        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.-->
+        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
+             set when a view or drawable is considered "active" by its host. Actual usage may vary
+             between views. Consult the host view documentation for details. -->
         <attr name="state_active" format="boolean" />
-        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.-->
+        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
+             set when a view or drawable is considered "single" by its host. Actual usage may vary
+             between views. Consult the host view documentation for details. -->
         <attr name="state_single" format="boolean" />
-        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.-->
+        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
+             set when a view or drawable is in the first position in an ordered set. Actual usage
+             may vary between views. Consult the host view documentation for details. -->
         <attr name="state_first" format="boolean" />
-        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.-->
+        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
+             set when a view or drawable is in the middle position in an ordered set. Actual usage
+             may vary between views. Consult the host view documentation for details. -->
         <attr name="state_middle" format="boolean" />
-        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.-->
+        <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
+             set when a view or drawable is in the last position in an ordered set. Actual usage
+             may vary between views. Consult the host view documentation for details. -->
         <attr name="state_last" format="boolean" />
         <!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},
              indicating that the Drawable is in a view that is hardware accelerated.
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index c744bbd..3a5336c 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -429,6 +429,9 @@
          sets. -->
     <attr name="multiArch" format ="boolean" />
 
+    <!-- Specify abiOverride for multiArch application. -->
+    <attr name="abiOverride" />
+
     <!-- Specify whether a component is allowed to have multiple instances
          of itself running in different processes.  Use with the activity
          and provider tags.
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index dd18544..7399fa9 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -48,8 +48,6 @@
     <color name="primary_text_default_material_light">#de000000</color>
     <!-- 54% black -->
     <color name="secondary_text_default_material_light">#8a000000</color>
-    <!-- 38% black -->
-    <color name="tertiary_text_default_material_light">#61000000</color>
 
     <!-- 100% white -->
     <color name="primary_text_default_material_dark">#ffffffff</color>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 7c6f338..8e86f78 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -449,5 +449,7 @@
     <item type="dimen" format="integer" name="time_picker_column_start_material">0</item>
     <item type="dimen" format="integer" name="time_picker_column_end_material">1</item>
 
+    <item type="dimen" name="aerr_padding_list_top">15dp</item>
+
     <item type="fraction" name="docked_stack_divider_fixed_ratio">34.15%</item>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bbbb963..5c5aff0 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2696,6 +2696,10 @@
     <public type="attr" name="endX" />
     <public type="attr" name="endY" />
     <public type="attr" name="offset" />
+    <public type="attr" name="abiOverride" />
+    <public type="attr" name="bitmap" />
+    <public type="attr" name="hotSpotX" />
+    <public type="attr" name="hotSpotY" />
 
     <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
     <public type="style" name="Widget.Material.SeekBar.Discrete" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 523826b..4e10d39 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2869,6 +2869,14 @@
     <string name="sim_added_message">Restart your device to access the cellular network.</string>
     <!-- See SIM_ADDED_DIALOG.  This is the button of that dialog. -->
     <string name="sim_restart_button">Restart</string>
+    <!-- See Carrier_App_Dialog. This is the message of that dialog. -->
+    <string name="carrier_app_dialog_message">To get your new SIM working properly, you\'ll need to install and open an app from your carrier.</string>
+    <!-- See Carrier_App_Dialog. This is the button of that dialog. -->
+    <string name="carrier_app_dialog_button">GET THE APP</string>
+    <string name="carrier_app_dialog_not_now">NOT NOW</string>
+    <!-- See carrier_app_notification. This is the headline. -->
+    <string name="carrier_app_notification_title">New SIM inserted</string>
+    <string name="carrier_app_notification_text">Tap to set it up</string>
 
     <!-- Date/Time picker dialogs strings -->
 
@@ -4168,7 +4176,7 @@
     <string name="language_selection_title">Language preference</string>
     <!-- Title for the region selection screen [CHAR LIMIT=25] -->
     <string name="country_selection_title">Region preference</string>
-    <!-- Hint text in a search edit box (used to filter long language / country lists) [CHAR LIMIT=20] -->
+    <!-- Hint text in a search edit box (used to filter long language / country lists) [CHAR LIMIT=25] -->
     <string name="search_language_hint">Type language name</string>
 
     <!-- List section subheader for the language picker, containing a list of suggested languages determined by the default region [CHAR LIMIT=30] -->
@@ -4206,4 +4214,15 @@
     <string name="usb_mtp_launch_notification_title">Connected to <xliff:g id="product_name">%1$s</xliff:g></string>
     <!-- Description of notification shown after a MTP device is connected to Android. -->
     <string name="usb_mtp_launch_notification_description">Tap to view files</string>
+
+    <!-- Resolver target actions strings -->
+
+    <!-- Pin (as in to a bulletin board with a pushpin) a resolver
+         target to the front of the list. -->
+    <string name="pin_target">Pin</string>
+    <!-- Unpin a resolver target such that it sorts normally. -->
+    <string name="unpin_target">Unpin</string>
+    <!-- View application info for a target. -->
+    <string name="app_info">App info</string>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index f0960c7..86b9f1d 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1403,8 +1403,12 @@
         <item name="textAppearance">?attr/textAppearanceListItemSmall</item>
         <item name="textColor">?attr/textColorAlertDialogListItem</item>
         <item name="gravity">center_vertical</item>
-        <item name="paddingStart">?attr/listPreferredItemPaddingStart</item>
-        <item name="paddingEnd">?attr/listPreferredItemPaddingEnd</item>
+        <item name="paddingStart">?attr/dialogPreferredPadding</item>
+        <item name="paddingEnd">?attr/dialogPreferredPadding</item>
+        <item name="background">?attr/selectableItemBackground</item>
+        <item name="drawablePadding">32dp</item>
+        <item name="drawableTint">@color/accent_material_light</item>
+        <item name="drawableTintMode">src_atop</item>
     </style>
 
     <!-- Wifi dialog styles -->
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 7aa0c12..9efcfda 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -444,7 +444,7 @@
     </style>
 
     <style name="TextAppearance.Material.Notification.Info">
-        <item name="textColor">@color/tertiary_text_default_material_light</item>
+        <item name="textColor">@color/secondary_text_default_material_light</item>
         <item name="textSize">@dimen/notification_subtext_size</item>
     </style>
 
@@ -1178,7 +1178,11 @@
         <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_material</item>
     </style>
 
-    <style name="AlertDialog.Material.Light"/>
+    <style name="AlertDialog.Material.Light" />
+
+    <style name="DatePickerDialog.Material" parent="AlertDialog.Material">
+        <item name="showTitle">true</item>
+    </style>
 
     <!-- Window title -->
     <style name="WindowTitleBackground.Material">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 28c01d2..f75f023 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1997,6 +1997,8 @@
   <java-symbol type="drawable" name="decor_close_button_light" />
   <java-symbol type="drawable" name="decor_maximize_button_dark" />
   <java-symbol type="drawable" name="decor_maximize_button_light" />
+  <java-symbol type="color" name="decor_button_dark_color" />
+  <java-symbol type="color" name="decor_button_light_color" />
 
   <!-- From TelephonyProvider -->
   <java-symbol type="xml" name="apns" />
@@ -2367,6 +2369,7 @@
   <java-symbol type="plurals" name="selected_count" />
   <java-symbol type="drawable" name="ic_dialog_alert_material" />
 
+
   <java-symbol type="string" name="lockscreen_access_pattern_area" />
 
   <java-symbol type="bool" name="config_eap_sim_based_auth_supported" />
@@ -2519,7 +2522,18 @@
   <java-symbol type="string" name="user_encrypted_title" />
   <java-symbol type="string" name="user_encrypted_message" />
   <java-symbol type="string" name="user_encrypted_detail" />
+  <java-symbol type="drawable" name="ic_user_secure" />
 
   <java-symbol type="string" name="usb_mtp_launch_notification_title" />
   <java-symbol type="string" name="usb_mtp_launch_notification_description" />
+
+  <!-- Resolver target actions -->
+  <java-symbol type="array" name="resolver_target_actions_pin" />
+  <java-symbol type="array" name="resolver_target_actions_unpin" />
+
+  <java-symbol type="string" name="carrier_app_dialog_message" />
+  <java-symbol type="string" name="carrier_app_dialog_button" />
+  <java-symbol type="string" name="carrier_app_dialog_not_now" />
+  <java-symbol type="string" name="carrier_app_notification_title" />
+  <java-symbol type="string" name="carrier_app_notification_text" />
 </resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 47892a3..5970a22 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -375,7 +375,7 @@
         <item name="datePickerStyle">@style/Widget.Material.DatePicker</item>
 
         <!-- DatePicker dialog theme -->
-        <item name="datePickerDialogTheme">?attr/dialogTheme</item>
+        <item name="datePickerDialogTheme">@style/ThemeOverlay.Material.Dialog.DatePicker</item>
 
         <!-- TODO: This belongs in a FastScroll style -->
         <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_material</item>
@@ -738,7 +738,7 @@
         <item name="datePickerStyle">@style/Widget.Material.Light.DatePicker</item>
 
         <!-- DatePicker dialog theme -->
-        <item name="datePickerDialogTheme">?attr/dialogTheme</item>
+        <item name="datePickerDialogTheme">@style/ThemeOverlay.Material.Dialog.DatePicker</item>
 
         <!-- TODO: This belongs in a FastScroll style -->
         <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_material</item>
@@ -891,6 +891,11 @@
         <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
     </style>
 
+    <!-- Theme overlay that overrides window properties to display as a date picker dialog. -->
+    <style name="ThemeOverlay.Material.Dialog.DatePicker">
+        <item name="alertDialogStyle">@style/DatePickerDialog.Material</item>
+    </style>
+
     <style name="ThemeOverlay.Material.Dialog.Alert">
         <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
         <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
diff --git a/core/tests/coretests/src/android/print/BasePrintTest.java b/core/tests/coretests/src/android/print/BasePrintTest.java
index 19ce44a..3feb0e9 100644
--- a/core/tests/coretests/src/android/print/BasePrintTest.java
+++ b/core/tests/coretests/src/android/print/BasePrintTest.java
@@ -141,7 +141,7 @@
         // Set to US locale.
         Resources resources = getInstrumentation().getTargetContext().getResources();
         Configuration oldConfiguration = resources.getConfiguration();
-        if (!oldConfiguration.getLocales().getPrimary().equals(Locale.US)) {
+        if (!oldConfiguration.getLocales().get(0).equals(Locale.US)) {
             mOldLocale = oldConfiguration.getLocales();
             DisplayMetrics displayMetrics = resources.getDisplayMetrics();
             Configuration newConfiguration = new Configuration(oldConfiguration);
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index d2bd106..de741b3 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -89,10 +89,7 @@
 endef
 
 font_src_files := \
-    Clockopia.ttf \
-    AndroidClock.ttf \
-    AndroidClock_Highlight.ttf \
-    AndroidClock_Solid.ttf
+    AndroidClock.ttf
 
 $(foreach f, $(font_src_files), $(call build-one-font-module, $(f)))
 
diff --git a/data/fonts/AndroidClock_Highlight.ttf b/data/fonts/AndroidClock_Highlight.ttf
deleted file mode 100644
index 923bb30..0000000
--- a/data/fonts/AndroidClock_Highlight.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/AndroidClock_Solid.ttf b/data/fonts/AndroidClock_Solid.ttf
deleted file mode 100644
index 923bb30..0000000
--- a/data/fonts/AndroidClock_Solid.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/Clockopia.ttf b/data/fonts/Clockopia.ttf
deleted file mode 100644
index 3f7b6aa..0000000
--- a/data/fonts/Clockopia.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/MTLc3m.ttf b/data/fonts/MTLc3m.ttf
deleted file mode 100644
index e9018f6..0000000
--- a/data/fonts/MTLc3m.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/MTLmr3m.ttf b/data/fonts/MTLmr3m.ttf
deleted file mode 100644
index 14f27d4..0000000
--- a/data/fonts/MTLmr3m.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 597a122..acd785e 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -20,7 +20,4 @@
 PRODUCT_PACKAGES := \
     DroidSansFallback.ttf \
     DroidSansMono.ttf \
-    Clockopia.ttf \
     AndroidClock.ttf \
-    AndroidClock_Highlight.ttf \
-    AndroidClock_Solid.ttf \
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 961d0eb..dc302c7 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -344,6 +344,9 @@
     <family lang="und-Zsye">
         <font weight="400" style="normal">NotoColorEmoji.ttf</font>
     </family>
+    <family>
+        <font weight="400" style="normal">DroidSansFallback.ttf</font>
+    </family>
     <!--
         Tai Le and Mongolian are intentionally kept last, to make sure they don't override
         the East Asian punctuation for Chinese.
diff --git a/docs/html/preview/support.jd b/docs/html/preview/support.jd
index 8c392aa..cfd9467 100644
--- a/docs/html/preview/support.jd
+++ b/docs/html/preview/support.jd
@@ -160,21 +160,20 @@
         still perform BTLE and WiFi scans, but only when they are in the foreground. While in the background, those apps will get no results from BTLE and WiFi scans.</li>
     </ul>
   </li>
-  <li>Accessing accounts
+  <li>Permission changes
     <ul>
-      <li>Updated the behavior of {@link android.accounts.AccountManager} account
-        discovery methods.
+      <li>Updated the user interface for permissions and enhanced some of the permissions
+        behaviors.</li>
+      <li>The {@link android.Manifest.permission#GET_ACCOUNTS} permission is now a member of the
+        {@link android.Manifest.permission_group#CONTACTS} permission group and it has a
+        {@code android:protectionLevel} of {@code dangerous}. This change means that when
+        targeting Android 6.0 (API level 23), you must check for and request this permission if
+        your app requires it.
       </li>
-      <li>The GET_ACCOUNTS permission has been deprecated.
-      </li>
-      <li>Apps targeting API level 24 should start the intent returned by
-        newChooseAccountIntent(...) and await the result to acquire a reference
-        to the user's selected account. AccountManager methods like getAccounts and
-        related methods will only return those accounts managed by
-        authenticators that match the signatures of the calling app.
-      </li>
-      <li>Apps targeting API level 23 or earlier will continue to behave as
-        before.
+
+      <li>The {@code android.permission.READ_PROFILE} and {@code android.permission.WRITE_PROFILE}
+       permissions have been removed from the {@link android.Manifest.permission_group#CONTACTS}
+       permission group.
       </li>
     </ul>
   </li>
diff --git a/docs/html/training/id-auth/identify.jd b/docs/html/training/id-auth/identify.jd
index 4c399f9..db9ab3a 100644
--- a/docs/html/training/id-auth/identify.jd
+++ b/docs/html/training/id-auth/identify.jd
@@ -15,7 +15,8 @@
 <ol>
   <li><a href="#ForYou">Determine if AccountManager is for You</a></li>
   <li><a href="#TaskTwo">Decide What Type of Account to Use</a></li>
-  <li><a href="#QueryAccounts">Query the user for an Account</a></li>
+  <li><a href="#GetPermission">Request GET_ACCOUNT permission</a></li>
+  <li><a href="#TaskFive">Query AccountManager for a List of Accounts</a></li>
   <li><a href="#IdentifyUser">Use the Account Object to Personalize Your App</a></li>
   <li><a href="#IdIsEnough">Decide Whether an Account Name is Enough</a></li>
 </ol>
@@ -70,46 +71,48 @@
 <h2 id="TaskTwo">Decide What Type of Account to Use</h2>
 
 <p>Android devices can store multiple accounts from many different providers.
-When you query {@link android.accounts.AccountManager} for account names, you
-can choose to filter by account type. The account type is a string that
-uniquely identifies the entity that issued the account. For instance, Google
-accounts have type "com.google," while Twitter uses
-"com.twitter.android.auth.login."</p>
+When you query {@link android.accounts.AccountManager} for account names, you can choose to filter
+by
+account type. The account type is a string that uniquely identifies the entity
+that issued the account. For instance, Google accounts have type "com.google,"
+while Twitter uses "com.twitter.android.auth.login."</p>
 
-<h2 id="QueryAccounts">Query the user for an Account</h2>
 
-<p>Once an account type has been determined, you can prompt the user with an
-account chooser as follows:
+<h2 id="GetPermission">Request GET_ACCOUNT permission</h2>
+
+<p>In order to get a list of accounts on the device, your app needs the {@link
+android.Manifest.permission#GET_ACCOUNTS}
+permission. Add a <a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">{@code
+<uses-permission>}</a> tag in your manifest file to request
+this permission:</p>
 
 <pre>
-AccountManager am = AccountManager.get(this);  // "this" reference the current Context
-Intent chooserIntent = am.newChooseAccountIntent(
-        null, // currently select account
-        null, // list of accounts that are allowed to be shown
-        new String[] { "com.google" }, // Only allow the user to select Google accounts
-        false,
-        null,  // description text
-        null, // add account auth token type
-        null, // required features for added accounts
-        null);  // options for adding an account
-this.startActivityForResult(chooserIntent, MY_REQUEST_CODE);
+&lt;manifest ... >
+    &lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
+    ...
+&lt;/manifest>
 </pre>
 
-<p>Once the chooser intent is started, the user will be presented with a list of
-appropriately typed accounts. From this list they will select one which will be
-returned to your app upon onActivityResult as follows:
+
+<h2 id="TaskFive">Query AccountManager for a List of Accounts</h2>
+
+<p>Once you decide what account type you're interested in, you need to query for accounts of that
+type. Get an instance of {@link android.accounts.AccountManager} by calling {@link
+android.accounts.AccountManager#get(android.content.Context) AccountManager.get()}. Then use that
+instance to call {@link android.accounts.AccountManager#getAccountsByType(java.lang.String)
+getAccountsByType()}.</p>
 
 <pre>
-protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-    if (requestCode == MY_REQUEST_CODE && resultCode == RESULT_OK) {
-        String name = data.getStringExtra(AccountManage.KEY_ACCOUNT_NAME);
-        String type = data.getStringExtra(AccountManage.KEY_ACCOUNT_TYPE);
-        Account selectedAccount = new Account(name, type);
-        doSomethingWithSelectedAccount(selectedAccount);
-    }
-}
+AccountManager am = AccountManager.get(this); // "this" references the current Context
+
+Account[] accounts = am.getAccountsByType("com.google");
 </pre>
 
+<p>This returns an array of {@link android.accounts.Account} objects. If there's more than one
+{@link android.accounts.Account} in
+the array, you should present a dialog asking the user to select one.</p>
+
+
 <h2 id="IdentifyUser">Use the Account Object to Personalize Your App</h2>
 
 <p>The {@link android.accounts.Account} object contains an account name, which for Google accounts
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index dfb8bb8..534121a 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -459,7 +459,7 @@
         // setHinting(DisplayMetrics.DENSITY_DEVICE >= DisplayMetrics.DENSITY_TV
         //        ? HINTING_OFF : HINTING_ON);
         mCompatScaling = mInvCompatScaling = 1;
-        setTextLocales(LocaleList.getDefault());
+        setTextLocales(LocaleList.getAdjustedDefault());
     }
 
     /**
@@ -500,7 +500,7 @@
         mInvCompatScaling = 1;
 
         mBidiFlags = BIDI_DEFAULT_LTR;
-        setTextLocales(LocaleList.getDefault());
+        setTextLocales(LocaleList.getAdjustedDefault());
         setElegantTextHeight(false);
         mFontFeatureSettings = null;
     }
@@ -1292,7 +1292,7 @@
      */
     @NonNull
     public Locale getTextLocale() {
-        return mLocales.getPrimary();
+        return mLocales.get(0);
     }
 
     /**
@@ -1317,7 +1317,7 @@
         if (locale == null) {
             throw new IllegalArgumentException("locale cannot be null");
         }
-        if (mLocales != null && mLocales.size() == 1 && locale.equals(mLocales.getPrimary())) {
+        if (mLocales != null && mLocales.size() == 1 && locale.equals(mLocales.get(0))) {
             return;
         }
         mLocales = new LocaleList(locale);
@@ -1340,8 +1340,8 @@
      * each language.
      *
      * By default, the text locale list is initialized to a one-member list just containing the
-     * system locale (as returned by {@link LocaleList#getDefault()}). This assumes that the text to
-     * be rendered will most likely be in the user's preferred language.
+     * system locales. This assumes that the text to be rendered will most likely be in the user's
+     * preferred language.
      *
      * If the actual language or languages of the text is/are known, then they can be provided to
      * the text renderer using this method. The text renderer may attempt to guess the
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index f036b19..0cde0b9 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -322,6 +322,34 @@
     }
 
     /**
+     * Insets the rectangle on all sides specified by the dimensions of the {@code insets}
+     * rectangle.
+     * @hide
+     * @param insets The rectangle specifying the insets on all side.
+     */
+    public void inset(Rect insets) {
+        left += insets.left;
+        top += insets.top;
+        right -= insets.right;
+        bottom -= insets.bottom;
+    }
+
+    /**
+     * Insets the rectangle on all sides specified by the insets.
+     * @hide
+     * @param left The amount to add from the rectangle's left
+     * @param top The amount to add from the rectangle's top
+     * @param right The amount to subtract from the rectangle's right
+     * @param bottom The amount to subtract from the rectangle's bottom
+     */
+    public void inset(int left, int top, int right, int bottom) {
+        this.left += left;
+        this.top += top;
+        this.right -= right;
+        this.bottom -= bottom;
+    }
+
+    /**
      * Returns true if (x,y) is inside the rectangle. The left and top are
      * considered to be inside, while the right and bottom are not. This means
      * that for a x,y to be contained: left <= x < right and top <= y < bottom.
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 1857345..af8ccf5 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -19,8 +19,14 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.Animator.AnimatorListener;
+import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ObjectAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityThread;
+import android.app.Application;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -31,17 +37,27 @@
 import android.graphics.Outline;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
+import android.os.Build;
 import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.LongArray;
+import android.util.PathParser;
+import android.util.TimeUtils;
+import android.view.Choreographer;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+import android.view.RenderNodeAnimatorSetHelper;
 import android.view.View;
 
 import com.android.internal.R;
 
+import com.android.internal.util.VirtualRefBasePtr;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
 /**
@@ -138,7 +154,7 @@
     private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
 
     /** Local, mutable animator set. */
-    private final AnimatorSet mAnimatorSet = new AnimatorSet();
+    private final VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimator();
 
     /**
      * The resources against which this drawable was created. Used to attempt
@@ -187,6 +203,24 @@
         mMutated = false;
     }
 
+    /**
+     * In order to avoid breaking old apps, we only throw exception on invalid VectorDrawable
+     * animations * for apps targeting N and later. For older apps, we ignore (i.e. quietly skip)
+     * these animations.
+     *
+     * @return whether invalid animations for vector drawable should be ignored.
+     */
+    private static boolean shouldIgnoreInvalidAnimation() {
+        Application app = ActivityThread.currentApplication();
+        if (app == null || app.getApplicationInfo() == null) {
+            return true;
+        }
+        if (app.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+            return true;
+        }
+        return false;
+    }
+
     @Override
     public ConstantState getConstantState() {
         mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations();
@@ -200,6 +234,9 @@
 
     @Override
     public void draw(Canvas canvas) {
+        if (canvas.isHardwareAccelerated()) {
+            mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas);
+        }
         mAnimatedVectorState.mVectorDrawable.draw(canvas);
         if (isStarted()) {
             invalidateSelf();
@@ -582,9 +619,8 @@
      * Resets the AnimatedVectorDrawable to the start state as specified in the animators.
      */
     public void reset() {
-        // TODO: Use reverse or seek to implement reset, when AnimatorSet supports them.
-        start();
-        mAnimatorSet.cancel();
+        mAnimatorSet.reset();
+        invalidateSelf();
     }
 
     @Override
@@ -603,8 +639,12 @@
     @NonNull
     private void ensureAnimatorSet() {
         if (!mHasAnimatorSet) {
-            mAnimatedVectorState.prepareLocalAnimators(mAnimatorSet, mRes);
+            // TODO: Skip the AnimatorSet creation and init the VectorDrawableAnimator directly
+            // with a list of LocalAnimators.
+            AnimatorSet set = new AnimatorSet();
+            mAnimatedVectorState.prepareLocalAnimators(set, mRes);
             mHasAnimatorSet = true;
+            mAnimatorSet.initWithAnimatorSet(set);
             mRes = null;
         }
     }
@@ -694,13 +734,13 @@
                 }
             };
         }
-        mAnimatorSet.addListener(mAnimatorListener);
+        mAnimatorSet.setListener(mAnimatorListener);
     }
 
     // A helper function to clean up the animator listener in the mAnimatorSet.
     private void removeAnimatorSetListener() {
         if (mAnimatorListener != null) {
-            mAnimatorSet.removeListener(mAnimatorListener);
+            mAnimatorSet.removeListener();
             mAnimatorListener = null;
         }
     }
@@ -730,4 +770,426 @@
         mAnimationCallbacks.clear();
     }
 
-}
\ No newline at end of file
+    /**
+     * @hide
+     */
+    public static class VectorDrawableAnimator {
+        private AnimatorListener mListener = null;
+        private final LongArray mStartDelays = new LongArray();
+        private PropertyValuesHolder.PropertyValues mTmpValues =
+                new PropertyValuesHolder.PropertyValues();
+        private long mSetPtr = 0;
+        private boolean mContainsSequentialAnimators = false;
+        private boolean mStarted = false;
+        private boolean mInitialized = false;
+        private boolean mAnimationPending = false;
+        private boolean mIsReversible = false;
+        // This needs to be set before parsing starts.
+        private boolean mShouldIgnoreInvalidAnim;
+        // TODO: Consider using NativeAllocationRegistery to track native allocation
+        private final VirtualRefBasePtr mSetRefBasePtr;
+        private WeakReference<RenderNode> mTarget = null;
+        private WeakReference<RenderNode> mLastSeenTarget = null;
+
+
+        VectorDrawableAnimator() {
+            mSetPtr = nCreateAnimatorSet();
+            // Increment ref count on native AnimatorSet, so it doesn't get released before Java
+            // side is done using it.
+            mSetRefBasePtr = new VirtualRefBasePtr(mSetPtr);
+        }
+
+        private void initWithAnimatorSet(AnimatorSet set) {
+            if (mInitialized) {
+                // Already initialized
+                throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
+                        "re-initialized");
+            }
+            mShouldIgnoreInvalidAnim = shouldIgnoreInvalidAnimation();
+            parseAnimatorSet(set, 0);
+            mInitialized = true;
+
+            // Check reversible.
+            if (mContainsSequentialAnimators) {
+                mIsReversible = false;
+            } else {
+                // Check if there's any start delay set on child
+                for (int i = 0; i < mStartDelays.size(); i++) {
+                    if (mStartDelays.get(i) > 0) {
+                        mIsReversible = false;
+                        return;
+                    }
+                }
+            }
+            mIsReversible = true;
+        }
+
+        private void parseAnimatorSet(AnimatorSet set, long startTime) {
+            ArrayList<Animator> animators = set.getChildAnimations();
+
+            boolean playTogether = set.shouldPlayTogether();
+            // Convert AnimatorSet to VectorDrawableAnimator
+            for (int i = 0; i < animators.size(); i++) {
+                Animator animator = animators.get(i);
+                // Here we only support ObjectAnimator
+                if (animator instanceof AnimatorSet) {
+                    parseAnimatorSet((AnimatorSet) animator, startTime);
+                } else if (animator instanceof ObjectAnimator) {
+                    createRTAnimator((ObjectAnimator) animator, startTime);
+                } // ignore ValueAnimators and others because they don't directly modify VD
+                  // therefore will be useless to AVD.
+
+                if (!playTogether) {
+                    // Assume not play together means play sequentially
+                    startTime += animator.getTotalDuration();
+                    mContainsSequentialAnimators = true;
+                }
+            }
+        }
+
+        // TODO: This method reads animation data from already parsed Animators. We need to move
+        // this step further up the chain in the parser to avoid the detour.
+        private void createRTAnimator(ObjectAnimator animator, long startTime) {
+            PropertyValuesHolder[] values = animator.getValues();
+            Object target = animator.getTarget();
+            if (target instanceof VectorDrawable.VGroup) {
+                createRTAnimatorForGroup(values, animator, (VectorDrawable.VGroup) target,
+                        startTime);
+            } else if (target instanceof VectorDrawable.VPath) {
+                for (int i = 0; i < values.length; i++) {
+                    values[i].getPropertyValues(mTmpValues);
+                    if (mTmpValues.endValue instanceof PathParser.PathData &&
+                            mTmpValues.propertyName.equals("pathData")) {
+                        createRTAnimatorForPath(animator, (VectorDrawable.VPath) target,
+                                startTime);
+                    }  else if (target instanceof VectorDrawable.VFullPath) {
+                        createRTAnimatorForFullPath(animator, (VectorDrawable.VFullPath) target,
+                                startTime);
+                    } else if (!mShouldIgnoreInvalidAnim) {
+                        throw new IllegalArgumentException("ClipPath only supports PathData " +
+                                "property");
+                    }
+
+                }
+            } else if (target instanceof VectorDrawable.VectorDrawableState) {
+                createRTAnimatorForRootGroup(values, animator,
+                        (VectorDrawable.VectorDrawableState) target, startTime);
+            } else if (!mShouldIgnoreInvalidAnim) {
+                // Should never get here
+                throw new UnsupportedOperationException("Target should be either VGroup, VPath, " +
+                        "or ConstantState, " + target == null ? "Null target" : target.getClass() +
+                        " is not supported");
+            }
+        }
+
+        private void createRTAnimatorForGroup(PropertyValuesHolder[] values,
+                ObjectAnimator animator, VectorDrawable.VGroup target,
+                long startTime) {
+
+            long nativePtr = target.getNativePtr();
+            int propertyId;
+            for (int i = 0; i < values.length; i++) {
+                // TODO: We need to support the rare case in AVD where no start value is provided
+                values[i].getPropertyValues(mTmpValues);
+                propertyId = VectorDrawable.VGroup.getPropertyIndex(mTmpValues.propertyName);
+                if (mTmpValues.type != Float.class && mTmpValues.type != float.class) {
+                    if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                        Log.e(LOGTAG, "Unsupported type: " +
+                                mTmpValues.type + ". Only float value is supported for Groups.");
+                    }
+                    continue;
+                }
+                if (propertyId < 0) {
+                    if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                        Log.e(LOGTAG, "Unsupported property: " +
+                                mTmpValues.propertyName + " for Vector Drawable Group");
+                    }
+                    continue;
+                }
+                long propertyPtr = nCreateGroupPropertyHolder(nativePtr, propertyId,
+                        (Float) mTmpValues.startValue, (Float) mTmpValues.endValue);
+                if (mTmpValues.dataSource != null) {
+                    float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator
+                            .getDuration());
+                    nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
+                }
+                createNativeChildAnimator(propertyPtr, startTime, animator);
+            }
+        }
+        private void createRTAnimatorForPath( ObjectAnimator animator, VectorDrawable.VPath target,
+                long startTime) {
+
+            long nativePtr = target.getNativePtr();
+            long startPathDataPtr = ((PathParser.PathData) mTmpValues.startValue)
+                    .getNativePtr();
+            long endPathDataPtr = ((PathParser.PathData) mTmpValues.endValue)
+                    .getNativePtr();
+            long propertyPtr = nCreatePathDataPropertyHolder(nativePtr, startPathDataPtr,
+                    endPathDataPtr);
+            createNativeChildAnimator(propertyPtr, startTime, animator);
+        }
+
+        private void createRTAnimatorForFullPath(ObjectAnimator animator,
+                VectorDrawable.VFullPath target, long startTime) {
+
+            int propertyId = target.getPropertyIndex(mTmpValues.propertyName);
+            long propertyPtr;
+            long nativePtr = target.getNativePtr();
+            if (mTmpValues.type == Float.class || mTmpValues.type == float.class) {
+                if (propertyId < 0) {
+                    if (mShouldIgnoreInvalidAnim) {
+                        return;
+                    } else {
+                        throw new IllegalArgumentException("Property: " + mTmpValues.propertyName
+                                + " is not supported for FullPath");
+                    }
+                }
+                propertyPtr = nCreatePathPropertyHolder(nativePtr, propertyId,
+                        (Float) mTmpValues.startValue, (Float) mTmpValues.endValue);
+
+            } else if (mTmpValues.type == Integer.class || mTmpValues.type == int.class) {
+                propertyPtr = nCreatePathColorPropertyHolder(nativePtr, propertyId,
+                        (Integer) mTmpValues.startValue, (Integer) mTmpValues.endValue);
+            } else {
+                if (mShouldIgnoreInvalidAnim) {
+                    return;
+                } else {
+                    throw new UnsupportedOperationException("Unsupported type: " +
+                            mTmpValues.type + ". Only float, int or PathData value is " +
+                            "supported for Paths.");
+                }
+            }
+            if (mTmpValues.dataSource != null) {
+                float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator
+                        .getDuration());
+                nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
+            }
+            createNativeChildAnimator(propertyPtr, startTime, animator);
+        }
+
+        private void createRTAnimatorForRootGroup(PropertyValuesHolder[] values,
+                ObjectAnimator animator, VectorDrawable.VectorDrawableState target,
+                long startTime) {
+                long nativePtr = target.getNativeRenderer();
+                if (!animator.getPropertyName().equals("alpha")) {
+                    if (mShouldIgnoreInvalidAnim) {
+                        return;
+                    } else {
+                        throw new UnsupportedOperationException("Only alpha is supported for root "
+                                + "group");
+                    }
+                }
+                Float startValue = null;
+                Float endValue = null;
+                for (int i = 0; i < values.length; i++) {
+                    values[i].getPropertyValues(mTmpValues);
+                    if (mTmpValues.propertyName.equals("alpha")) {
+                        startValue = (Float) mTmpValues.startValue;
+                        endValue = (Float) mTmpValues.endValue;
+                        break;
+                    }
+                }
+                if (startValue == null && endValue == null) {
+                    if (mShouldIgnoreInvalidAnim) {
+                        return;
+                    } else {
+                        throw new UnsupportedOperationException("No alpha values are specified");
+                    }
+                }
+                long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue);
+                createNativeChildAnimator(propertyPtr, startTime, animator);
+        }
+
+        // These are the data points that define the value of the animating properties.
+        // e.g. translateX and translateY can animate along a Path, at any fraction in [0, 1]
+        // a point on the path corresponds to the values of translateX and translateY.
+        // TODO: (Optimization) We should pass the path down in native and chop it into segments
+        // in native.
+        private static float[] createDataPoints(
+                PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) {
+            long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos();
+            int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS);
+            int numAnimFrames = (int) Math.ceil(((double) duration) / animIntervalMs);
+            float values[] = new float[numAnimFrames];
+            float lastFrame = numAnimFrames - 1;
+            for (int i = 0; i < numAnimFrames; i++) {
+                float fraction = i / lastFrame;
+                values[i] = (Float) dataSource.getValueAtFraction(fraction);
+            }
+            return values;
+        }
+
+        private void createNativeChildAnimator(long propertyPtr, long extraDelay,
+                                               ObjectAnimator animator) {
+            long duration = animator.getDuration();
+            int repeatCount = animator.getRepeatCount();
+            long startDelay = extraDelay + animator.getStartDelay();
+            TimeInterpolator interpolator = animator.getInterpolator();
+            long nativeInterpolator =
+                    RenderNodeAnimatorSetHelper.createNativeInterpolator(interpolator, duration);
+
+            startDelay *= ValueAnimator.getDurationScale();
+            duration *= ValueAnimator.getDurationScale();
+
+            mStartDelays.add(startDelay);
+            nAddAnimator(mSetPtr, propertyPtr, nativeInterpolator, startDelay, duration,
+                    repeatCount);
+        }
+
+        /**
+         * Holds a weak reference to the target that was last seen (through the DisplayListCanvas
+         * in the last draw call), so that when animator set needs to start, we can add the animator
+         * to the last seen RenderNode target and start right away.
+         */
+        protected void recordLastSeenTarget(DisplayListCanvas canvas) {
+            if (mAnimationPending) {
+                mLastSeenTarget = new WeakReference<RenderNode>(
+                        RenderNodeAnimatorSetHelper.getTarget(canvas));
+                if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                    Log.d(LOGTAG, "Target is set in the next frame");
+                }
+                mAnimationPending = false;
+                start();
+            } else {
+                mLastSeenTarget = new WeakReference<RenderNode>(
+                        RenderNodeAnimatorSetHelper.getTarget(canvas));
+            }
+
+        }
+
+        private boolean setTarget(RenderNode node) {
+            if (mTarget != null && mTarget.get() != null) {
+                // TODO: Maybe we want to support target change.
+                throw new IllegalStateException("Target already set!");
+            }
+
+            node.addAnimator(this);
+            mTarget = new WeakReference<RenderNode>(node);
+            return true;
+        }
+
+        private boolean useLastSeenTarget() {
+            if (mLastSeenTarget != null && mLastSeenTarget.get() != null) {
+                setTarget(mLastSeenTarget.get());
+                return true;
+            }
+            return false;
+        }
+
+        public void start() {
+            if (!mInitialized) {
+                return;
+            }
+
+            if (mStarted) {
+                return;
+            }
+
+            if (!useLastSeenTarget()) {
+                mAnimationPending = true;
+                return;
+            }
+
+            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
+            }
+
+           nStart(mSetPtr, this);
+            if (mListener != null) {
+                mListener.onAnimationStart(null);
+            }
+            mStarted = true;
+        }
+
+        public void end() {
+            if (mInitialized && mStarted) {
+                nEnd(mSetPtr);
+                onAnimationEnd();
+            }
+        }
+
+        void reset() {
+            if (!mInitialized) {
+                return;
+            }
+            // TODO: Need to implement reset.
+            Log.w(LOGTAG, "Reset is yet to be implemented");
+            nReset(mSetPtr);
+        }
+
+        // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential
+        // animators or when the animator set has a start delay
+        void reverse() {
+            if (!mIsReversible) {
+                return;
+            }
+            // TODO: Need to support reverse (non-public API)
+            Log.w(LOGTAG, "Reverse is yet to be implemented");
+            nReverse(mSetPtr, this);
+        }
+
+        public long getAnimatorNativePtr() {
+            return mSetPtr;
+        }
+
+        boolean canReverse() {
+            return mIsReversible;
+        }
+
+        boolean isStarted() {
+            return mStarted;
+        }
+
+        boolean isRunning() {
+            if (!mInitialized) {
+                return false;
+            }
+            return mStarted;
+        }
+
+        void setListener(AnimatorListener listener) {
+            mListener = listener;
+        }
+
+        void removeListener() {
+            mListener = null;
+        }
+
+        private void onAnimationEnd() {
+            mStarted = false;
+            if (mListener != null) {
+                mListener.onAnimationEnd(null);
+            }
+            mTarget = null;
+        }
+
+        // onFinished: should be called from native
+        private static void callOnFinished(VectorDrawableAnimator set) {
+            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                Log.d(LOGTAG, "on finished called from native");
+            }
+            set.onAnimationEnd();
+        }
+    }
+
+    private static native long nCreateAnimatorSet();
+    private static native void nAddAnimator(long setPtr, long propertyValuesHolder,
+             long nativeInterpolator, long startDelay, long duration, int repeatCount);
+
+    private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
+            float startValue, float endValue);
+
+    private static native long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
+            long endValuePtr);
+    private static native long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
+            int startValue, int endValue);
+    private static native long nCreatePathPropertyHolder(long nativePtr, int propertyId,
+            float startValue, float endValue);
+    private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
+            float endValue);
+    private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
+    private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set);
+    private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set);
+    private static native void nEnd(long animatorSetPtr);
+    private static native void nReset(long animatorSetPtr);
+}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 1fc1b83..bdbf3c0 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -39,6 +39,7 @@
 import android.util.Xml;
 
 import com.android.internal.R;
+import com.android.internal.util.VirtualRefBasePtr;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -47,6 +48,7 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Stack;
 
 /**
@@ -522,13 +524,13 @@
     public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
             @NonNull AttributeSet attrs, @Nullable Theme theme)
             throws XmlPullParserException, IOException {
-        if (mVectorState.mRootGroup != null || mVectorState.mNativeRendererPtr != 0) {
+        if (mVectorState.mRootGroup != null || mVectorState.mNativeRendererRefBase != null) {
             // This VD has been used to display other VD resource content, clean up.
             mVectorState.mRootGroup = new VGroup();
-            if (mVectorState.mNativeRendererPtr != 0) {
-                nDestroyRenderer(mVectorState.mNativeRendererPtr);
+            if (mVectorState.mNativeRendererRefBase != null) {
+                mVectorState.mNativeRendererRefBase.release();
             }
-            mVectorState.mNativeRendererPtr = nCreateRenderer(mVectorState.mRootGroup.mNativePtr);
+            mVectorState.createNativeRenderer(mVectorState.mRootGroup.mNativePtr);
         }
         final VectorDrawableState state = mVectorState;
         state.setDensity(Drawable.resolveDensity(r, 0));
@@ -707,7 +709,7 @@
         return mVectorState.mAutoMirrored;
     }
 
-    private static class VectorDrawableState extends ConstantState {
+    static class VectorDrawableState extends ConstantState {
         // Variables below need to be copied (deep copy if applicable) for mutation.
         int[] mThemeAttrs;
         int mChangingConfigurations;
@@ -722,7 +724,7 @@
         Insets mOpticalInsets = Insets.NONE;
         String mRootName = null;
         VGroup mRootGroup;
-        long mNativeRendererPtr;
+        VirtualRefBasePtr mNativeRendererRefBase = null;
 
         int mDensity = DisplayMetrics.DENSITY_DEFAULT;
         final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<>();
@@ -743,7 +745,7 @@
                 mTintMode = copy.mTintMode;
                 mAutoMirrored = copy.mAutoMirrored;
                 mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
-                mNativeRendererPtr = nCreateRenderer(mRootGroup.mNativePtr);
+                createNativeRenderer(mRootGroup.mNativePtr);
 
                 mBaseWidth = copy.mBaseWidth;
                 mBaseHeight = copy.mBaseHeight;
@@ -758,18 +760,15 @@
             }
         }
 
-        @Override
-        public void finalize() throws Throwable {
-            if (mNativeRendererPtr != 0) {
-                nDestroyRenderer(mNativeRendererPtr);
-                mNativeRendererPtr = 0;
-            }
-            super.finalize();
+        private void createNativeRenderer(long rootGroupPtr) {
+            mNativeRendererRefBase = new VirtualRefBasePtr(nCreateRenderer(rootGroupPtr));
         }
 
-
         long getNativeRenderer() {
-            return mNativeRendererPtr;
+            if (mNativeRendererRefBase == null) {
+                return 0;
+            }
+            return mNativeRendererRefBase.get();
         }
 
         public boolean canReuseCache() {
@@ -808,7 +807,7 @@
 
         public VectorDrawableState() {
             mRootGroup = new VGroup();
-            mNativeRendererPtr = nCreateRenderer(mRootGroup.mNativePtr);
+            createNativeRenderer(mRootGroup.mNativePtr);
         }
 
         @Override
@@ -872,16 +871,16 @@
          * has changed.
          */
         public boolean setAlpha(float alpha) {
-            return nSetRootAlpha(mNativeRendererPtr, alpha);
+            return nSetRootAlpha(mNativeRendererRefBase.get(), alpha);
         }
 
         @SuppressWarnings("unused")
         public float getAlpha() {
-            return nGetRootAlpha(mNativeRendererPtr);
+            return nGetRootAlpha(mNativeRendererRefBase.get());
         }
     }
 
-    private static class VGroup implements VObject {
+    static class VGroup implements VObject {
         private static final int ROTATE_INDEX = 0;
         private static final int PIVOT_X_INDEX = 1;
         private static final int PIVOT_Y_INDEX = 2;
@@ -891,6 +890,28 @@
         private static final int TRANSLATE_Y_INDEX = 6;
         private static final int TRANSFORM_PROPERTY_COUNT = 7;
 
+        private static final HashMap<String, Integer> sPropertyMap =
+                new HashMap<String, Integer>() {
+                    {
+                        put("translateX", TRANSLATE_X_INDEX);
+                        put("translateY", TRANSLATE_Y_INDEX);
+                        put("scaleX", SCALE_X_INDEX);
+                        put("scaleY", SCALE_Y_INDEX);
+                        put("pivotX", PIVOT_X_INDEX);
+                        put("pivotY", PIVOT_Y_INDEX);
+                        put("rotation", ROTATE_INDEX);
+                    }
+                };
+
+        static int getPropertyIndex(String propertyName) {
+            if (sPropertyMap.containsKey(propertyName)) {
+                return sPropertyMap.get(propertyName);
+            } else {
+                // property not found
+                return -1;
+            }
+        }
+
         // Temp array to store transform values obtained from native.
         private float[] mTransform;
         /////////////////////////////////////////////////////
@@ -903,8 +924,11 @@
         private int mChangingConfigurations;
         private int[] mThemeAttrs;
         private String mGroupName = null;
-        private long mNativePtr = 0;
 
+        // The native object will be created in the constructor and will be destroyed in native
+        // when the neither java nor native has ref to the tree. This pointer should be valid
+        // throughout this VGroup Java object's life.
+        private final long mNativePtr;
         public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
 
             mIsStateful = copy.mIsStateful;
@@ -1044,16 +1068,6 @@
         }
 
         @Override
-        protected void finalize() throws Throwable {
-            if (mNativePtr != 0) {
-                nDestroy(mNativePtr);
-                mNativePtr = 0;
-            }
-            super.finalize();
-        }
-
-
-        @Override
         public void applyTheme(Theme t) {
             if (mThemeAttrs != null) {
                 final TypedArray a = t.resolveAttributes(mThemeAttrs,
@@ -1149,7 +1163,7 @@
     /**
      * Common Path information for clip path and normal path.
      */
-    private static abstract class VPath implements VObject {
+    static abstract class VPath implements VObject {
         protected PathParser.PathData mPathData = null;
 
         String mPathName;
@@ -1187,10 +1201,10 @@
      * Clip path, which only has name and pathData.
      */
     private static class VClipPath extends VPath {
-        long mNativePtr = 0;
+        private final long mNativePtr;
+
         public VClipPath() {
             mNativePtr = nCreateClipPath();
-            // Empty constructor.
         }
 
         public VClipPath(VClipPath copy) {
@@ -1204,14 +1218,6 @@
         }
 
         @Override
-        protected void finalize() throws Throwable {
-            if (mNativePtr != 0) {
-                nDestroy(mNativePtr);
-                mNativePtr = 0;
-            }
-            super.finalize();
-        }
-        @Override
         public void inflate(Resources r, AttributeSet attrs, Theme theme) {
             final TypedArray a = obtainAttributes(r, theme, attrs,
                     R.styleable.VectorDrawableClipPath);
@@ -1260,7 +1266,7 @@
     /**
      * Normal path, which contains all the fill / paint information.
      */
-    private static class VFullPath extends VPath {
+    static class VFullPath extends VPath {
         private static final int STROKE_WIDTH_INDEX = 0;
         private static final int STROKE_COLOR_INDEX = 1;
         private static final int STROKE_ALPHA_INDEX = 2;
@@ -1274,6 +1280,20 @@
         private static final int STROKE_MITER_LIMIT_INDEX = 10;
         private static final int TOTAL_PROPERTY_COUNT = 11;
 
+        private final static HashMap<String, Integer> sPropertyMap
+                = new HashMap<String, Integer> () {
+            {
+                put("strokeWidth", STROKE_WIDTH_INDEX);
+                put("strokeColor", STROKE_COLOR_INDEX);
+                put("strokeAlpha", STROKE_ALPHA_INDEX);
+                put("fillColor", FILL_COLOR_INDEX);
+                put("fillAlpha", FILL_ALPHA_INDEX);
+                put("trimPathStart", TRIM_PATH_START_INDEX);
+                put("trimPathEnd", TRIM_PATH_END_INDEX);
+                put("trimPathOffset", TRIM_PATH_OFFSET_INDEX);
+            }
+        };
+
         // Temp array to store property data obtained from native getter.
         private byte[] mPropertyData;
         /////////////////////////////////////////////////////
@@ -1282,10 +1302,9 @@
 
         ComplexColor mStrokeColors = null;
         ComplexColor mFillColors = null;
-        private long mNativePtr = 0;
+        private final long mNativePtr;
 
         public VFullPath() {
-            // Empty constructor.
             mNativePtr = nCreateFullPath();
         }
 
@@ -1297,6 +1316,14 @@
             mFillColors = copy.mFillColors;
         }
 
+        int getPropertyIndex(String propertyName) {
+            if (!sPropertyMap.containsKey(propertyName)) {
+                return -1;
+            } else {
+                return sPropertyMap.get(propertyName);
+            }
+        }
+
         @Override
         public boolean onStateChange(int[] stateSet) {
             boolean changed = false;
@@ -1341,15 +1368,6 @@
             a.recycle();
         }
 
-        @Override
-        protected void finalize() throws Throwable {
-            if (mNativePtr != 0) {
-                nDestroy(mNativePtr);
-                mNativePtr = 0;
-            }
-            super.finalize();
-        }
-
         private void updateStateFromTypedArray(TypedArray a) {
             int byteCount = TOTAL_PROPERTY_COUNT * 4;
             if (mPropertyData == null) {
@@ -1595,7 +1613,6 @@
     }
 
     private static native long nCreateRenderer(long rootGroupPtr);
-    private static native void nDestroyRenderer(long rendererPtr);
     private static native void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
             float viewportHeight);
     private static native boolean nSetRootAlpha(long rendererPtr, float alpha);
@@ -1605,7 +1622,7 @@
     private static native void nDraw(long rendererPtr, long canvasWrapperPtr,
             long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache);
     private static native long nCreateFullPath();
-    private static native long nCreateFullPath(long mNativeFullPathPtr);
+    private static native long nCreateFullPath(long nativeFullPathPtr);
     private static native boolean nGetFullPathProperties(long pathPtr, byte[] properties,
             int length);
 
@@ -1621,7 +1638,6 @@
 
     private static native long nCreateGroup();
     private static native long nCreateGroup(long groupPtr);
-    private static native void nDestroy(long nodePtr);
     private static native void nSetName(long nodePtr, String name);
     private static native boolean nGetGroupProperties(long groupPtr, float[] properties,
             int length);
diff --git a/include/androidfw/LocaleData.h b/include/androidfw/LocaleData.h
index add0ab5..b14829d 100644
--- a/include/androidfw/LocaleData.h
+++ b/include/androidfw/LocaleData.h
@@ -29,6 +29,8 @@
 
 void localeDataComputeScript(char out[4], const char* language, const char* region);
 
+bool localeDataIsCloseToUsEnglish(const char* region);
+
 } // namespace android
 
 #endif // _LIBS_UTILS_LOCALE_DATA_H
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index 7cf4b04..d726880 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -269,7 +269,7 @@
 
     /**
      * Returns {@code true} if the requirement that this key can only be used if the user has been
-     * authenticated if enforced by secure hardware (e.g., Trusted Execution Environment (TEE) or
+     * authenticated is enforced by secure hardware (e.g., Trusted Execution Environment (TEE) or
      * Secure Element (SE)).
      *
      * @see #isUserAuthenticationRequired()
diff --git a/libs/androidfw/LocaleData.cpp b/libs/androidfw/LocaleData.cpp
index c0c3ab8..038ef58 100644
--- a/libs/androidfw/LocaleData.cpp
+++ b/libs/androidfw/LocaleData.cpp
@@ -70,13 +70,17 @@
 //
 // Returns the number of ancestors written in the output, which is always
 // at least one.
+//
+// (If 'out' is nullptr, we do everything the same way but we simply don't write
+// any results in 'out'.)
 size_t findAncestors(uint32_t* out, ssize_t* stop_list_index,
                      uint32_t packed_locale, const char* script,
                      const uint32_t* stop_list, size_t stop_set_length) {
     uint32_t ancestor = packed_locale;
     size_t count = 0;
     do {
-        out[count++] = ancestor;
+        if (out != nullptr) out[count] = ancestor;
+        count++;
         for (size_t i = 0; i < stop_set_length; i++) {
             if (stop_list[i] == ancestor) {
                 *stop_list_index = (ssize_t) i;
@@ -93,10 +97,9 @@
                     const char* script,
                     const uint32_t* request_ancestors,
                     size_t request_ancestors_count) {
-    uint32_t supported_ancestors[MAX_PARENT_DEPTH+1];
     ssize_t request_ancestors_index;
     const size_t supported_ancestor_count = findAncestors(
-            supported_ancestors, &request_ancestors_index,
+            nullptr, &request_ancestors_index,
             supported, script,
             request_ancestors, request_ancestors_count);
     // Since both locales share the same root, there will always be a shared
@@ -198,4 +201,19 @@
     }
 }
 
+const uint32_t ENGLISH_STOP_LIST[2] = {
+    0x656E0000lu, // en
+    0x656E8400lu, // en-001
+};
+const char ENGLISH_CHARS[2] = {'e', 'n'};
+const char LATIN_CHARS[4] = {'L', 'a', 't', 'n'};
+
+bool localeDataIsCloseToUsEnglish(const char* region) {
+    const uint32_t locale = packLocale(ENGLISH_CHARS, region);
+    ssize_t stop_list_index;
+    findAncestors(nullptr, &stop_list_index, locale, LATIN_CHARS, ENGLISH_STOP_LIST, 2);
+    // A locale is like US English if we see "en" before "en-001" in its ancestor list.
+    return stop_list_index == 0; // 'en' is first in ENGLISH_STOP_LIST
+}
+
 } // namespace android
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 71e9c92..1d9fe35 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2196,7 +2196,32 @@
         // The languages of the two resources are not the same. We can only
         // assume that one of the two resources matched the request because one
         // doesn't have a language and the other has a matching language.
-        return (language[0] != 0);
+        //
+        // We consider the one that has the language specified a better match.
+        //
+        // The exception is that we consider no-language resources a better match
+        // for US English and similar locales than locales that are a descendant
+        // of Internatinal English (en-001), since no-language resources are
+        // where the US English resource have traditionally lived for most apps.
+        if (requested->language[0] == 'e' && requested->language[1] == 'n') {
+            if (requested->country[0] == 'U' && requested->country[1] == 'S') {
+                // For US English itself, we consider a no-locale resource a
+                // better match if the other resource has a country other than
+                // US specified.
+                if (language[0] != '\0') {
+                    return country[0] == '\0' || (country[0] == 'U' && country[1] == 'S');
+                } else {
+                    return !(o.country[0] == '\0' || (o.country[0] == 'U' && o.country[1] == 'S'));
+                }
+            } else if (localeDataIsCloseToUsEnglish(requested->country)) {
+                if (language[0] != '\0') {
+                    return localeDataIsCloseToUsEnglish(country);
+                } else {
+                    return !localeDataIsCloseToUsEnglish(o.country);
+                }
+            }
+        }
+        return (language[0] != '\0');
     }
 
     // If we are here, both the resources have the same non-empty language as
diff --git a/libs/androidfw/tests/ConfigLocale_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp
index 1941563..7b38640 100644
--- a/libs/androidfw/tests/ConfigLocale_test.cpp
+++ b/libs/androidfw/tests/ConfigLocale_test.cpp
@@ -592,4 +592,52 @@
     EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
 }
 
+// Default resources are considered better matches for US English
+// and US-like English locales than International English locales
+TEST(ConfigLocaleTest, isLocaleBetterThan_UsEnglishIsSpecial) {
+    ResTable_config config1, config2, request;
+
+    fillIn("en", "US", NULL, NULL, &request);
+    fillIn(NULL, NULL, NULL, NULL, &config1);
+    fillIn("en", "001", NULL, NULL, &config2);
+    // default is better than International English
+    EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+    EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+    fillIn("en", "US", NULL, NULL, &request);
+    fillIn(NULL, NULL, NULL, NULL, &config1);
+    fillIn("en", "GB", NULL, NULL, &config2);
+    // default is better than British English
+    EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+    EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+    fillIn("en", "PR", NULL, NULL, &request);
+    fillIn(NULL, NULL, NULL, NULL, &config1);
+    fillIn("en", "001", NULL, NULL, &config2);
+    // Even for Puerto Rico, default is better than International English
+    EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+    EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+    fillIn("en", "US", NULL, NULL, &request);
+    fillIn("en", NULL, NULL, NULL, &config1);
+    fillIn(NULL, NULL, NULL, NULL, &config2);
+    // "English" is better than default, since it's a parent of US English
+    EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+    EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+    fillIn("en", "PR", NULL, NULL, &request);
+    fillIn("en", NULL, NULL, NULL, &config1);
+    fillIn(NULL, NULL, NULL, NULL, &config2);
+    // "English" is better than default, since it's a parent of Puerto Rico English
+    EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+    EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+    fillIn("en", "US", NULL, NULL, &request);
+    fillIn(NULL, NULL, NULL, NULL, &config1);
+    fillIn("en", "PR", NULL, NULL, &config2);
+    // For US English itself, we prefer default to its siblings in the parent tree
+    EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+    EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+}
+
 }  // namespace android
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index fc40554..7b43947 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -78,6 +78,8 @@
     Program.cpp \
     ProgramCache.cpp \
     Properties.cpp \
+    PropertyValuesHolder.cpp \
+    PropertyValuesAnimatorSet.cpp \
     RenderBufferCache.cpp \
     RenderNode.cpp \
     RenderProperties.cpp \
@@ -236,6 +238,7 @@
 
 LOCAL_SRC_FILES += \
     $(hwui_test_common_src_files) \
+    tests/unit/BufferPoolTests.cpp \
     tests/unit/CanvasStateTests.cpp \
     tests/unit/ClipAreaTests.cpp \
     tests/unit/CrashHandlerInjector.cpp \
@@ -245,10 +248,12 @@
     tests/unit/GpuMemoryTrackerTests.cpp \
     tests/unit/LayerUpdateQueueTests.cpp \
     tests/unit/LinearAllocatorTests.cpp \
-    tests/unit/VectorDrawableTests.cpp \
     tests/unit/OffscreenBufferPoolTests.cpp \
+    tests/unit/SkiaBehaviorTests.cpp \
     tests/unit/StringUtilsTests.cpp \
-    tests/unit/BufferPoolTests.cpp
+    tests/unit/TextDropShadowCacheTests.cpp \
+    tests/unit/VectorDrawableTests.cpp \
+    tests/unit/GradientCacheTests.cpp
 
 ifeq (true, $(HWUI_NEW_OPS))
     LOCAL_SRC_FILES += \
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 5ca2a2f..7bd2b24 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -90,6 +90,9 @@
         doSetStartValue(getValue(mTarget));
     }
     if (mStagingPlayState > mPlayState) {
+        if (mStagingPlayState == PlayState::Restarted) {
+            mStagingPlayState = PlayState::Running;
+        }
         mPlayState = mStagingPlayState;
         // Oh boy, we're starting! Man the battle stations!
         if (mPlayState == PlayState::Running) {
@@ -131,6 +134,11 @@
         return true;
     }
 
+    // This should be set before setValue() so animators can query this time when setValue
+    // is called.
+    nsecs_t currentFrameTime = context.frameTimeMs();
+    onPlayTimeChanged(currentFrameTime - mStartTime);
+
     // If BaseRenderNodeAnimator is handling the delay (not typical), then
     // because the staging properties reflect the final value, we always need
     // to call setValue even if the animation isn't yet running or is still
@@ -141,8 +149,9 @@
     }
 
     float fraction = 1.0f;
+
     if (mPlayState == PlayState::Running && mDuration > 0) {
-        fraction = (float)(context.frameTimeMs() - mStartTime) / mDuration;
+        fraction = (float)(currentFrameTime - mStartTime) / mDuration;
     }
     if (fraction >= 1.0f) {
         fraction = 1.0f;
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index aea95bf..2c9c9c3 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -59,7 +59,13 @@
         mMayRunAsync = mayRunAsync;
     }
     bool mayRunAsync() { return mMayRunAsync; }
-    ANDROID_API void start() { mStagingPlayState = PlayState::Running; onStagingPlayStateChanged(); }
+    ANDROID_API void start() {
+        if (mStagingPlayState == PlayState::NotStarted) {
+            mStagingPlayState = PlayState::Running;
+        } else {
+            mStagingPlayState = PlayState::Restarted;
+        }
+        onStagingPlayStateChanged(); }
     ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); }
 
     void attach(RenderNode* target);
@@ -77,10 +83,27 @@
     void forceEndNow(AnimationContext& context);
 
 protected:
+    // PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI
+    // thread and Render Thread animation state, respectively.
+    // From the UI thread, mStagingPlayState transition looks like
+    // NotStarted -> Running -> Finished
+    //                ^            |
+    //                |            |
+    //            Restarted <------
+    // Note: For mStagingState, the Finished state (optional) is only set when the animation is
+    // terminated by user.
+    //
+    // On Render Thread, mPlayState transition:
+    // NotStart -> Running -> Finished
+    //                ^            |
+    //                |            |
+    //                -------------
+
     enum class PlayState {
         NotStarted,
         Running,
         Finished,
+        Restarted,
     };
 
     BaseRenderNodeAnimator(float finalValue);
@@ -93,6 +116,7 @@
     void callOnFinishedListener(AnimationContext& context);
 
     virtual void onStagingPlayStateChanged() {}
+    virtual void onPlayTimeChanged(nsecs_t playTime) {}
 
     RenderNode* mTarget;
 
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 7ecc743..e3a5f3e 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -663,13 +663,7 @@
 }
 
 void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) {
-    TessellationCache::vertexBuffer_pair_t buffers;
-    renderer.caches().tessellationCache.getShadowBuffers(&state.computedState.transform,
-            op.localClipRect, op.casterAlpha >= 1.0f, op.casterPath,
-            &op.shadowMatrixXY, &op.shadowMatrixZ,
-            op.lightCenter, renderer.getLightInfo().lightRadius,
-            buffers);
-
+    TessellationCache::vertexBuffer_pair_t buffers = op.shadowTask->getResult();
     renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second);
 }
 
@@ -734,23 +728,34 @@
 }
 
 void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) {
+    // Note that we don't use op->paint in this function - it's never set on a LayerOp
     OffscreenBuffer* buffer = *op.layerHandle;
 
-    // Note that we don't use op->paint here - it's never set on a LayerOp
-    float layerAlpha = op.alpha * state.alpha;
-    Glop glop;
-    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
-            .setRoundRectClipState(state.roundRectClipState)
-            .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount)
-            .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap)
-            .setTransform(state.computedState.transform, TransformFlags::None)
-            .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
-                    Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
-            .build();
-    renderer.renderGlop(state, glop);
+    if (CC_UNLIKELY(!buffer)) {
+        // Layer was not allocated, which can occur if there were no draw ops inside. We draw the
+        // equivalent by drawing a rect with the same layer properties (alpha/xfer/filter).
+        SkPaint paint;
+        paint.setAlpha(op.alpha * 255);
+        paint.setXfermodeMode(op.mode);
+        paint.setColorFilter(op.colorFilter);
+        RectOp rectOp(op.unmappedBounds, op.localMatrix, op.localClip, &paint);
+        BakedOpDispatcher::onRectOp(renderer, rectOp, state);
+    } else {
+        float layerAlpha = op.alpha * state.alpha;
+        Glop glop;
+        GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
+                .setRoundRectClipState(state.roundRectClipState)
+                .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount)
+                .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap)
+                .setTransform(state.computedState.transform, TransformFlags::None)
+                .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
+                        Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
+                .build();
+        renderer.renderGlop(state, glop);
 
-    if (op.destroy) {
-        renderer.renderState().layerPool().putOrDelete(buffer);
+        if (op.destroy) {
+            renderer.renderState().layerPool().putOrDelete(buffer);
+        }
     }
 }
 
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 10c4698..55ea935 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -45,13 +45,11 @@
      * Position agnostic shadow lighting info. Used with all shadow ops in scene.
      */
     struct LightInfo {
-        LightInfo() : LightInfo(0, 0, 0) {}
-        LightInfo(float lightRadius, uint8_t ambientShadowAlpha,
+        LightInfo() : LightInfo(0, 0) {}
+        LightInfo(uint8_t ambientShadowAlpha,
                 uint8_t spotShadowAlpha)
-                : lightRadius(lightRadius)
-                , ambientShadowAlpha(ambientShadowAlpha)
+                : ambientShadowAlpha(ambientShadowAlpha)
                 , spotShadowAlpha(spotShadowAlpha) {}
-        float lightRadius;
         uint8_t ambientShadowAlpha;
         uint8_t spotShadowAlpha;
     };
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index 87844f9..a542c26 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -63,16 +63,11 @@
     }
 }
 
-ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot) {
-    transform = *snapshot.transform;
-
-    // Since the op doesn't have known bounds, we conservatively set the mapped bounds
-    // to the current clipRect, and clipSideFlags to Full.
-    clipState = snapshot.mutateClipArea().serializeClip(allocator);
-    LOG_ALWAYS_FATAL_IF(!clipState, "clipState required");
-    clippedBounds = clipState->rect;
-    clipSideFlags = OpClipSideFlags::Full;
-}
+ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot)
+        : transform(*snapshot.transform)
+        , clipState(snapshot.mutateClipArea().serializeClip(allocator))
+        , clippedBounds(clipState->rect)
+        , clipSideFlags(OpClipSideFlags::Full) {}
 
 ResolvedRenderState::ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect)
         : transform(Matrix4::identity())
diff --git a/libs/hwui/Canvas.cpp b/libs/hwui/Canvas.cpp
index bc88c81..11ae1a1 100644
--- a/libs/hwui/Canvas.cpp
+++ b/libs/hwui/Canvas.cpp
@@ -16,10 +16,20 @@
 
 #include "Canvas.h"
 
+#include "DisplayListCanvas.h"
+#include "RecordingCanvas.h"
 #include <SkDrawFilter.h>
 
 namespace android {
 
+Canvas* Canvas::create_recording_canvas(int width, int height) {
+#if HWUI_NEW_OPS
+    return new uirenderer::RecordingCanvas(width, height);
+#else
+    return new uirenderer::DisplayListCanvas(width, height);
+#endif
+}
+
 void Canvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
     uint32_t flags;
     SkDrawFilter* drawFilter = getDrawFilter();
diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h
index 9dfe454..27facdf 100644
--- a/libs/hwui/Canvas.h
+++ b/libs/hwui/Canvas.h
@@ -18,6 +18,7 @@
 #define ANDROID_GRAPHICS_CANVAS_H
 
 #include <cutils/compiler.h>
+#include <utils/Functor.h>
 
 #include "utils/NinePatch.h"
 
@@ -27,6 +28,14 @@
 
 namespace android {
 
+namespace uirenderer {
+    class CanvasPropertyPaint;
+    class CanvasPropertyPrimitive;
+    class DeferredLayerUpdater;
+    class DisplayList;
+    class RenderNode;
+}
+
 namespace SaveFlags {
 
 // These must match the corresponding Canvas API constants.
@@ -43,12 +52,21 @@
 
 } // namespace SaveFlags
 
+namespace uirenderer {
+namespace VectorDrawable {
+class Tree;
+};
+};
+typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
+
 class ANDROID_API Canvas {
 public:
     virtual ~Canvas() {};
 
     static Canvas* create_canvas(const SkBitmap& bitmap);
 
+    static Canvas* create_recording_canvas(int width, int height);
+
     /**
      *  Create a new Canvas object which delegates to an SkCanvas.
      *
@@ -74,15 +92,36 @@
      */
     virtual SkCanvas* asSkCanvas() = 0;
 
+
     virtual void setBitmap(const SkBitmap& bitmap) = 0;
 
     virtual bool isOpaque() = 0;
     virtual int width() = 0;
     virtual int height() = 0;
 
+// ----------------------------------------------------------------------------
+// View System operations (not exposed in public Canvas API)
+// ----------------------------------------------------------------------------
+
+    virtual void resetRecording(int width, int height) = 0;
+    virtual uirenderer::DisplayList* finishRecording() = 0;
+    virtual void insertReorderBarrier(bool enableReorder) = 0;
+
     virtual void setHighContrastText(bool highContrastText) = 0;
     virtual bool isHighContrastText() = 0;
 
+    virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
+            uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
+            uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
+            uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) = 0;
+    virtual void drawCircle(uirenderer::CanvasPropertyPrimitive* x,
+            uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius,
+            uirenderer::CanvasPropertyPaint* paint) = 0;
+
+    virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0;
+    virtual void drawRenderNode(uirenderer::RenderNode* renderNode) = 0;
+    virtual void callDrawGLFunction(Functor* functor) = 0;
+
 // ----------------------------------------------------------------------------
 // Canvas state operations
 // ----------------------------------------------------------------------------
@@ -185,6 +224,11 @@
      */
     virtual bool drawTextAbsolutePos() const = 0;
 
+    /**
+     * Draws a VectorDrawable onto the canvas.
+     */
+    virtual void drawVectorDrawable(VectorDrawableRoot* tree);
+
 protected:
     void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
 };
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index 160090d..9c08b4d 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -213,6 +213,7 @@
 
 void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
         SkRegion::Op op) {
+    if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
     onClipUpdated();
     switch (mMode) {
     case ClipMode::Rectangle:
@@ -228,6 +229,7 @@
 }
 
 void ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
+    if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
     onClipUpdated();
     enterRegionMode();
     mClipRegion.op(region, op);
@@ -236,6 +238,7 @@
 
 void ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform,
         SkRegion::Op op) {
+    if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
     onClipUpdated();
     SkMatrix skTransform;
     transform->copyTo(skTransform);
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
index e44fc20..250296e 100644
--- a/libs/hwui/DamageAccumulator.h
+++ b/libs/hwui/DamageAccumulator.h
@@ -57,7 +57,7 @@
     // Returns the current dirty area, *NOT* transformed by pushed transforms
     void peekAtDirty(SkRect* dest) const;
 
-    void computeCurrentTransform(Matrix4* outMatrix) const;
+    ANDROID_API void computeCurrentTransform(Matrix4* outMatrix) const;
 
     void finish(SkRect* totalDirty);
 
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 384e64d..3db14b5 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -16,11 +16,12 @@
 
 #include "DisplayListCanvas.h"
 
-#include "ResourceCache.h"
 #include "DeferredDisplayList.h"
 #include "DeferredLayerUpdater.h"
 #include "DisplayListOp.h"
+#include "ResourceCache.h"
 #include "RenderNode.h"
+#include "VectorDrawable.h"
 #include "utils/PaintUtils.h"
 
 #include <SkCamera.h>
@@ -41,7 +42,7 @@
     , mDeferredBarrierType(kBarrier_None)
     , mHighContrastText(false)
     , mRestoreSaveCount(-1) {
-    reset(width, height);
+    resetRecording(width, height);
 }
 
 DisplayListCanvas::~DisplayListCanvas() {
@@ -49,7 +50,7 @@
             "Destroyed a DisplayListCanvas during a record!");
 }
 
-void DisplayListCanvas::reset(int width, int height) {
+void DisplayListCanvas::resetRecording(int width, int height) {
     LOG_ALWAYS_FATAL_IF(mDisplayList,
             "prepareDirty called a second time during a recording!");
     mDisplayList = new DisplayList();
@@ -412,6 +413,16 @@
     addDrawOp(new (alloc()) DrawPointsOp(points, count, refPaint(&paint)));
 }
 
+void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
+    mDisplayList->ref(tree);
+    const SkBitmap& bitmap = tree->getBitmapUpdateIfDirty();
+    SkPaint* paint = tree->getPaint();
+    const SkRect bounds = tree->getBounds();
+    addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap),
+            0, 0, bitmap.width(), bitmap.height(),
+            bounds.left(), bounds.top(), bounds.right(), bounds.bottom(), refPaint(paint)));
+}
+
 void DisplayListCanvas::drawTextOnPath(const uint16_t* glyphs, int count,
         const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) {
     if (!glyphs || count <= 0) return;
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index f1cfa08..06e72a0 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -67,36 +67,33 @@
     DisplayListCanvas(int width, int height);
     virtual ~DisplayListCanvas();
 
-    void reset(int width, int height);
-    WARN_UNUSED_RESULT DisplayList* finishRecording();
+    virtual void resetRecording(int width, int height) override;
+    virtual WARN_UNUSED_RESULT DisplayList* finishRecording() override;
 
 // ----------------------------------------------------------------------------
 // HWUI Canvas state operations
 // ----------------------------------------------------------------------------
 
-    void insertReorderBarrier(bool enableReorder);
+    virtual void insertReorderBarrier(bool enableReorder) override;
 
 // ----------------------------------------------------------------------------
 // HWUI Canvas draw operations
 // ----------------------------------------------------------------------------
 
     // Shapes
-    void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
+    virtual void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
                 CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
                 CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
-                CanvasPropertyPaint* paint);
-    void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
-                CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
-
+                CanvasPropertyPaint* paint) override;
+    virtual void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+                CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) override;
 
 // ----------------------------------------------------------------------------
 // HWUI Canvas draw operations - special
 // ----------------------------------------------------------------------------
-    void drawLayer(DeferredLayerUpdater* layerHandle);
-    void drawRenderNode(RenderNode* renderNode);
-
-    // TODO: rename for consistency
-    void callDrawGLFunction(Functor* functor);
+    virtual void drawLayer(DeferredLayerUpdater* layerHandle) override;
+    virtual void drawRenderNode(RenderNode* renderNode) override;
+    virtual void callDrawGLFunction(Functor* functor) override;
 
 // ----------------------------------------------------------------------------
 // CanvasStateClient interface
@@ -209,6 +206,8 @@
             float dstLeft, float dstTop, float dstRight, float dstBottom,
             const SkPaint* paint) override;
 
+    virtual void drawVectorDrawable(VectorDrawableRoot* tree) override;
+
     // Text
     virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
             const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
@@ -217,7 +216,6 @@
             float hOffset, float vOffset, const SkPaint& paint) override;
     virtual bool drawTextAbsolutePos() const override { return false; }
 
-
 private:
 
     CanvasState mState;
diff --git a/libs/hwui/FboCache.cpp b/libs/hwui/FboCache.cpp
index cca3cb7..b2181b6 100644
--- a/libs/hwui/FboCache.cpp
+++ b/libs/hwui/FboCache.cpp
@@ -27,15 +27,8 @@
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
-FboCache::FboCache(): mMaxSize(DEFAULT_FBO_CACHE_SIZE) {
-    char property[PROPERTY_VALUE_MAX];
-    if (property_get(PROPERTY_FBO_CACHE_SIZE, property, nullptr) > 0) {
-        INIT_LOGD("  Setting fbo cache size to %s", property);
-        mMaxSize = atoi(property);
-    } else {
-        INIT_LOGD("  Using default fbo cache size of %d", DEFAULT_FBO_CACHE_SIZE);
-    }
-}
+FboCache::FboCache()
+        : mMaxSize(Properties::fboCacheSize) {}
 
 FboCache::~FboCache() {
     clear();
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index a457212..185acce 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -19,6 +19,7 @@
 #include "Canvas.h"
 #include "LayerUpdateQueue.h"
 #include "RenderNode.h"
+#include "VectorDrawable.h"
 #include "renderstate/OffscreenBufferPool.h"
 #include "utils/FatVector.h"
 #include "utils/PaintUtils.h"
@@ -32,17 +33,11 @@
 
 FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
         uint32_t viewportWidth, uint32_t viewportHeight,
-        const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter)
-        : FrameBuilder(layers, clip, viewportWidth, viewportHeight, nodes, lightCenter,
-                Rect(0, 0, 0, 0)) {
-}
-
-
-FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
-        uint32_t viewportWidth, uint32_t viewportHeight,
-        const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter,
-        const Rect &contentDrawBounds)
-        : mCanvasState(*this) {
+        const std::vector< sp<RenderNode> >& nodes,
+        const LightGeometry& lightGeometry, const Rect &contentDrawBounds, Caches* caches)
+        : mCanvasState(*this)
+        , mCaches(caches)
+        , mLightRadius(lightGeometry.radius) {
     ATRACE_NAME("prepare drawing commands");
 
     mLayerBuilders.reserve(layers.entries().size());
@@ -54,7 +49,7 @@
     mLayerStack.push_back(0);
     mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
             clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
-            lightCenter);
+            lightGeometry.center);
 
     // Render all layers to be updated, in order. Defer in reverse order, so that they'll be
     // updated in the order they're passed in (mLayerBuilders are issued to Renderer in reverse)
@@ -208,7 +203,9 @@
         mCanvasState.setClippingOutline(mAllocator, &(properties.getOutline()));
     }
 
-    if (!mCanvasState.quickRejectConservative(0, 0, width, height)) {
+    bool quickRejected = properties.getClipToBounds()
+            && mCanvasState.quickRejectConservative(0, 0, width, height);
+    if (!quickRejected) {
         // not rejected, so defer render as either Layer, or direct (possibly wrapped in saveLayer)
         if (node.getLayer()) {
             // HW layer
@@ -366,13 +363,28 @@
         casterPath = frameAllocatedPath;
     }
 
-    ShadowOp* shadowOp = new (mAllocator) ShadowOp(casterNodeOp, casterAlpha, casterPath,
-            mCanvasState.getLocalClipBounds(),
-            mCanvasState.currentSnapshot()->getRelativeLightCenter());
-    BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct(
-            mAllocator, *mCanvasState.writableSnapshot(), shadowOp);
-    if (CC_LIKELY(bakedOpState)) {
-        currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow);
+
+    if (CC_LIKELY(!mCanvasState.getRenderTargetClipBounds().isEmpty())) {
+        Matrix4 shadowMatrixXY(casterNodeOp.localMatrix);
+        Matrix4 shadowMatrixZ(casterNodeOp.localMatrix);
+        node.applyViewPropertyTransforms(shadowMatrixXY, false);
+        node.applyViewPropertyTransforms(shadowMatrixZ, true);
+
+        LOG_ALWAYS_FATAL_IF(!mCaches, "Caches needed for shadows");
+        sp<TessellationCache::ShadowTask> task = mCaches->tessellationCache.getShadowTask(
+                mCanvasState.currentTransform(),
+                mCanvasState.getLocalClipBounds(),
+                casterAlpha >= 1.0f,
+                casterPath,
+                &shadowMatrixXY, &shadowMatrixZ,
+                mCanvasState.currentSnapshot()->getRelativeLightCenter(),
+                mLightRadius);
+        ShadowOp* shadowOp = mAllocator.create<ShadowOp>(task, casterAlpha);
+        BakedOpState* bakedOpState = BakedOpState::tryShadowOpConstruct(
+                mAllocator, *mCanvasState.writableSnapshot(), shadowOp);
+        if (CC_LIKELY(bakedOpState)) {
+            currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow);
+        }
     }
 }
 
@@ -534,6 +546,18 @@
     currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
 }
 
+void FrameBuilder::deferVectorDrawableOp(const VectorDrawableOp& op) {
+    const SkBitmap& bitmap = op.vectorDrawable->getBitmapUpdateIfDirty();
+    SkPaint* paint = op.vectorDrawable->getPaint();
+    const BitmapRectOp* resolvedOp = new (mAllocator) BitmapRectOp(op.unmappedBounds,
+            op.localMatrix,
+            op.localClip,
+            paint,
+            &bitmap,
+            Rect(bitmap.width(), bitmap.height()));
+    deferBitmapRectOp(*resolvedOp);
+}
+
 void FrameBuilder::deferCirclePropsOp(const CirclePropsOp& op) {
     // allocate a temporary oval op (with mAllocator, so it persists until render), so the
     // renderer doesn't have to handle the RoundRectPropsOp type, and so state baking is simple.
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index dea9934..f44306a 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -55,14 +55,24 @@
  */
 class FrameBuilder : public CanvasStateClient {
 public:
+    struct LightGeometry {
+        Vector3 center;
+        float radius;
+    };
+
+    // TODO: remove
     FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
             uint32_t viewportWidth, uint32_t viewportHeight,
-            const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter);
+            const std::vector< sp<RenderNode> >& nodes,
+            const LightGeometry& lightGeometry,
+            Caches* caches)
+            : FrameBuilder(layers, clip, viewportWidth, viewportHeight, nodes, lightGeometry, Rect(), caches) {}
 
     FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
             uint32_t viewportWidth, uint32_t viewportHeight,
-            const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter,
-            const Rect &contentDrawBounds);
+            const std::vector< sp<RenderNode> >& nodes,
+            const LightGeometry& lightGeometry,
+            const Rect &contentDrawBounds, Caches* caches);
 
     virtual ~FrameBuilder() {}
 
@@ -114,7 +124,8 @@
                 layer.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
                 GL_CHECKPOINT(MODERATE);
                 renderer.endLayer();
-            } else if (!layer.empty()) { // save layer - skip entire layer if empty
+            } 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);
                 GL_CHECKPOINT(MODERATE);
                 layer.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
@@ -215,7 +226,11 @@
 
     CanvasState mCanvasState;
 
-    // contains ResolvedOps and Batches
+    Caches* mCaches = nullptr;
+
+    float mLightRadius;
+
+    // contains single-frame objects, such as BakedOpStates, LayerBuilders, Batches
     LinearAllocator mAllocator;
 };
 
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index e899ac7..11293d6 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -65,17 +65,9 @@
 GradientCache::GradientCache(Extensions& extensions)
         : mCache(LruCache<GradientCacheEntry, Texture*>::kUnlimitedCapacity)
         , mSize(0)
-        , mMaxSize(MB(DEFAULT_GRADIENT_CACHE_SIZE))
+        , mMaxSize(Properties::gradientCacheSize)
         , mUseFloatTexture(extensions.hasFloatTextures())
         , mHasNpot(extensions.hasNPot()){
-    char property[PROPERTY_VALUE_MAX];
-    if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, nullptr) > 0) {
-        INIT_LOGD("  Setting gradient cache size to %sMB", property);
-        setMaxSize(MB(atof(property)));
-    } else {
-        INIT_LOGD("  Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE);
-    }
-
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
 
     mCache.setOnEntryRemovedListener(this);
@@ -97,13 +89,6 @@
     return mMaxSize;
 }
 
-void GradientCache::setMaxSize(uint32_t maxSize) {
-    mMaxSize = maxSize;
-    while (mSize > mMaxSize) {
-        mCache.removeOldest();
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Callbacks
 ///////////////////////////////////////////////////////////////////////////////
@@ -168,10 +153,13 @@
     texture->blend = info.hasAlpha;
     texture->generation = 1;
 
-    // Asume the cache is always big enough
+    // Assume the cache is always big enough
     const uint32_t size = info.width * 2 * bytesPerPixel();
     while (getSize() + size > mMaxSize) {
-        mCache.removeOldest();
+        LOG_ALWAYS_FATAL_IF(!mCache.removeOldest(),
+                "Ran out of things to remove from the cache? getSize() = %" PRIu32
+                ", size = %" PRIu32 ", mMaxSize = %" PRIu32 ", width = %" PRIu32,
+                getSize(), size, mMaxSize, info.width);
     }
 
     generateTexture(colors, positions, info.width, 2, texture);
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index b762ca7..dccd450 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -123,10 +123,6 @@
     void clear();
 
     /**
-     * Sets the maximum size of the cache in bytes.
-     */
-    void setMaxSize(uint32_t maxSize);
-    /**
      * Returns the maximum size of the cache in bytes.
      */
     uint32_t getMaxSize();
@@ -177,7 +173,7 @@
     LruCache<GradientCacheEntry, Texture*> mCache;
 
     uint32_t mSize;
-    uint32_t mMaxSize;
+    const uint32_t mMaxSize;
 
     GLint mMaxTextureSize;
     bool mUseFloatTexture;
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index 9881280..bd6feb9 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -32,20 +32,12 @@
 
 PatchCache::PatchCache(RenderState& renderState)
         : mRenderState(renderState)
+        , mMaxSize(Properties::patchCacheSize)
         , mSize(0)
         , mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity)
         , mMeshBuffer(0)
         , mFreeBlocks(nullptr)
-        , mGenerationId(0) {
-    char property[PROPERTY_VALUE_MAX];
-    if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, nullptr) > 0) {
-        INIT_LOGD("  Setting patch cache size to %skB", property);
-        mMaxSize = KB(atoi(property));
-    } else {
-        INIT_LOGD("  Using default patch cache size of %.2fkB", DEFAULT_PATCH_CACHE_SIZE);
-        mMaxSize = KB(DEFAULT_PATCH_CACHE_SIZE);
-    }
-}
+        , mGenerationId(0) {}
 
 PatchCache::~PatchCache() {
     clear();
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 387f79a..66ef6a0 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -169,7 +169,7 @@
 #endif
 
     RenderState& mRenderState;
-    uint32_t mMaxSize;
+    const uint32_t mMaxSize;
     uint32_t mSize;
 
     LruCache<PatchDescription, Patch*> mCache;
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index bfabc1d..8f914ac 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -135,17 +135,10 @@
 // Cache constructor/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
-PathCache::PathCache():
-        mCache(LruCache<PathDescription, PathTexture*>::kUnlimitedCapacity),
-        mSize(0), mMaxSize(MB(DEFAULT_PATH_CACHE_SIZE)) {
-    char property[PROPERTY_VALUE_MAX];
-    if (property_get(PROPERTY_PATH_CACHE_SIZE, property, nullptr) > 0) {
-        INIT_LOGD("  Setting path cache size to %sMB", property);
-        mMaxSize = MB(atof(property));
-    } else {
-        INIT_LOGD("  Using default path cache size of %.2fMB", DEFAULT_PATH_CACHE_SIZE);
-    }
-
+PathCache::PathCache()
+        : mCache(LruCache<PathDescription, PathTexture*>::kUnlimitedCapacity)
+        , mSize(0)
+        , mMaxSize(Properties::pathCacheSize) {
     mCache.setOnEntryRemovedListener(this);
 
     GLint maxTextureSize;
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 18f380f..d2633aa 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -300,7 +300,7 @@
 
     LruCache<PathDescription, PathTexture*> mCache;
     uint32_t mSize;
-    uint32_t mMaxSize;
+    const uint32_t mMaxSize;
     GLuint mMaxTextureSize;
 
     bool mDebugEnabled;
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 083aeb7..bbd8c72 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -37,7 +37,18 @@
 bool Properties::enablePartialUpdates = true;
 
 float Properties::textGamma = DEFAULT_TEXT_GAMMA;
-int Properties::layerPoolSize = DEFAULT_LAYER_CACHE_SIZE;
+
+int Properties::fboCacheSize = DEFAULT_FBO_CACHE_SIZE;
+int Properties::gradientCacheSize = MB(DEFAULT_GRADIENT_CACHE_SIZE);
+int Properties::layerPoolSize = MB(DEFAULT_LAYER_CACHE_SIZE);
+int Properties::patchCacheSize = KB(DEFAULT_PATCH_CACHE_SIZE);
+int Properties::pathCacheSize = MB(DEFAULT_PATH_CACHE_SIZE);
+int Properties::renderBufferCacheSize = MB(DEFAULT_RENDER_BUFFER_CACHE_SIZE);
+int Properties::tessellationCacheSize = MB(DEFAULT_VERTEX_CACHE_SIZE);
+int Properties::textDropShadowCacheSize = MB(DEFAULT_DROP_SHADOW_CACHE_SIZE);
+int Properties::textureCacheSize = MB(DEFAULT_TEXTURE_CACHE_SIZE);
+
+float Properties::textureCacheFlushRate = DEFAULT_TEXTURE_CACHE_FLUSH_RATE;
 
 DebugLevel Properties::debugLevel = kDebugDisabled;
 OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default;
@@ -79,7 +90,6 @@
     bool prevDebugOverdraw = debugOverdraw;
     StencilClipDebug prevDebugStencilClip = debugStencilClip;
 
-
     debugOverdraw = false;
     if (property_get(PROPERTY_DEBUG_OVERDRAW, property, nullptr) > 0) {
         INIT_LOGD("  Overdraw debug enabled: %s", property);
@@ -133,7 +143,18 @@
     enablePartialUpdates = property_get_bool(PROPERTY_ENABLE_PARTIAL_UPDATES, true);
 
     textGamma = property_get_float(PROPERTY_TEXT_GAMMA, DEFAULT_TEXT_GAMMA);
+
+    fboCacheSize = property_get_int(PROPERTY_FBO_CACHE_SIZE, DEFAULT_FBO_CACHE_SIZE);
+    gradientCacheSize = MB(property_get_float(PROPERTY_GRADIENT_CACHE_SIZE, DEFAULT_GRADIENT_CACHE_SIZE));
     layerPoolSize = MB(property_get_float(PROPERTY_LAYER_CACHE_SIZE, DEFAULT_LAYER_CACHE_SIZE));
+    patchCacheSize = KB(property_get_float(PROPERTY_PATCH_CACHE_SIZE, DEFAULT_PATCH_CACHE_SIZE));
+    pathCacheSize = MB(property_get_float(PROPERTY_PATH_CACHE_SIZE, DEFAULT_PATH_CACHE_SIZE));
+    renderBufferCacheSize = MB(property_get_float(PROPERTY_RENDER_BUFFER_CACHE_SIZE, DEFAULT_RENDER_BUFFER_CACHE_SIZE));
+    tessellationCacheSize = MB(property_get_float(PROPERTY_VERTEX_CACHE_SIZE, DEFAULT_VERTEX_CACHE_SIZE));
+    textDropShadowCacheSize = MB(property_get_float(PROPERTY_DROP_SHADOW_CACHE_SIZE, DEFAULT_DROP_SHADOW_CACHE_SIZE));
+    textureCacheSize = MB(property_get_float(PROPERTY_TEXTURE_CACHE_SIZE, DEFAULT_TEXTURE_CACHE_SIZE));
+    textureCacheFlushRate = std::max(0.0f, std::min(1.0f,
+            property_get_float(PROPERTY_TEXTURE_CACHE_FLUSH_RATE, DEFAULT_TEXTURE_CACHE_FLUSH_RATE)));
 
     return (prevDebugLayersUpdates != debugLayersUpdates)
             || (prevDebugOverdraw != debugOverdraw)
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 88f1dbc..3e11151 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -267,7 +267,16 @@
 
     static float textGamma;
 
+    static int fboCacheSize;
+    static int gradientCacheSize;
     static int layerPoolSize;
+    static int patchCacheSize;
+    static int pathCacheSize;
+    static int renderBufferCacheSize;
+    static int tessellationCacheSize;
+    static int textDropShadowCacheSize;
+    static int textureCacheSize;
+    static float textureCacheFlushRate;
 
     static DebugLevel debugLevel;
     static OverdrawColorSet overdrawColorSet;
diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp
new file mode 100644
index 0000000..eca1afcc
--- /dev/null
+++ b/libs/hwui/PropertyValuesAnimatorSet.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PropertyValuesAnimatorSet.h"
+#include "RenderNode.h"
+
+namespace android {
+namespace uirenderer {
+
+void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
+            Interpolator* interpolator, nsecs_t startDelay,
+            nsecs_t duration, int repeatCount) {
+
+    PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder,
+            interpolator, startDelay, duration, repeatCount);
+    mAnimators.emplace_back(animator);
+    setListener(new PropertyAnimatorSetListener(this));
+}
+
+PropertyValuesAnimatorSet::PropertyValuesAnimatorSet()
+        : BaseRenderNodeAnimator(1.0f) {
+    setStartValue(0);
+    mLastFraction = 0.0f;
+    setInterpolator(new LinearInterpolator());
+}
+
+void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) {
+    if (mOneShotListener.get()) {
+        mOneShotListener->onAnimationFinished(animator);
+        mOneShotListener = nullptr;
+    }
+}
+
+float PropertyValuesAnimatorSet::getValue(RenderNode* target) const {
+    return mLastFraction;
+}
+
+void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) {
+    mLastFraction = value;
+}
+
+void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) {
+    for (size_t i = 0; i < mAnimators.size(); i++) {
+        mAnimators[i]->setCurrentPlayTime(playTime);
+    }
+}
+
+void PropertyValuesAnimatorSet::reset() {
+    // TODO: implement reset through adding a play state because we need to support reset() even
+    // during an animation run.
+}
+
+void PropertyValuesAnimatorSet::start(AnimationListener* listener) {
+    init();
+    mOneShotListener = listener;
+    BaseRenderNodeAnimator::start();
+}
+
+void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) {
+// TODO: implement reverse
+}
+
+void PropertyValuesAnimatorSet::init() {
+    if (mInitialized) {
+        return;
+    }
+    nsecs_t maxDuration = 0;
+    for (size_t i = 0; i < mAnimators.size(); i++) {
+        if (maxDuration < mAnimators[i]->getTotalDuration()) {
+            maxDuration = mAnimators[i]->getTotalDuration();
+        }
+    }
+    mDuration = maxDuration;
+    mInitialized = true;
+}
+
+uint32_t PropertyValuesAnimatorSet::dirtyMask() {
+    return RenderNode::DISPLAY_LIST;
+}
+
+PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator,
+        nsecs_t startDelay, nsecs_t duration, int repeatCount)
+        : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay),
+          mDuration(duration) {
+    if (repeatCount < 0) {
+        mRepeatCount = UINT32_MAX;
+    } else {
+        mRepeatCount = repeatCount;
+    }
+    mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay;
+}
+
+void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
+    if (playTime >= mStartDelay && playTime < mTotalDuration) {
+         nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration;
+         mLatestFraction = currentIterationPlayTime / (float) mDuration;
+    } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) {
+        mLatestFraction = 1.0f;
+    } else {
+        return;
+    }
+
+    setFraction(mLatestFraction);
+}
+
+void PropertyAnimator::setFraction(float fraction) {
+    float interpolatedFraction = mInterpolator->interpolate(mLatestFraction);
+    mPropertyValuesHolder->setFraction(interpolatedFraction);
+}
+
+void PropertyAnimatorSetListener::onAnimationFinished(BaseRenderNodeAnimator* animator) {
+    mSet->onFinished(animator);
+}
+
+}
+}
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
new file mode 100644
index 0000000..4c7ce52
--- /dev/null
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Animator.h"
+#include "PropertyValuesHolder.h"
+#include "Interpolator.h"
+
+namespace android {
+namespace uirenderer {
+
+class PropertyAnimator {
+public:
+    PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, nsecs_t startDelay,
+            nsecs_t duration, int repeatCount);
+    void setCurrentPlayTime(nsecs_t playTime);
+    nsecs_t getTotalDuration() {
+        return mTotalDuration;
+    }
+    void setFraction(float fraction);
+
+private:
+    std::unique_ptr<PropertyValuesHolder> mPropertyValuesHolder;
+    std::unique_ptr<Interpolator> mInterpolator;
+    nsecs_t mStartDelay;
+    nsecs_t mDuration;
+    uint32_t mRepeatCount;
+    nsecs_t mTotalDuration;
+    float mLatestFraction = 0.0f;
+};
+
+class ANDROID_API PropertyValuesAnimatorSet : public BaseRenderNodeAnimator {
+public:
+    friend class PropertyAnimatorSetListener;
+    PropertyValuesAnimatorSet();
+
+    void start(AnimationListener* listener);
+    void reverse(AnimationListener* listener);
+    void reset();
+
+    void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
+            Interpolator* interpolators, int64_t startDelays,
+            nsecs_t durations, int repeatCount);
+    virtual uint32_t dirtyMask();
+
+protected:
+    virtual float getValue(RenderNode* target) const override;
+    virtual void setValue(RenderNode* target, float value) override;
+    virtual void onPlayTimeChanged(nsecs_t playTime) override;
+
+private:
+    void init();
+    void onFinished(BaseRenderNodeAnimator* animator);
+    // Listener set from outside
+    sp<AnimationListener> mOneShotListener;
+    std::vector< std::unique_ptr<PropertyAnimator> > mAnimators;
+    float mLastFraction = 0.0f;
+    bool mInitialized = false;
+};
+
+class PropertyAnimatorSetListener : public AnimationListener {
+public:
+    PropertyAnimatorSetListener(PropertyValuesAnimatorSet* set) : mSet(set) {}
+    virtual void onAnimationFinished(BaseRenderNodeAnimator* animator) override;
+
+private:
+    PropertyValuesAnimatorSet* mSet;
+};
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp
new file mode 100644
index 0000000..8f837f6
--- /dev/null
+++ b/libs/hwui/PropertyValuesHolder.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PropertyValuesHolder.h"
+
+#include "utils/VectorDrawableUtils.h"
+
+#include <utils/Log.h>
+
+namespace android {
+namespace uirenderer {
+
+using namespace VectorDrawable;
+
+float PropertyValuesHolder::getValueFromData(float fraction) {
+    if (mDataSource.size() == 0) {
+        LOG_ALWAYS_FATAL("No data source is defined");
+        return 0;
+    }
+    if (fraction <= 0.0f) {
+        return mDataSource.front();
+    }
+    if (fraction >= 1.0f) {
+        return mDataSource.back();
+    }
+
+    fraction *= mDataSource.size() - 1;
+    int lowIndex = floor(fraction);
+    fraction -= lowIndex;
+
+    float value = mDataSource[lowIndex] * (1.0f - fraction)
+            + mDataSource[lowIndex + 1] * fraction;
+    return value;
+}
+
+void GroupPropertyValuesHolder::setFraction(float fraction) {
+    float animatedValue;
+    if (mDataSource.size() > 0) {
+        animatedValue = getValueFromData(fraction);
+    } else {
+        animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
+    }
+    mGroup->setPropertyValue(mPropertyId, animatedValue);
+}
+
+inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) {
+    return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction);
+}
+
+// TODO: Add a test for this
+SkColor FullPathColorPropertyValuesHolder::interpolateColors(SkColor fromColor, SkColor toColor,
+        float fraction) {
+    U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction);
+    U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction);
+    U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction);
+    U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction);
+    return SkColorSetARGB(alpha, red, green, blue);
+}
+
+void FullPathColorPropertyValuesHolder::setFraction(float fraction) {
+    SkColor animatedValue = interpolateColors(mStartValue, mEndValue, fraction);
+    mFullPath->setColorPropertyValue(mPropertyId, animatedValue);
+}
+
+void FullPathPropertyValuesHolder::setFraction(float fraction) {
+    float animatedValue;
+    if (mDataSource.size() > 0) {
+        animatedValue = getValueFromData(fraction);
+    } else {
+        animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
+    }
+    mFullPath->setPropertyValue(mPropertyId, animatedValue);
+}
+
+void PathDataPropertyValuesHolder::setFraction(float fraction) {
+    VectorDrawableUtils::interpolatePaths(&mPathData, mStartValue, mEndValue, fraction);
+    mPath->setPathData(mPathData);
+}
+
+void RootAlphaPropertyValuesHolder::setFraction(float fraction) {
+    float animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
+    mTree->setRootAlpha(animatedValue);
+}
+
+} // namepace uirenderer
+} // namespace android
diff --git a/libs/hwui/PropertyValuesHolder.h b/libs/hwui/PropertyValuesHolder.h
new file mode 100644
index 0000000..b905fae
--- /dev/null
+++ b/libs/hwui/PropertyValuesHolder.h
@@ -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.
+ */
+
+#pragma once
+
+#include "VectorDrawable.h"
+
+#include <SkColor.h>
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * PropertyValues holder contains data needed to change a property of a Vector Drawable object.
+ * When a fraction in [0f, 1f] is provided, the holder will calculate an interpolated value based
+ * on its start and end value, and set the new value on the VectorDrawble's corresponding property.
+ */
+class ANDROID_API PropertyValuesHolder {
+public:
+    virtual void setFraction(float fraction) = 0;
+    void setPropertyDataSource(float* dataSource, int length) {
+        mDataSource.insert(mDataSource.begin(), dataSource, dataSource + length);
+    }
+   float getValueFromData(float fraction);
+   virtual ~PropertyValuesHolder() {}
+protected:
+   std::vector<float> mDataSource;
+};
+
+class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolder {
+public:
+    GroupPropertyValuesHolder(VectorDrawable::Group* ptr, int propertyId, float startValue,
+            float endValue)
+            : mGroup(ptr)
+            , mPropertyId(propertyId)
+            , mStartValue(startValue)
+            , mEndValue(endValue){
+    }
+    void setFraction(float fraction) override;
+private:
+    VectorDrawable::Group* mGroup;
+    int mPropertyId;
+    float mStartValue;
+    float mEndValue;
+};
+
+class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolder {
+public:
+    FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, int32_t startValue,
+            int32_t endValue)
+            : mFullPath(ptr)
+            , mPropertyId(propertyId)
+            , mStartValue(startValue)
+            , mEndValue(endValue) {};
+    void setFraction(float fraction) override;
+    static SkColor interpolateColors(SkColor fromColor, SkColor toColor, float fraction);
+private:
+    VectorDrawable::FullPath* mFullPath;
+    int mPropertyId;
+    int32_t mStartValue;
+    int32_t mEndValue;
+};
+
+class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolder {
+public:
+    FullPathPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, float startValue,
+            float endValue)
+            : mFullPath(ptr)
+            , mPropertyId(propertyId)
+            , mStartValue(startValue)
+            , mEndValue(endValue) {};
+    void setFraction(float fraction) override;
+private:
+    VectorDrawable::FullPath* mFullPath;
+    int mPropertyId;
+    float mStartValue;
+    float mEndValue;
+};
+
+class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolder {
+public:
+    PathDataPropertyValuesHolder(VectorDrawable::Path* ptr, PathData* startValue,
+            PathData* endValue)
+            : mPath(ptr)
+            , mStartValue(*startValue)
+            , mEndValue(*endValue) {};
+    void setFraction(float fraction) override;
+private:
+    VectorDrawable::Path* mPath;
+    PathData mPathData;
+    PathData mStartValue;
+    PathData mEndValue;
+};
+
+class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolder {
+public:
+    RootAlphaPropertyValuesHolder(VectorDrawable::Tree* tree, float startValue, float endValue)
+            : mTree(tree)
+            , mStartValue(startValue)
+            , mEndValue(endValue) {}
+    void setFraction(float fraction) override;
+private:
+    VectorDrawable::Tree* mTree;
+    float mStartValue;
+    float mEndValue;
+};
+}
+}
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index 30d5c29..bb26e2e 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -17,10 +17,12 @@
 #ifndef ANDROID_HWUI_RECORDED_OP_H
 #define ANDROID_HWUI_RECORDED_OP_H
 
+#include "RecordedOp.h"
 #include "font/FontUtil.h"
 #include "Matrix.h"
 #include "Rect.h"
 #include "RenderNode.h"
+#include "TessellationCache.h"
 #include "utils/LinearAllocator.h"
 #include "Vector.h"
 
@@ -38,6 +40,10 @@
 class RenderNode;
 struct Vertex;
 
+namespace VectorDrawable {
+class Tree;
+}
+
 /**
  * Authoritative op list, used for generating the op ID enum, ID based LUTS, and
  * the functions to which they dispatch. Parameter macros are executed for each op,
@@ -74,6 +80,7 @@
         PRE_RENDER_OP_FN(EndLayerOp) \
         PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \
         PRE_RENDER_OP_FN(EndUnclippedLayerOp) \
+        PRE_RENDER_OP_FN(VectorDrawableOp) \
         \
         RENDER_ONLY_OP_FN(ShadowOp) \
         RENDER_ONLY_OP_FN(LayerOp) \
@@ -324,6 +331,13 @@
     const float* ry;
 };
 
+struct VectorDrawableOp : RecordedOp {
+    VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS)
+            : SUPER_PAINTLESS(VectorDrawableOp)
+            , vectorDrawable(tree) {}
+    VectorDrawable::Tree* vectorDrawable;
+};
+
 /**
  * Real-time, dynamic-lit shadow.
  *
@@ -333,25 +347,13 @@
  * State construction handles these properties specially, ignoring matrix/bounds.
  */
 struct ShadowOp : RecordedOp {
-    ShadowOp(const RenderNodeOp& casterOp, float casterAlpha, const SkPath* casterPath,
-            const Rect& localClipRect, const Vector3& lightCenter)
+    ShadowOp(sp<TessellationCache::ShadowTask>& shadowTask, float casterAlpha)
             : RecordedOp(RecordedOpId::ShadowOp, Rect(), Matrix4::identity(), nullptr, nullptr)
-            , shadowMatrixXY(casterOp.localMatrix)
-            , shadowMatrixZ(casterOp.localMatrix)
-            , casterAlpha(casterAlpha)
-            , casterPath(casterPath)
-            , localClipRect(localClipRect)
-            , lightCenter(lightCenter) {
-        const RenderNode& node = *casterOp.renderNode;
-        node.applyViewPropertyTransforms(shadowMatrixXY, false);
-        node.applyViewPropertyTransforms(shadowMatrixZ, true);
+            , shadowTask(shadowTask)
+            , casterAlpha(casterAlpha) {
     };
-    Matrix4 shadowMatrixXY;
-    Matrix4 shadowMatrixZ;
+    sp<TessellationCache::ShadowTask> shadowTask;
     const float casterAlpha;
-    const SkPath* casterPath;
-    const Rect localClipRect;
-    const Vector3 lightCenter;
 };
 
 struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 328e291..16929b8 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -19,6 +19,7 @@
 #include "DeferredLayerUpdater.h"
 #include "RecordedOp.h"
 #include "RenderNode.h"
+#include "VectorDrawable.h"
 
 namespace android {
 namespace uirenderer {
@@ -26,7 +27,7 @@
 RecordingCanvas::RecordingCanvas(size_t width, size_t height)
         : mState(*this)
         , mResourceCache(ResourceCache::getInstance()) {
-    reset(width, height);
+    resetRecording(width, height);
 }
 
 RecordingCanvas::~RecordingCanvas() {
@@ -34,7 +35,7 @@
             "Destroyed a RecordingCanvas during a record!");
 }
 
-void RecordingCanvas::reset(int width, int height) {
+void RecordingCanvas::resetRecording(int width, int height) {
     LOG_ALWAYS_FATAL_IF(mDisplayList,
             "prepareDirty called a second time during a recording!");
     mDisplayList = new DisplayList();
@@ -395,7 +396,6 @@
             &x->value, &y->value, &radius->value));
 }
 
-
 void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
     addOp(new (alloc()) OvalOp(
             Rect(left, top, right, bottom),
@@ -422,6 +422,15 @@
             refPaint(&paint), refPath(&path)));
 }
 
+void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
+    mDisplayList->ref(tree);
+    addOp(new (alloc()) VectorDrawableOp(
+            tree,
+            Rect(tree->getBounds()),
+            *(mState.currentSnapshot()->transform),
+            getRecordedClip()));
+}
+
 // Bitmap-based
 void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
     save(SaveFlags::Matrix);
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 786f96e..cc14e61 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -50,22 +50,19 @@
     RecordingCanvas(size_t width, size_t height);
     virtual ~RecordingCanvas();
 
-    void reset(int width, int height);
-    WARN_UNUSED_RESULT DisplayList* finishRecording();
-
+    virtual void resetRecording(int width, int height) override;
+    virtual WARN_UNUSED_RESULT DisplayList* finishRecording() override;
 // ----------------------------------------------------------------------------
 // MISC HWUI OPERATIONS - TODO: CATEGORIZE
 // ----------------------------------------------------------------------------
-    void insertReorderBarrier(bool enableReorder) {
+    virtual void insertReorderBarrier(bool enableReorder) override {
         mDeferredBarrierType = enableReorder
                 ? DeferredBarrierType::OutOfOrder : DeferredBarrierType::InOrder;
     }
 
-    void drawLayer(DeferredLayerUpdater* layerHandle);
-    void drawRenderNode(RenderNode* renderNode);
-
-    // TODO: rename for consistency
-    void callDrawGLFunction(Functor* functor);
+    virtual void drawLayer(DeferredLayerUpdater* layerHandle) override;
+    virtual void drawRenderNode(RenderNode* renderNode) override;
+    virtual void callDrawGLFunction(Functor* functor) override;
 
 // ----------------------------------------------------------------------------
 // CanvasStateClient interface
@@ -78,12 +75,12 @@
 // HWUI Canvas draw operations
 // ----------------------------------------------------------------------------
 
-    void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
+    virtual void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
             CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
             CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
-            CanvasPropertyPaint* paint);
-    void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
-            CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
+            CanvasPropertyPaint* paint) override;
+    virtual void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+            CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) override;
 
 // ----------------------------------------------------------------------------
 // android/graphics/Canvas interface
@@ -178,6 +175,8 @@
             const uint16_t* indices, int indexCount, const SkPaint& paint) override
         { /* RecordingCanvas does not support drawVertices(); ignore */ }
 
+    virtual void drawVectorDrawable(VectorDrawableRoot* tree) override;
+
     // Bitmap-based
     virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) override;
     virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
diff --git a/libs/hwui/RenderBufferCache.cpp b/libs/hwui/RenderBufferCache.cpp
index 11d7a6a..1ac57cd 100644
--- a/libs/hwui/RenderBufferCache.cpp
+++ b/libs/hwui/RenderBufferCache.cpp
@@ -40,16 +40,9 @@
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
-RenderBufferCache::RenderBufferCache(): mSize(0), mMaxSize(MB(DEFAULT_RENDER_BUFFER_CACHE_SIZE)) {
-    char property[PROPERTY_VALUE_MAX];
-    if (property_get(PROPERTY_RENDER_BUFFER_CACHE_SIZE, property, nullptr) > 0) {
-        INIT_LOGD("  Setting render buffer cache size to %sMB", property);
-        setMaxSize(MB(atof(property)));
-    } else {
-        INIT_LOGD("  Using default render buffer cache size of %.2fMB",
-                DEFAULT_RENDER_BUFFER_CACHE_SIZE);
-    }
-}
+RenderBufferCache::RenderBufferCache()
+        : mSize(0)
+        , mMaxSize(Properties::renderBufferCacheSize) {}
 
 RenderBufferCache::~RenderBufferCache() {
     clear();
@@ -67,11 +60,6 @@
     return mMaxSize;
 }
 
-void RenderBufferCache::setMaxSize(uint32_t maxSize) {
-    clear();
-    mMaxSize = maxSize;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Caching
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/RenderBufferCache.h b/libs/hwui/RenderBufferCache.h
index 7f59ec1..f77f4c9 100644
--- a/libs/hwui/RenderBufferCache.h
+++ b/libs/hwui/RenderBufferCache.h
@@ -64,10 +64,6 @@
     void clear();
 
     /**
-     * Sets the maximum size of the cache in bytes.
-     */
-    void setMaxSize(uint32_t maxSize);
-    /**
      * Returns the maximum size of the cache in bytes.
      */
     uint32_t getMaxSize();
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index d4588ed..bade216 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -381,6 +381,10 @@
     bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
             willHaveFunctor, functorsNeedLayer);
 
+    if (CC_UNLIKELY(mPositionListener.get())) {
+        mPositionListener->onPositionUpdated(*this, info);
+    }
+
     prepareLayer(info, animatorDirtyMask);
     if (info.mode == TreeInfo::MODE_FULL) {
         pushStagingDisplayListChanges(info);
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 8e4a3df..f248de54 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -209,6 +209,19 @@
     OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
 #endif
 
+    class ANDROID_API PositionListener {
+    public:
+        virtual ~PositionListener() {}
+        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
+    };
+
+    // Note this is not thread safe, this needs to be called
+    // before the RenderNode is used for drawing.
+    // RenderNode takes ownership of the pointer
+    ANDROID_API void setPositionListener(PositionListener* listener) {
+        mPositionListener.reset(listener);
+    }
+
 private:
     typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
 
@@ -317,6 +330,8 @@
     // This is *NOT* thread-safe, and should therefore only be tracking
     // mDisplayList, not mStagingDisplayList.
     uint32_t mParentCount;
+
+    std::unique_ptr<PositionListener> mPositionListener;
 }; // class RenderNode
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 20e7c71..bd4442d 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -15,18 +15,25 @@
  */
 
 #include "Canvas.h"
+#include "CanvasProperty.h"
+#include "Layer.h"
+#include "RenderNode.h"
 
 #include <SkCanvas.h>
 #include <SkClipStack.h>
+#include <SkDrawable.h>
 #include <SkDevice.h>
 #include <SkDeque.h>
 #include <SkDrawFilter.h>
 #include <SkGraphics.h>
+#include <SkImage.h>
 #include <SkShader.h>
 #include <SkTArray.h>
 #include <SkTLazy.h>
 #include <SkTemplates.h>
 
+#include "VectorDrawable.h"
+
 #include <memory>
 
 namespace android {
@@ -52,6 +59,18 @@
         return mCanvas.get();
     }
 
+    virtual void resetRecording(int width, int height) override {
+        LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas");
+    }
+
+    virtual uirenderer::DisplayList* finishRecording() override {
+        LOG_ALWAYS_FATAL("SkiaCanvas does not produce a DisplayList");
+        return nullptr;
+    }
+    virtual void insertReorderBarrier(bool enableReorder) override {
+        LOG_ALWAYS_FATAL("SkiaCanvas does not support reordering barriers");
+    }
+
     virtual void setBitmap(const SkBitmap& bitmap) override;
 
     virtual bool isOpaque() override;
@@ -136,6 +155,19 @@
             float hOffset, float vOffset, const SkPaint& paint) override;
 
     virtual bool drawTextAbsolutePos() const  override { return true; }
+    virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
+
+    virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
+            uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
+            uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
+            uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) override;
+    virtual void drawCircle(uirenderer::CanvasPropertyPrimitive* x,
+            uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius,
+            uirenderer::CanvasPropertyPaint* paint) override;
+
+    virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
+    virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
+    virtual void callDrawGLFunction(Functor* functor) override;
 
 private:
     struct SaveRec {
@@ -713,6 +745,14 @@
     NinePatch::Draw(mCanvas, bounds, bitmap, chunk, paint, nullptr);
 }
 
+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());
+}
+
 // ----------------------------------------------------------------------------
 // Canvas draw operations: Text
 // ----------------------------------------------------------------------------
@@ -737,4 +777,84 @@
     mCanvas->drawTextOnPathHV(glyphs, count << 1, path, hOffset, vOffset, paint);
 }
 
+// ----------------------------------------------------------------------------
+// Canvas draw operations: Animations
+// ----------------------------------------------------------------------------
+
+class AnimatedRoundRect : public SkDrawable {
+ public:
+    AnimatedRoundRect(uirenderer::CanvasPropertyPrimitive* left,
+            uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
+            uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
+            uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* p) :
+            mLeft(left), mTop(top), mRight(right), mBottom(bottom), mRx(rx), mRy(ry), mPaint(p) {}
+
+ protected:
+     virtual SkRect onGetBounds() override {
+         return SkRect::MakeLTRB(mLeft->value, mTop->value, mRight->value, mBottom->value);
+     }
+     virtual void onDraw(SkCanvas* canvas) override {
+         SkRect rect = SkRect::MakeLTRB(mLeft->value, mTop->value, mRight->value, mBottom->value);
+         canvas->drawRoundRect(rect, mRx->value, mRy->value, mPaint->value);
+     }
+
+ private:
+    sp<uirenderer::CanvasPropertyPrimitive> mLeft;
+    sp<uirenderer::CanvasPropertyPrimitive> mTop;
+    sp<uirenderer::CanvasPropertyPrimitive> mRight;
+    sp<uirenderer::CanvasPropertyPrimitive> mBottom;
+    sp<uirenderer::CanvasPropertyPrimitive> mRx;
+    sp<uirenderer::CanvasPropertyPrimitive> mRy;
+    sp<uirenderer::CanvasPropertyPaint> mPaint;
+};
+
+class AnimatedCircle : public SkDrawable {
+ public:
+    AnimatedCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y,
+            uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) :
+            mX(x), mY(y), mRadius(radius), mPaint(paint) {}
+
+ protected:
+     virtual SkRect onGetBounds() override {
+         const float x = mX->value;
+         const float y = mY->value;
+         const float radius = mRadius->value;
+         return SkRect::MakeLTRB(x - radius, y - radius, x + radius, y + radius);
+     }
+     virtual void onDraw(SkCanvas* canvas) override {
+         canvas->drawCircle(mX->value, mY->value, mRadius->value, mPaint->value);
+     }
+
+ private:
+    sp<uirenderer::CanvasPropertyPrimitive> mX;
+    sp<uirenderer::CanvasPropertyPrimitive> mY;
+    sp<uirenderer::CanvasPropertyPrimitive> mRadius;
+    sp<uirenderer::CanvasPropertyPaint> mPaint;
+};
+
+void SkiaCanvas::drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
+        uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
+        uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
+        uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) {
+    SkAutoTUnref<AnimatedRoundRect> drawable(
+            new AnimatedRoundRect(left, top, right, bottom, rx, ry, paint));
+    mCanvas->drawDrawable(drawable.get());
+}
+
+void SkiaCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y,
+        uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) {
+    SkAutoTUnref<AnimatedCircle> drawable(new AnimatedCircle(x, y, radius, paint));
+    mCanvas->drawDrawable(drawable.get());
+}
+
+// ----------------------------------------------------------------------------
+// Canvas draw operations: View System
+// ----------------------------------------------------------------------------
+
+void SkiaCanvas::drawLayer(uirenderer::DeferredLayerUpdater* layer) { }
+
+void SkiaCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { }
+
+void SkiaCanvas::callDrawGLFunction(Functor* functor) { }
+
 } // namespace android
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 0835c29..14c8f39 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -160,45 +160,6 @@
 // Shadow tessellation task processing
 ///////////////////////////////////////////////////////////////////////////////
 
-class ShadowTask : public Task<TessellationCache::vertexBuffer_pair_t*> {
-public:
-    ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
-            const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
-            const Vector3& lightCenter, float lightRadius)
-        : drawTransform(*drawTransform)
-        , localClip(localClip)
-        , opaque(opaque)
-        , casterPerimeter(*casterPerimeter)
-        , transformXY(*transformXY)
-        , transformZ(*transformZ)
-        , lightCenter(lightCenter)
-        , lightRadius(lightRadius) {
-    }
-
-    ~ShadowTask() {
-        TessellationCache::vertexBuffer_pair_t* bufferPair = getResult();
-        delete bufferPair->getFirst();
-        delete bufferPair->getSecond();
-        delete bufferPair;
-    }
-
-    /* Note - we deep copy all task parameters, because *even though* pointers into Allocator
-     * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
-     * certain Allocators are destroyed before trim() is called to flush incomplete tasks.
-     *
-     * These deep copies could be avoided, long term, by cancelling or flushing outstanding tasks
-     * before tearning down single-frame LinearAllocators.
-     */
-    const Matrix4 drawTransform;
-    const Rect localClip;
-    bool opaque;
-    const SkPath casterPerimeter;
-    const Matrix4 transformXY;
-    const Matrix4 transformZ;
-    const Vector3 lightCenter;
-    const float lightRadius;
-};
-
 static void mapPointFakeZ(Vector3& point, const mat4* transformXY, const mat4* transformZ) {
     // map z coordinate with true 3d matrix
     point.z = transformZ->mapZ(point);
@@ -281,23 +242,21 @@
             spotBuffer);
 }
 
-class ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t*> {
+class ShadowProcessor : public TaskProcessor<TessellationCache::vertexBuffer_pair_t> {
 public:
     ShadowProcessor(Caches& caches)
-            : TaskProcessor<TessellationCache::vertexBuffer_pair_t*>(&caches.tasks) {}
+            : TaskProcessor<TessellationCache::vertexBuffer_pair_t>(&caches.tasks) {}
     ~ShadowProcessor() {}
 
-    virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t*> >& task) override {
-        ShadowTask* t = static_cast<ShadowTask*>(task.get());
+    virtual void onProcess(const sp<Task<TessellationCache::vertexBuffer_pair_t> >& task) override {
+        TessellationCache::ShadowTask* t = static_cast<TessellationCache::ShadowTask*>(task.get());
         ATRACE_NAME("shadow tessellation");
 
-        VertexBuffer* ambientBuffer = new VertexBuffer;
-        VertexBuffer* spotBuffer = new VertexBuffer;
         tessellateShadows(&t->drawTransform, &t->localClip, t->opaque, &t->casterPerimeter,
                 &t->transformXY, &t->transformZ, t->lightCenter, t->lightRadius,
-                *ambientBuffer, *spotBuffer);
+                t->ambientBuffer, t->spotBuffer);
 
-        t->setResult(new TessellationCache::vertexBuffer_pair_t(ambientBuffer, spotBuffer));
+        t->setResult(TessellationCache::vertexBuffer_pair_t(&t->ambientBuffer, &t->spotBuffer));
     }
 };
 
@@ -306,18 +265,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 TessellationCache::TessellationCache()
-        : mSize(0)
-        , mMaxSize(MB(DEFAULT_VERTEX_CACHE_SIZE))
+        : mMaxSize(Properties::tessellationCacheSize)
         , mCache(LruCache<Description, Buffer*>::kUnlimitedCapacity)
         , mShadowCache(LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*>::kUnlimitedCapacity) {
-    char property[PROPERTY_VALUE_MAX];
-    if (property_get(PROPERTY_VERTEX_CACHE_SIZE, property, nullptr) > 0) {
-        INIT_LOGD("  Setting tessellation cache size to %sMB", property);
-        setMaxSize(MB(atof(property)));
-    } else {
-        INIT_LOGD("  Using default tessellation cache size of %.2fMB", DEFAULT_VERTEX_CACHE_SIZE);
-    }
-
     mCache.setOnEntryRemovedListener(&mBufferRemovedListener);
     mShadowCache.setOnEntryRemovedListener(&mBufferPairRemovedListener);
     mDebugEnabled = Properties::debugLevel & kDebugCaches;
@@ -344,13 +294,6 @@
     return mMaxSize;
 }
 
-void TessellationCache::setMaxSize(uint32_t maxSize) {
-    mMaxSize = maxSize;
-    while (mSize > mMaxSize) {
-        mCache.removeOldest();
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Caching
 ///////////////////////////////////////////////////////////////////////////////
@@ -412,7 +355,23 @@
         task = static_cast<ShadowTask*>(mShadowCache.get(key));
     }
     LOG_ALWAYS_FATAL_IF(task == nullptr, "shadow not precached");
-    outBuffers = *(task->getResult());
+    outBuffers = task->getResult();
+}
+
+sp<TessellationCache::ShadowTask> TessellationCache::getShadowTask(
+        const Matrix4* drawTransform, const Rect& localClip,
+        bool opaque, const SkPath* casterPerimeter,
+        const Matrix4* transformXY, const Matrix4* transformZ,
+        const Vector3& lightCenter, float lightRadius) {
+    ShadowDescription key(casterPerimeter, drawTransform);
+    ShadowTask* task = static_cast<ShadowTask*>(mShadowCache.get(key));
+    if (!task) {
+        precacheShadows(drawTransform, localClip, opaque, casterPerimeter,
+                transformXY, transformZ, lightCenter, lightRadius);
+        task = static_cast<ShadowTask*>(mShadowCache.get(key));
+    }
+    LOG_ALWAYS_FATAL_IF(task == nullptr, "shadow not precached");
+    return task;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h
index 06e567e..0bd6365 100644
--- a/libs/hwui/TessellationCache.h
+++ b/libs/hwui/TessellationCache.h
@@ -21,11 +21,13 @@
 #include "Matrix.h"
 #include "Rect.h"
 #include "Vector.h"
+#include "VertexBuffer.h"
 #include "thread/TaskProcessor.h"
 #include "utils/Macros.h"
 #include "utils/Pair.h"
 
 #include <SkPaint.h>
+#include <SkPath.h>
 
 #include <utils/LruCache.h>
 #include <utils/Mutex.h>
@@ -33,7 +35,6 @@
 
 class SkBitmap;
 class SkCanvas;
-class SkPath;
 struct SkRect;
 
 namespace android {
@@ -89,6 +90,40 @@
         hash_t hash() const;
     };
 
+    class ShadowTask : public Task<vertexBuffer_pair_t> {
+    public:
+        ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
+                const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
+                const Vector3& lightCenter, float lightRadius)
+            : drawTransform(*drawTransform)
+            , localClip(localClip)
+            , opaque(opaque)
+            , casterPerimeter(*casterPerimeter)
+            , transformXY(*transformXY)
+            , transformZ(*transformZ)
+            , lightCenter(lightCenter)
+            , lightRadius(lightRadius) {
+        }
+
+        /* Note - we deep copy all task parameters, because *even though* pointers into Allocator
+         * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
+         * certain Allocators are destroyed before trim() is called to flush incomplete tasks.
+         *
+         * These deep copies could be avoided, long term, by canceling or flushing outstanding
+         * tasks before tearing down single-frame LinearAllocators.
+         */
+        const Matrix4 drawTransform;
+        const Rect localClip;
+        bool opaque;
+        const SkPath casterPerimeter;
+        const Matrix4 transformXY;
+        const Matrix4 transformZ;
+        const Vector3 lightCenter;
+        const float lightRadius;
+        VertexBuffer ambientBuffer;
+        VertexBuffer spotBuffer;
+    };
+
     TessellationCache();
     ~TessellationCache();
 
@@ -96,11 +131,6 @@
      * Clears the cache. This causes all TessellationBuffers to be deleted.
      */
     void clear();
-
-    /**
-     * Sets the maximum size of the cache in bytes.
-     */
-    void setMaxSize(uint32_t maxSize);
     /**
      * Returns the maximum size of the cache in bytes.
      */
@@ -133,17 +163,22 @@
     const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint,
             float width, float height, float rx, float ry);
 
+    // TODO: delete these when switching to HWUI_NEW_OPS
     void precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
             bool opaque, const SkPath* casterPerimeter,
             const Matrix4* transformXY, const Matrix4* transformZ,
             const Vector3& lightCenter, float lightRadius);
-
     void getShadowBuffers(const Matrix4* drawTransform, const Rect& localClip,
             bool opaque, const SkPath* casterPerimeter,
             const Matrix4* transformXY, const Matrix4* transformZ,
             const Vector3& lightCenter, float lightRadius,
             vertexBuffer_pair_t& outBuffers);
 
+    sp<ShadowTask> getShadowTask(const Matrix4* drawTransform, const Rect& localClip,
+            bool opaque, const SkPath* casterPerimeter,
+            const Matrix4* transformXY, const Matrix4* transformZ,
+            const Vector3& lightCenter, float lightRadius);
+
 private:
     class Buffer;
     class TessellationTask;
@@ -158,8 +193,7 @@
 
     Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator);
 
-    uint32_t mSize;
-    uint32_t mMaxSize;
+    const uint32_t mMaxSize;
 
     bool mDebugEnabled;
 
@@ -178,12 +212,12 @@
     ///////////////////////////////////////////////////////////////////////////////
     // Shadow tessellation caching
     ///////////////////////////////////////////////////////////////////////////////
-    sp<TaskProcessor<vertexBuffer_pair_t*> > mShadowProcessor;
+    sp<TaskProcessor<vertexBuffer_pair_t> > mShadowProcessor;
 
     // holds a pointer, and implicit strong ref to each shadow task of the frame
-    LruCache<ShadowDescription, Task<vertexBuffer_pair_t*>*> mShadowCache;
-    class BufferPairRemovedListener : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t*>*> {
-        void operator()(ShadowDescription& description, Task<vertexBuffer_pair_t*>*& bufferPairTask) override {
+    LruCache<ShadowDescription, Task<vertexBuffer_pair_t>*> mShadowCache;
+    class BufferPairRemovedListener : public OnEntryRemoved<ShadowDescription, Task<vertexBuffer_pair_t>*> {
+        void operator()(ShadowDescription& description, Task<vertexBuffer_pair_t>*& bufferPairTask) override {
             bufferPairTask->decStrong(nullptr);
         }
     };
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index 62a20fc..fe4b3d75 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -93,36 +93,21 @@
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
-TextDropShadowCache::TextDropShadowCache():
-        mCache(LruCache<ShadowText, ShadowTexture*>::kUnlimitedCapacity),
-        mSize(0), mMaxSize(MB(DEFAULT_DROP_SHADOW_CACHE_SIZE)) {
-    char property[PROPERTY_VALUE_MAX];
-    if (property_get(PROPERTY_DROP_SHADOW_CACHE_SIZE, property, nullptr) > 0) {
-        INIT_LOGD("  Setting drop shadow cache size to %sMB", property);
-        setMaxSize(MB(atof(property)));
-    } else {
-        INIT_LOGD("  Using default drop shadow cache size of %.2fMB",
-                DEFAULT_DROP_SHADOW_CACHE_SIZE);
-    }
+TextDropShadowCache::TextDropShadowCache()
+        : TextDropShadowCache(Properties::textDropShadowCacheSize) {}
 
-    init();
-}
-
-TextDropShadowCache::TextDropShadowCache(uint32_t maxByteSize):
-        mCache(LruCache<ShadowText, ShadowTexture*>::kUnlimitedCapacity),
-        mSize(0), mMaxSize(maxByteSize) {
-    init();
+TextDropShadowCache::TextDropShadowCache(uint32_t maxByteSize)
+        : mCache(LruCache<ShadowText, ShadowTexture*>::kUnlimitedCapacity)
+        , mSize(0)
+        , mMaxSize(maxByteSize) {
+    mCache.setOnEntryRemovedListener(this);
+    mDebugEnabled = Properties::debugLevel & kDebugMoreCaches;
 }
 
 TextDropShadowCache::~TextDropShadowCache() {
     mCache.clear();
 }
 
-void TextDropShadowCache::init() {
-    mCache.setOnEntryRemovedListener(this);
-    mDebugEnabled = Properties::debugLevel & kDebugMoreCaches;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Size management
 ///////////////////////////////////////////////////////////////////////////////
@@ -135,20 +120,13 @@
     return mMaxSize;
 }
 
-void TextDropShadowCache::setMaxSize(uint32_t maxSize) {
-    mMaxSize = maxSize;
-    while (mSize > mMaxSize) {
-        mCache.removeOldest();
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Callbacks
 ///////////////////////////////////////////////////////////////////////////////
 
 void TextDropShadowCache::operator()(ShadowText&, ShadowTexture*& texture) {
     if (texture) {
-        mSize -= texture->bitmapSize;
+        mSize -= texture->objectSize();
 
         if (mDebugEnabled) {
             ALOGD("Shadow texture deleted, size = %d", texture->bitmapSize);
@@ -195,7 +173,9 @@
         // Don't even try to cache a bitmap that's bigger than the cache
         if (size < mMaxSize) {
             while (mSize + size > mMaxSize) {
-                mCache.removeOldest();
+                LOG_ALWAYS_FATAL_IF(!mCache.removeOldest(),
+                        "Failed to remove oldest from cache. mSize = %"
+                        PRIu32 ", mCache.size() = %zu", mSize, mCache.size());
             }
         }
 
@@ -212,7 +192,7 @@
 
             entry.copyTextLocally();
 
-            mSize += size;
+            mSize += texture->objectSize();
             mCache.put(entry, texture);
         } else {
             texture->cleanup = true;
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index c4f3c5d..cf64788 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -148,10 +148,6 @@
     }
 
     /**
-     * Sets the maximum size of the cache in bytes.
-     */
-    void setMaxSize(uint32_t maxSize);
-    /**
      * Returns the maximum size of the cache in bytes.
      */
     uint32_t getMaxSize();
@@ -161,13 +157,11 @@
     uint32_t getSize();
 
 private:
-    void init();
-
     LruCache<ShadowText, ShadowTexture*> mCache;
 
     uint32_t mSize;
-    uint32_t mMaxSize;
-    FontRenderer* mRenderer;
+    const uint32_t mMaxSize;
+    FontRenderer* mRenderer = nullptr;
     bool mDebugEnabled;
 }; // class TextDropShadowCache
 
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 31bfa3a..ade8600 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -35,26 +35,9 @@
 TextureCache::TextureCache()
         : mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity)
         , mSize(0)
-        , mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE))
-        , mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE)
+        , mMaxSize(Properties::textureCacheSize)
+        , mFlushRate(Properties::textureCacheFlushRate)
         , mAssetAtlas(nullptr) {
-    char property[PROPERTY_VALUE_MAX];
-    if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, nullptr) > 0) {
-        INIT_LOGD("  Setting texture cache size to %sMB", property);
-        setMaxSize(MB(atof(property)));
-    } else {
-        INIT_LOGD("  Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE);
-    }
-
-    if (property_get(PROPERTY_TEXTURE_CACHE_FLUSH_RATE, property, nullptr) > 0) {
-        float flushRate = atof(property);
-        INIT_LOGD("  Setting texture cache flush rate to %.2f%%", flushRate * 100.0f);
-        setFlushRate(flushRate);
-    } else {
-        INIT_LOGD("  Using default texture cache flush rate of %.2f%%",
-                DEFAULT_TEXTURE_CACHE_FLUSH_RATE * 100.0f);
-    }
-
     mCache.setOnEntryRemovedListener(this);
 
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
@@ -79,17 +62,6 @@
     return mMaxSize;
 }
 
-void TextureCache::setMaxSize(uint32_t maxSize) {
-    mMaxSize = maxSize;
-    while (mSize > mMaxSize) {
-        mCache.removeOldest();
-    }
-}
-
-void TextureCache::setFlushRate(float flushRate) {
-    mFlushRate = std::max(0.0f, std::min(1.0f, flushRate));
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Callbacks
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 463450c..a4317ce 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -109,10 +109,6 @@
     void clear();
 
     /**
-     * Sets the maximum size of the cache in bytes.
-     */
-    void setMaxSize(uint32_t maxSize);
-    /**
      * Returns the maximum size of the cache in bytes.
      */
     uint32_t getMaxSize();
@@ -126,11 +122,6 @@
      * is defined by the flush rate.
      */
     void flush();
-    /**
-     * Indicates the percentage of the cache to retain when a
-     * memory trim is requested (see Caches::flush).
-     */
-    void setFlushRate(float flushRate);
 
     void setAssetAtlas(AssetAtlas* assetAtlas);
 
@@ -148,10 +139,10 @@
     LruCache<uint32_t, Texture*> mCache;
 
     uint32_t mSize;
-    uint32_t mMaxSize;
+    const uint32_t mMaxSize;
     GLint mMaxTextureSize;
 
-    float mFlushRate;
+    const float mFlushRate;
 
     bool mDebugEnabled;
 
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index be25516..accd303 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -86,6 +86,12 @@
 #endif
     ErrorHandler* errorHandler = nullptr;
 
+    // Frame number for use with synchronized surfaceview position updating
+    int64_t frameNumber = -1;
+    int32_t windowInsetLeft = 0;
+    int32_t windowInsetTop = 0;
+    bool updateWindowPositions = false;
+
     struct Out {
         bool hasFunctors = false;
         // This is only updated if evaluateAnimations is true
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 1cf15ac..2e3856f 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -138,18 +138,7 @@
 }
 
 FullPath::FullPath(const FullPath& path) : Path(path) {
-    mStrokeWidth = path.mStrokeWidth;
-    mStrokeColor = path.mStrokeColor;
-    mStrokeAlpha = path.mStrokeAlpha;
-    mFillColor = path.mFillColor;
-    mFillAlpha = path.mFillAlpha;
-    mTrimPathStart = path.mTrimPathStart;
-    mTrimPathEnd = path.mTrimPathEnd;
-    mTrimPathOffset = path.mTrimPathOffset;
-    mStrokeMiterLimit = path.mStrokeMiterLimit;
-    mStrokeLineCap = path.mStrokeLineCap;
-    mStrokeLineJoin = path.mStrokeLineJoin;
-
+    mProperties = path.mProperties;
     SkRefCnt_SafeAssign(mStrokeGradient, path.mStrokeGradient);
     SkRefCnt_SafeAssign(mFillGradient, path.mFillGradient);
 }
@@ -159,7 +148,7 @@
         return mTrimmedSkPath;
     }
     Path::getUpdatedPath();
-    if (mTrimPathStart != 0.0f || mTrimPathEnd != 1.0f) {
+    if (mProperties.trimPathStart != 0.0f || mProperties.trimPathEnd != 1.0f) {
         applyTrim();
         return mTrimmedSkPath;
     } else {
@@ -170,14 +159,14 @@
 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) {
-    mStrokeWidth = strokeWidth;
-    mStrokeColor = strokeColor;
-    mStrokeAlpha = strokeAlpha;
-    mFillColor = fillColor;
-    mFillAlpha = fillAlpha;
-    mStrokeMiterLimit = strokeMiterLimit;
-    mStrokeLineCap = SkPaint::Cap(strokeLineCap);
-    mStrokeLineJoin = SkPaint::Join(strokeLineJoin);
+    mProperties.strokeWidth = strokeWidth;
+    mProperties.strokeColor = strokeColor;
+    mProperties.strokeAlpha = strokeAlpha;
+    mProperties.fillColor = fillColor;
+    mProperties.fillAlpha = fillAlpha;
+    mProperties.strokeMiterLimit = strokeMiterLimit;
+    mProperties.strokeLineCap = strokeLineCap;
+    mProperties.strokeLineJoin = strokeLineJoin;
 
     // If any trim property changes, mark trim dirty and update the trim path
     setTrimPathStart(trimPathStart);
@@ -195,12 +184,12 @@
     // Draw path's fill, if fill color or gradient is valid
     bool needsFill = false;
     if (mFillGradient != nullptr) {
-        mPaint.setColor(applyAlpha(SK_ColorBLACK, mFillAlpha));
+        mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.fillAlpha));
         SkShader* newShader = mFillGradient->newWithLocalMatrix(matrix);
         mPaint.setShader(newShader);
         needsFill = true;
-    } else if (mFillColor != SK_ColorTRANSPARENT) {
-        mPaint.setColor(applyAlpha(mFillColor, mFillAlpha));
+    } else if (mProperties.fillColor != SK_ColorTRANSPARENT) {
+        mPaint.setColor(applyAlpha(mProperties.fillColor, mProperties.fillAlpha));
         needsFill = true;
     }
 
@@ -213,21 +202,21 @@
     // Draw path's stroke, if stroke color or gradient is valid
     bool needsStroke = false;
     if (mStrokeGradient != nullptr) {
-        mPaint.setColor(applyAlpha(SK_ColorBLACK, mStrokeAlpha));
+        mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.strokeAlpha));
         SkShader* newShader = mStrokeGradient->newWithLocalMatrix(matrix);
         mPaint.setShader(newShader);
         needsStroke = true;
-    } else if (mStrokeColor != SK_ColorTRANSPARENT) {
-        mPaint.setColor(applyAlpha(mStrokeColor, mStrokeAlpha));
+    } else if (mProperties.strokeColor != SK_ColorTRANSPARENT) {
+        mPaint.setColor(applyAlpha(mProperties.strokeColor, mProperties.strokeAlpha));
         needsStroke = true;
     }
     if (needsStroke) {
         mPaint.setStyle(SkPaint::Style::kStroke_Style);
         mPaint.setAntiAlias(true);
-        mPaint.setStrokeJoin(mStrokeLineJoin);
-        mPaint.setStrokeCap(mStrokeLineCap);
-        mPaint.setStrokeMiter(mStrokeMiterLimit);
-        mPaint.setStrokeWidth(mStrokeWidth * strokeScale);
+        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);
     }
 }
@@ -236,14 +225,14 @@
  * Applies trimming to the specified path.
  */
 void FullPath::applyTrim() {
-    if (mTrimPathStart == 0.0f && mTrimPathEnd == 1.0f) {
+    if (mProperties.trimPathStart == 0.0f && mProperties.trimPathEnd == 1.0f) {
         // No trimming necessary.
         return;
     }
     SkPathMeasure measure(mSkPath, false);
     float len = SkScalarToFloat(measure.getLength());
-    float start = len * fmod((mTrimPathStart + mTrimPathOffset), 1.0f);
-    float end = len * fmod((mTrimPathEnd + mTrimPathOffset), 1.0f);
+    float start = len * fmod((mProperties.trimPathStart + mProperties.trimPathOffset), 1.0f);
+    float end = len * fmod((mProperties.trimPathEnd + mProperties.trimPathOffset), 1.0f);
 
     mTrimmedSkPath.reset();
     if (start > end) {
@@ -255,76 +244,69 @@
     mTrimDirty = false;
 }
 
-inline int putData(int8_t* outBytes, int startIndex, float value) {
-    int size = sizeof(float);
-    memcpy(&outBytes[startIndex], &value, size);
-    return size;
-}
-
-inline int putData(int8_t* outBytes, int startIndex, int value) {
-    int size = sizeof(int);
-    memcpy(&outBytes[startIndex], &value, size);
-    return size;
-}
-
-struct FullPathProperties {
-    // TODO: Consider storing full path properties in this struct instead of the fields.
-    float strokeWidth;
-    SkColor strokeColor;
-    float strokeAlpha;
-    SkColor fillColor;
-    float fillAlpha;
-    float trimPathStart;
-    float trimPathEnd;
-    float trimPathOffset;
-    int32_t strokeLineCap;
-    int32_t strokeLineJoin;
-    float strokeMiterLimit;
-};
-
-REQUIRE_COMPATIBLE_LAYOUT(FullPathProperties);
+REQUIRE_COMPATIBLE_LAYOUT(FullPath::Properties);
 
 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(FullPathProperties);
+    int propertyDataSize = sizeof(Properties);
     if (length != propertyDataSize) {
         LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided",
                 propertyDataSize, length);
         return false;
     }
-    // TODO: consider replacing the property fields with a FullPathProperties struct.
-    FullPathProperties properties;
-    properties.strokeWidth = mStrokeWidth;
-    properties.strokeColor = mStrokeColor;
-    properties.strokeAlpha = mStrokeAlpha;
-    properties.fillColor = mFillColor;
-    properties.fillAlpha = mFillAlpha;
-    properties.trimPathStart = mTrimPathStart;
-    properties.trimPathEnd = mTrimPathEnd;
-    properties.trimPathOffset = mTrimPathOffset;
-    properties.strokeLineCap = mStrokeLineCap;
-    properties.strokeLineJoin = mStrokeLineJoin;
-    properties.strokeMiterLimit = mStrokeMiterLimit;
-
-    memcpy(outProperties, &properties, length);
+    Properties* out = reinterpret_cast<Properties*>(outProperties);
+    *out = mProperties;
     return true;
 }
 
+void FullPath::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;
+    } else {
+        LOG_ALWAYS_FATAL("Error setting color property on FullPath: No valid property with id: %d",
+                propertyId);
+    }
+}
+
+void FullPath::setPropertyValue(int propertyId, float value) {
+    Property property = static_cast<Property>(propertyId);
+    switch (property) {
+    case Property::StrokeWidth:
+        setStrokeWidth(value);
+        break;
+    case Property::StrokeAlpha:
+        setStrokeAlpha(value);
+        break;
+    case Property::FillAlpha:
+        setFillAlpha(value);
+        break;
+    case Property::TrimPathStart:
+        setTrimPathStart(value);
+        break;
+    case Property::TrimPathEnd:
+        setTrimPathEnd(value);
+        break;
+    case Property::TrimPathOffset:
+        setTrimPathOffset(value);
+        break;
+    default:
+        LOG_ALWAYS_FATAL("Invalid property id: %d for animation", propertyId);
+        break;
+    }
+}
+
 void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
         float strokeScale, const SkMatrix& matrix){
     outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
 }
 
 Group::Group(const Group& group) : Node(group) {
-    mRotate = group.mRotate;
-    mPivotX = group.mPivotX;
-    mPivotY = group.mPivotY;
-    mScaleX = group.mScaleX;
-    mScaleY = group.mScaleY;
-    mTranslateX = group.mTranslateX;
-    mTranslateY = group.mTranslateY;
+    mProperties = group.mProperties;
 }
 
 void Group::draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scaleX,
@@ -342,7 +324,7 @@
     // 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 (Node* child : mChildren) {
+    for (auto& child : mChildren) {
         child->draw(outCanvas, stackedMatrix, scaleX, scaleY);
     }
     // Restore the previous clip information.
@@ -371,14 +353,15 @@
     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(-mPivotX, -mPivotY);
-    outMatrix->postScale(mScaleX, mScaleY);
-    outMatrix->postRotate(mRotate, 0, 0);
-    outMatrix->postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+    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);
 }
 
 void Group::addChild(Node* child) {
-    mChildren.push_back(child);
+    mChildren.emplace_back(child);
 }
 
 bool Group::getProperties(float* outProperties, int length) {
@@ -388,38 +371,68 @@
                 propertyCount, length);
         return false;
     }
-    for (int i = 0; i < propertyCount; i++) {
-        Property currentProperty = static_cast<Property>(i);
-        switch (currentProperty) {
-        case Property::Rotate_Property:
-            outProperties[i] = mRotate;
-            break;
-        case Property::PivotX_Property:
-            outProperties[i] = mPivotX;
-            break;
-        case Property::PivotY_Property:
-            outProperties[i] = mPivotY;
-            break;
-        case Property::ScaleX_Property:
-            outProperties[i] = mScaleX;
-            break;
-        case Property::ScaleY_Property:
-            outProperties[i] = mScaleY;
-            break;
-        case Property::TranslateX_Property:
-            outProperties[i] = mTranslateX;
-            break;
-        case Property::TranslateY_Property:
-            outProperties[i] = mTranslateY;
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Invalid input index: %d", i);
-            return false;
-        }
-    }
+    Properties* out = reinterpret_cast<Properties*>(outProperties);
+    *out = mProperties;
     return true;
 }
 
+// TODO: Consider animating the properties as float pointers
+float Group::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;
+    default:
+        LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
+        return 0;
+    }
+}
+
+void Group::setPropertyValue(int propertyId, float value) {
+    Property currentProperty = static_cast<Property>(propertyId);
+    switch (currentProperty) {
+    case Property::Rotate:
+        mProperties.rotate = value;
+        break;
+    case Property::PivotX:
+        mProperties.pivotX = value;
+        break;
+    case Property::PivotY:
+        mProperties.pivotY = value;
+        break;
+    case Property::ScaleX:
+        mProperties.scaleX = value;
+        break;
+    case Property::ScaleY:
+        mProperties.scaleY = value;
+        break;
+    case Property::TranslateX:
+        mProperties.translateX = value;
+        break;
+    case Property::TranslateY:
+        mProperties.translateY = value;
+        break;
+    default:
+        LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId);
+    }
+}
+
+bool Group::isValidProperty(int propertyId) {
+    return propertyId >= 0 && propertyId < static_cast<int>(Property::Count);
+}
+
 void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter,
         const SkRect& bounds, bool needsMirroring, bool canReuseCache) {
     // The imageView can scale the canvas in different ways, in order to
@@ -445,6 +458,8 @@
         return;
     }
 
+    mPaint.setColorFilter(colorFilter);
+
     int saveCount = outCanvas->save(SaveFlags::MatrixClip);
     outCanvas->translate(mBounds.fLeft, mBounds.fTop);
 
@@ -458,43 +473,33 @@
     // 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);
-    if (!mAllowCaching) {
-        updateCachedBitmap(scaledWidth, scaledHeight);
-    } else {
-        if (!canReuseCache || mCacheDirty) {
-            updateCachedBitmap(scaledWidth, scaledHeight);
-        }
-    }
-    drawCachedBitmapWithRootAlpha(outCanvas, colorFilter, mBounds);
+
+    outCanvas->drawVectorDrawable(this);
 
     outCanvas->restoreToCount(saveCount);
 }
 
-void Tree::drawCachedBitmapWithRootAlpha(Canvas* outCanvas, SkColorFilter* filter,
-        const SkRect& originalBounds) {
+SkPaint* Tree::getPaint() {
     SkPaint* paint;
-    if (mRootAlpha == 1.0f && filter == NULL) {
+    if (mRootAlpha == 1.0f && mPaint.getColorFilter() == NULL) {
         paint = NULL;
     } else {
         mPaint.setFilterQuality(kLow_SkFilterQuality);
         mPaint.setAlpha(mRootAlpha * 255);
-        mPaint.setColorFilter(filter);
         paint = &mPaint;
     }
-    outCanvas->drawBitmap(mCachedBitmap, 0, 0, mCachedBitmap.width(), mCachedBitmap.height(),
-            originalBounds.fLeft, originalBounds.fTop, originalBounds.fRight,
-            originalBounds.fBottom, paint);
+    return paint;
 }
 
-void Tree::updateCachedBitmap(int width, int height) {
+const SkBitmap& Tree::getBitmapUpdateIfDirty() {
     mCachedBitmap.eraseColor(SK_ColorTRANSPARENT);
     SkCanvas outCanvas(mCachedBitmap);
-    float scaleX = width / mViewportWidth;
-    float scaleY = height / mViewportHeight;
+    float scaleX = (float) mCachedBitmap.width() / mViewportWidth;
+    float scaleY = (float) mCachedBitmap.height() / mViewportHeight;
     mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY);
     mCacheDirty = false;
+    return mCachedBitmap;
 }
 
 void Tree::createCachedBitmapIfNeeded(int width, int height) {
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 09bdce5..36a8aeb 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -18,6 +18,7 @@
 #define ANDROID_HWUI_VPATH_H
 
 #include "Canvas.h"
+
 #include <SkBitmap.h>
 #include <SkColor.h>
 #include <SkCanvas.h>
@@ -104,6 +105,21 @@
 
 class ANDROID_API FullPath: public Path {
 public:
+
+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;
+};
+
     FullPath(const FullPath& path); // for cloning
     FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
     FullPath() : Path() {}
@@ -118,55 +134,58 @@
             float strokeAlpha, SkColor fillColor, float fillAlpha,
             float trimPathStart, float trimPathEnd, float trimPathOffset,
             float strokeMiterLimit, int strokeLineCap, int strokeLineJoin);
+    // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
     float getStrokeWidth() {
-        return mStrokeWidth;
+        return mProperties.strokeWidth;
     }
     void setStrokeWidth(float strokeWidth) {
-        mStrokeWidth = strokeWidth;
+        mProperties.strokeWidth = strokeWidth;
     }
     SkColor getStrokeColor() {
-        return mStrokeColor;
+        return mProperties.strokeColor;
     }
     void setStrokeColor(SkColor strokeColor) {
-        mStrokeColor = strokeColor;
+        mProperties.strokeColor = strokeColor;
     }
     float getStrokeAlpha() {
-        return mStrokeAlpha;
+        return mProperties.strokeAlpha;
     }
     void setStrokeAlpha(float strokeAlpha) {
-        mStrokeAlpha = strokeAlpha;
+        mProperties.strokeAlpha = strokeAlpha;
     }
     SkColor getFillColor() {
-        return mFillColor;
+        return mProperties.fillColor;
     }
     void setFillColor(SkColor fillColor) {
-        mFillColor = fillColor;
+        mProperties.fillColor = fillColor;
     }
     float getFillAlpha() {
-        return mFillAlpha;
+        return mProperties.fillAlpha;
     }
     void setFillAlpha(float fillAlpha) {
-        mFillAlpha = fillAlpha;
+        mProperties.fillAlpha = fillAlpha;
     }
     float getTrimPathStart() {
-        return mTrimPathStart;
+        return mProperties.trimPathStart;
     }
     void setTrimPathStart(float trimPathStart) {
-        VD_SET_PROP_WITH_FLAG(mTrimPathStart, trimPathStart, mTrimDirty);
+        VD_SET_PROP_WITH_FLAG(mProperties.trimPathStart, trimPathStart, mTrimDirty);
     }
     float getTrimPathEnd() {
-        return mTrimPathEnd;
+        return mProperties.trimPathEnd;
     }
     void setTrimPathEnd(float trimPathEnd) {
-        VD_SET_PROP_WITH_FLAG(mTrimPathEnd, trimPathEnd, mTrimDirty);
+        VD_SET_PROP_WITH_FLAG(mProperties.trimPathEnd, trimPathEnd, mTrimDirty);
     }
     float getTrimPathOffset() {
-        return mTrimPathOffset;
+        return mProperties.trimPathOffset;
     }
     void setTrimPathOffset(float trimPathOffset) {
-        VD_SET_PROP_WITH_FLAG(mTrimPathOffset, trimPathOffset, mTrimDirty);
+        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);
@@ -182,24 +201,28 @@
             float strokeScale, const SkMatrix& matrix) override;
 
 private:
+    enum class Property {
+        StrokeWidth = 0,
+        StrokeColor,
+        StrokeAlpha,
+        FillColor,
+        FillAlpha,
+        TrimPathStart,
+        TrimPathEnd,
+        TrimPathOffset,
+        StrokeLineCap,
+        StrokeLineJoin,
+        StrokeMiterLimit,
+        Count,
+    };
     // Applies trimming to the specified path.
     void applyTrim();
-    float mStrokeWidth = 0;
-    SkColor mStrokeColor = SK_ColorTRANSPARENT;
-    float mStrokeAlpha = 1;
-    SkColor mFillColor = SK_ColorTRANSPARENT;
-    SkShader* mStrokeGradient = nullptr;
-    SkShader* mFillGradient = nullptr;
-    float mFillAlpha = 1;
-    float mTrimPathStart = 0;
-    float mTrimPathEnd = 1;
-    float mTrimPathOffset = 0;
+    Properties mProperties;
     bool mTrimDirty = true;
-    SkPaint::Cap mStrokeLineCap = SkPaint::Cap::kButt_Cap;
-    SkPaint::Join mStrokeLineJoin = SkPaint::Join::kMiter_Join;
-    float mStrokeMiterLimit = 4;
     SkPath mTrimmedSkPath;
     SkPaint mPaint;
+    SkShader* mStrokeGradient = nullptr;
+    SkShader* mFillGradient = nullptr;
 };
 
 class ANDROID_API ClipPath: public Path {
@@ -216,49 +239,58 @@
 
 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;
+    };
     Group(const Group& group);
     Group() {}
     float getRotation() {
-        return mRotate;
+        return mProperties.rotate;
     }
     void setRotation(float rotation) {
-        mRotate = rotation;
+        mProperties.rotate = rotation;
     }
     float getPivotX() {
-        return mPivotX;
+        return mProperties.pivotX;
     }
     void setPivotX(float pivotX) {
-        mPivotX = pivotX;
+        mProperties.pivotX = pivotX;
     }
     float getPivotY() {
-        return mPivotY;
+        return mProperties.pivotY;
     }
     void setPivotY(float pivotY) {
-        mPivotY = pivotY;
+        mProperties.pivotY = pivotY;
     }
     float getScaleX() {
-        return mScaleX;
+        return mProperties.scaleX;
     }
     void setScaleX(float scaleX) {
-        mScaleX = scaleX;
+        mProperties.scaleX = scaleX;
     }
     float getScaleY() {
-        return mScaleY;
+        return mProperties.scaleY;
     }
     void setScaleY(float scaleY) {
-        mScaleY = scaleY;
+        mProperties.scaleY = scaleY;
     }
     float getTranslateX() {
-        return mTranslateX;
+        return mProperties.translateX;
     }
     void setTranslateX(float translateX) {
-        mTranslateX = translateX;
+        mProperties.translateX = translateX;
     }
     float getTranslateY() {
-        return mTranslateY;
+        return mProperties.translateY;
     }
     void setTranslateY(float translateY) {
-        mTranslateY = translateY;
+        mProperties.translateY = translateY;
     }
     virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
             float scaleX, float scaleY) override;
@@ -268,38 +300,33 @@
     void addChild(Node* child);
     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);
 
 private:
     enum class Property {
-        Rotate_Property = 0,
-        PivotX_Property,
-        PivotY_Property,
-        ScaleX_Property,
-        ScaleY_Property,
-        TranslateX_Property,
-        TranslateY_Property,
+        Rotate = 0,
+        PivotX,
+        PivotY,
+        ScaleX,
+        ScaleY,
+        TranslateX,
+        TranslateY,
         // Count of the properties, must be at the end.
         Count,
     };
-    float mRotate = 0;
-    float mPivotX = 0;
-    float mPivotY = 0;
-    float mScaleX = 1;
-    float mScaleY = 1;
-    float mTranslateX = 0;
-    float mTranslateY = 0;
-    std::vector<Node*> mChildren;
+    std::vector< std::unique_ptr<Node> > mChildren;
+    Properties mProperties;
 };
 
-class ANDROID_API Tree {
+class ANDROID_API Tree : public VirtualLightRefBase {
 public:
     Tree(Group* rootNode) : mRootNode(rootNode) {}
     void draw(Canvas* outCanvas, SkColorFilter* colorFilter,
             const SkRect& bounds, bool needsMirroring, bool canReuseCache);
-    void drawCachedBitmapWithRootAlpha(Canvas* outCanvas, SkColorFilter* filter,
-            const SkRect& originalBounds);
 
-    void updateCachedBitmap(int width, int height);
+    const SkBitmap& getBitmapUpdateIfDirty();
     void createCachedBitmapIfNeeded(int width, int height);
     bool canReuseBitmap(int width, int height);
     void setAllowCaching(bool allowCaching) {
@@ -316,6 +343,10 @@
         mViewportWidth = viewportWidth;
         mViewportHeight = viewportHeight;
     }
+    SkPaint* getPaint();
+    const SkRect& getBounds() const {
+        return mBounds;
+    }
 
 private:
     // Cap the bitmap size, such that it won't hurt the performance too much
@@ -329,7 +360,7 @@
     float mViewportHeight = 0;
     float mRootAlpha = 1.0f;
 
-    Group* mRootNode;
+    std::unique_ptr<Group> mRootNode;
     SkRect mBounds;
     SkMatrix mCanvasMatrix;
     SkPaint mPaint;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index e7cf3ec..ea702c0 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -33,10 +33,6 @@
 #include "utils/GLUtils.h"
 #include "utils/TimeUtils.h"
 
-#if HWUI_NEW_OPS
-#include "FrameBuilder.h"
-#endif
-
 #include <cutils/properties.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <private/hwui/DrawGlInfo.h>
@@ -96,18 +92,18 @@
     }
 }
 
-void CanvasContext::setSurface(ANativeWindow* window) {
+void CanvasContext::setSurface(Surface* surface) {
     ATRACE_CALL();
 
-    mNativeWindow = window;
+    mNativeSurface = surface;
 
     if (mEglSurface != EGL_NO_SURFACE) {
         mEglManager.destroySurface(mEglSurface);
         mEglSurface = EGL_NO_SURFACE;
     }
 
-    if (window) {
-        mEglSurface = mEglManager.createSurface(window);
+    if (surface) {
+        mEglSurface = mEglManager.createSurface(surface);
     }
 
     if (mEglSurface != EGL_NO_SURFACE) {
@@ -131,8 +127,8 @@
     mSwapBehavior = swapBehavior;
 }
 
-void CanvasContext::initialize(ANativeWindow* window) {
-    setSurface(window);
+void CanvasContext::initialize(Surface* surface) {
+    setSurface(surface);
 #if !HWUI_NEW_OPS
     if (mCanvas) return;
     mCanvas = new OpenGLRenderer(mRenderThread.renderState());
@@ -140,11 +136,11 @@
 #endif
 }
 
-void CanvasContext::updateSurface(ANativeWindow* window) {
-    setSurface(window);
+void CanvasContext::updateSurface(Surface* surface) {
+    setSurface(surface);
 }
 
-bool CanvasContext::pauseSurface(ANativeWindow* window) {
+bool CanvasContext::pauseSurface(Surface* surface) {
     return mRenderThread.removeFrameCallback(this);
 }
 
@@ -152,7 +148,7 @@
 void CanvasContext::setup(int width, int height, float lightRadius,
         uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
 #if HWUI_NEW_OPS
-    mLightInfo.lightRadius = lightRadius;
+    mLightGeometry.radius = lightRadius;
     mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
     mLightInfo.spotShadowAlpha = spotShadowAlpha;
 #else
@@ -163,7 +159,7 @@
 
 void CanvasContext::setLightCenter(const Vector3& lightCenter) {
 #if HWUI_NEW_OPS
-    mLightCenter = lightCenter;
+    mLightGeometry.center = lightCenter;
 #else
     if (!mCanvas) return;
     mCanvas->setLightCenter(lightCenter);
@@ -208,6 +204,10 @@
     info.renderer = mCanvas;
 #endif
 
+    if (CC_LIKELY(mNativeSurface.get())) {
+        info.frameNumber = static_cast<int64_t>(mNativeSurface->getNextFrameNumber());
+    }
+
     mAnimationContext->startFrame(info.mode);
     for (const sp<RenderNode>& node : mRenderNodes) {
         // Only the primary target node will be drawn full - all other nodes would get drawn in
@@ -223,7 +223,7 @@
     freePrefetechedLayers();
     GL_CHECKPOINT(MODERATE);
 
-    if (CC_UNLIKELY(!mNativeWindow.get())) {
+    if (CC_UNLIKELY(!mNativeSurface.get())) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
         info.out.canDrawThisFrame = false;
         return;
@@ -246,8 +246,9 @@
         } else {
             // We're maybe behind? Find out for sure
             int runningBehind = 0;
-            mNativeWindow->query(mNativeWindow.get(),
-                    NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
+            // TODO: Have this method be on Surface, too, not just ANativeWindow...
+            ANativeWindow* window = mNativeSurface.get();
+            window->query(window, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
             info.out.canDrawThisFrame = !runningBehind;
         }
     } else {
@@ -345,7 +346,7 @@
 
 #if HWUI_NEW_OPS
     FrameBuilder frameBuilder(mLayerUpdateQueue, dirty, frame.width(), frame.height(),
-            mRenderNodes, mLightCenter, mContentDrawBounds);
+            mRenderNodes, mLightGeometry, mContentDrawBounds, &Caches::getInstance());
     mLayerUpdateQueue.clear();
     BakedOpRenderer renderer(Caches::getInstance(), mRenderThread.renderState(),
             mOpaque, mLightInfo);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 270fb1f..168166e 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -31,6 +31,7 @@
 #if HWUI_NEW_OPS
 #include "BakedOpDispatcher.h"
 #include "BakedOpRenderer.h"
+#include "FrameBuilder.h"
 #endif
 
 #include <cutils/compiler.h>
@@ -38,6 +39,7 @@
 #include <SkBitmap.h>
 #include <SkRect.h>
 #include <utils/Functor.h>
+#include <gui/Surface.h>
 
 #include <set>
 #include <string>
@@ -74,10 +76,10 @@
     // Won't take effect until next EGLSurface creation
     void setSwapBehavior(SwapBehavior swapBehavior);
 
-    void initialize(ANativeWindow* window);
-    void updateSurface(ANativeWindow* window);
-    bool pauseSurface(ANativeWindow* window);
-    bool hasSurface() { return mNativeWindow.get(); }
+    void initialize(Surface* surface);
+    void updateSurface(Surface* surface);
+    bool pauseSurface(Surface* surface);
+    bool hasSurface() { return mNativeSurface.get(); }
 
     void setup(int width, int height, float lightRadius,
             uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
@@ -171,7 +173,7 @@
     // lifecycle tracking
     friend class android::uirenderer::RenderState;
 
-    void setSurface(ANativeWindow* window);
+    void setSurface(Surface* window);
     void requireSurface();
 
     void freePrefetechedLayers();
@@ -181,7 +183,7 @@
 
     RenderThread& mRenderThread;
     EglManager& mEglManager;
-    sp<ANativeWindow> mNativeWindow;
+    sp<Surface> mNativeSurface;
     EGLSurface mEglSurface = EGL_NO_SURFACE;
     bool mBufferPreserved = false;
     SwapBehavior mSwapBehavior = kSwap_default;
@@ -197,7 +199,7 @@
     OpenGLRenderer* mCanvas = nullptr;
 #if HWUI_NEW_OPS
     BakedOpRenderer::LightInfo mLightInfo;
-    Vector3 mLightCenter = { 0, 0, 0 };
+    FrameBuilder::LightGeometry mLightGeometry = { {0, 0, 0}, 0 };
 #endif
 
     bool mHaveNewSurface = false;
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 466fef9..364d4dd 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -228,6 +228,13 @@
     LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
             "Failed to create EGLSurface for window %p, eglErr = %s",
             (void*) window, egl_error_str());
+
+    if (mSwapBehavior != SwapBehavior::Preserved) {
+        LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED) == EGL_FALSE,
+                            "Failed to set swap behavior to destroyed for window %p, eglErr = %s",
+                            (void*) window, egl_error_str());
+    }
+
     return surface;
 }
 
@@ -337,8 +344,8 @@
         // For some reason our surface was destroyed out from under us
         // This really shouldn't happen, but if it does we can recover easily
         // by just not trying to use the surface anymore
-        ALOGW("swapBuffers encountered EGL_BAD_SURFACE on %p, halting rendering...",
-                frame.mSurface);
+        ALOGW("swapBuffers encountered EGL error %d on %p, halting rendering...",
+                err, frame.mSurface);
         return false;
     }
     LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering",
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 1d1b144..7c6cd7e 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -139,38 +139,38 @@
     postAndWait(task); // block since name/value pointers owned by caller
 }
 
-CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) {
-    args->context->initialize(args->window);
+CREATE_BRIDGE2(initialize, CanvasContext* context, Surface* surface) {
+    args->context->initialize(args->surface);
     return nullptr;
 }
 
-void RenderProxy::initialize(const sp<ANativeWindow>& window) {
+void RenderProxy::initialize(const sp<Surface>& surface) {
     SETUP_TASK(initialize);
     args->context = mContext;
-    args->window = window.get();
+    args->surface = surface.get();
     post(task);
 }
 
-CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) {
-    args->context->updateSurface(args->window);
+CREATE_BRIDGE2(updateSurface, CanvasContext* context, Surface* surface) {
+    args->context->updateSurface(args->surface);
     return nullptr;
 }
 
-void RenderProxy::updateSurface(const sp<ANativeWindow>& window) {
+void RenderProxy::updateSurface(const sp<Surface>& surface) {
     SETUP_TASK(updateSurface);
     args->context = mContext;
-    args->window = window.get();
+    args->surface = surface.get();
     postAndWait(task);
 }
 
-CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) {
-    return (void*) args->context->pauseSurface(args->window);
+CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) {
+    return (void*) args->context->pauseSurface(args->surface);
 }
 
-bool RenderProxy::pauseSurface(const sp<ANativeWindow>& window) {
+bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
     SETUP_TASK(pauseSurface);
     args->context = mContext;
-    args->window = window.get();
+    args->surface = surface.get();
     return (bool) postAndWait(task);
 }
 
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 4180d802..178724a 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -67,9 +67,9 @@
     ANDROID_API bool loadSystemProperties();
     ANDROID_API void setName(const char* name);
 
-    ANDROID_API void initialize(const sp<ANativeWindow>& window);
-    ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
-    ANDROID_API bool pauseSurface(const sp<ANativeWindow>& window);
+    ANDROID_API void initialize(const sp<Surface>& surface);
+    ANDROID_API void updateSurface(const sp<Surface>& surface);
+    ANDROID_API bool pauseSurface(const sp<Surface>& surface);
     ANDROID_API void setup(int width, int height, float lightRadius,
             uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
     ANDROID_API void setLightCenter(const Vector3& lightCenter);
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index a843e92..58c0876 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -112,9 +112,9 @@
             scene->doFrame(i);
             proxy->syncAndDrawFrame();
         }
-        proxy->fence();
-        nsecs_t done = systemTime(CLOCK_MONOTONIC);
         if (opts.reportFrametimeWeight) {
+            proxy->fence();
+            nsecs_t done = systemTime(CLOCK_MONOTONIC);
             avgMs.add((done - vsync) / 1000000.0);
             if (i % 10 == 9) {
                 printf("Average frametime %.3fms\n", avgMs.average());
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index 83af148..b317c12 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -63,7 +63,7 @@
 
     StartBenchmarkTiming();
     for (int i = 0; i < iters; ++i) {
-        canvas.reset(100, 100);
+        canvas.resetRecording(100, 100);
         MicroBench::DoNotOptimize(&canvas);
         delete canvas.finishRecording();
     }
@@ -77,7 +77,7 @@
 
     StartBenchmarkTiming();
     for (int i = 0; i < iters; ++i) {
-        canvas.reset(100, 100);
+        canvas.resetRecording(100, 100);
         canvas.save(SaveFlags::MatrixClip);
         canvas.save(SaveFlags::MatrixClip);
         MicroBench::DoNotOptimize(&canvas);
@@ -95,7 +95,7 @@
 
     StartBenchmarkTiming();
     for (int i = 0; i < iters; ++i) {
-        canvas.reset(100, 100);
+        canvas.resetRecording(100, 100);
         canvas.scale(10, 10);
         MicroBench::DoNotOptimize(&canvas);
         delete canvas.finishRecording();
@@ -119,7 +119,7 @@
 
     StartBenchmarkTiming();
     for (int i = 0; i < iters; ++i) {
-        canvas.reset(100, 100);
+        canvas.resetRecording(100, 100);
         {
             canvas.save(SaveFlags::MatrixClip);
             canvas.drawRect(0, 0, 100, 100, rectPaint);
diff --git a/libs/hwui/tests/microbench/FrameBuilderBench.cpp b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
index f9c2b67..7845eb4 100644
--- a/libs/hwui/tests/microbench/FrameBuilderBench.cpp
+++ b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
@@ -37,7 +37,8 @@
 using namespace android::uirenderer::test;
 
 const LayerUpdateQueue sEmptyLayerUpdateQueue;
-const Vector3 sLightCenter = {100, 100, 100};
+const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50};
+const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
 
 static std::vector<sp<RenderNode>> createTestNodeList() {
     auto node = TestUtils::createNode(0, 0, 200, 200,
@@ -67,7 +68,7 @@
     StartBenchmarkTiming();
     for (int i = 0; i < iters; i++) {
         FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
-                nodes, sLightCenter);
+                nodes, sLightGeometry, nullptr);
         MicroBench::DoNotOptimize(&frameBuilder);
     }
     StopBenchmarkTiming();
@@ -77,7 +78,6 @@
 void BM_FrameBuilder_deferAndRender::Run(int iters) {
     TestUtils::runOnRenderThread([this, iters](RenderThread& thread) {
         auto nodes = createTestNodeList();
-        BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128 };
 
         RenderState& renderState = thread.renderState();
         Caches& caches = Caches::getInstance();
@@ -85,9 +85,9 @@
         StartBenchmarkTiming();
         for (int i = 0; i < iters; i++) {
             FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
-                    nodes, sLightCenter);
+                    nodes, sLightGeometry, nullptr);
 
-            BakedOpRenderer renderer(caches, renderState, true, lightInfo);
+            BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
             frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
             MicroBench::DoNotOptimize(&renderer);
         }
@@ -119,7 +119,7 @@
     for (int i = 0; i < iters; i++) {
         FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
                 SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
-                nodes, sLightCenter);
+                nodes, sLightGeometry, nullptr);
         MicroBench::DoNotOptimize(&frameBuilder);
     }
     benchmark.StopBenchmarkTiming();
@@ -129,7 +129,6 @@
         int iters, const char* sceneName) {
     TestUtils::runOnRenderThread([&benchmark, iters, sceneName](RenderThread& thread) {
         auto nodes = getSyncedSceneNodes(sceneName);
-        BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128 }; // TODO!
 
         RenderState& renderState = thread.renderState();
         Caches& caches = Caches::getInstance();
@@ -138,9 +137,9 @@
         for (int i = 0; i < iters; i++) {
             FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
                     SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
-                    nodes, sLightCenter);
+                    nodes, sLightGeometry, nullptr);
 
-            BakedOpRenderer renderer(caches, renderState, true, lightInfo);
+            BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
             frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
             MicroBench::DoNotOptimize(&renderer);
         }
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 618df14..f49dd3f 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -30,7 +30,8 @@
 namespace uirenderer {
 
 const LayerUpdateQueue sEmptyLayerUpdateQueue;
-const Vector3 sLightCenter = {100, 100, 100};
+const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50};
+
 
 /**
  * Virtual class implemented by each test to redirect static operation / state transitions to
@@ -132,7 +133,7 @@
         canvas.drawBitmap(bitmap, 10, 10, nullptr);
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     SimpleTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end
@@ -158,7 +159,7 @@
         canvas.drawPoint(50, 50, strokedPaint);
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     SimpleStrokeTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(1, renderer.getIndex());
@@ -173,7 +174,7 @@
         canvas.restore();
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
 
     FailRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
@@ -208,7 +209,7 @@
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     SimpleBatchingTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(2 * LOOPS, renderer.getIndex())
@@ -250,7 +251,7 @@
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     ClippedMergingTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(4, renderer.getIndex());
@@ -278,7 +279,7 @@
         TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     TextMergingTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops";
@@ -309,7 +310,7 @@
         }
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     TextStrikethroughTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(2 * LOOPS, renderer.getIndex())
@@ -343,7 +344,7 @@
         canvas.restore();
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     TextureLayerTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(1, renderer.getIndex());
@@ -388,7 +389,7 @@
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(parent), sLightCenter);
+            TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
     RenderNodeTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
 }
@@ -412,7 +413,7 @@
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
             SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
-            200, 200, TestUtils::createSyncedNodeList(node), sLightCenter);
+            200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     ClippedTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
 }
@@ -454,7 +455,7 @@
         canvas.restore();
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     SaveLayerSimpleTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(4, renderer.getIndex());
@@ -526,7 +527,7 @@
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     SaveLayerNestedTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(10, renderer.getIndex());
@@ -546,7 +547,7 @@
         canvas.restore();
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
 
     FailRenderer renderer;
     // should see no ops, even within the layer, since the layer should be rejected
@@ -589,7 +590,7 @@
         canvas.restore();
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     SaveLayerUnclippedSimpleTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(4, renderer.getIndex());
@@ -643,7 +644,7 @@
         canvas.restoreToCount(restoreTo);
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     SaveLayerUnclippedMergedClearsTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(10, renderer.getIndex())
@@ -705,7 +706,7 @@
         canvas.restore();
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     SaveLayerUnclippedComplexTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(12, renderer.getIndex());
@@ -763,7 +764,7 @@
     layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
 
     FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            syncedNodeList, sLightCenter);
+            syncedNodeList, sLightGeometry, nullptr);
     HwLayerSimpleTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(6, renderer.getIndex());
@@ -864,7 +865,7 @@
     layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200));
 
     FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            syncedList, sLightCenter);
+            syncedList, sLightGeometry, nullptr);
     HwLayerComplexTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(13, renderer.getIndex());
@@ -913,7 +914,7 @@
         drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
     });
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
-            TestUtils::createSyncedNodeList(parent), sLightCenter);
+            TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
     ZReorderTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(10, renderer.getIndex());
@@ -996,7 +997,7 @@
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
-            TestUtils::createSyncedNodeList(parent), sLightCenter);
+            TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
     ProjectionReorderTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(3, renderer.getIndex());
@@ -1014,18 +1015,18 @@
     });
 }
 
-TEST(FrameBuilder, shadow) {
+RENDERTHREAD_TEST(FrameBuilder, shadow) {
     class ShadowTestRenderer : public TestRendererBase {
     public:
         void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
             EXPECT_EQ(0, mIndex++);
             EXPECT_FLOAT_EQ(1.0f, op.casterAlpha);
-            EXPECT_TRUE(op.casterPath->isRect(nullptr));
-            EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowMatrixXY);
+            EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr));
+            EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY);
 
             Matrix4 expectedZ;
             expectedZ.loadTranslate(0, 0, 5);
-            EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowMatrixZ);
+            EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ);
         }
         void onRectOp(const RectOp& op, const BakedOpState& state) override {
             EXPECT_EQ(1, mIndex++);
@@ -1039,13 +1040,13 @@
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(parent), sLightCenter);
+            TestUtils::createSyncedNodeList(parent), sLightGeometry, &Caches::getInstance());
     ShadowTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(2, renderer.getIndex());
 }
 
-TEST(FrameBuilder, shadowSaveLayer) {
+RENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) {
     class ShadowSaveLayerTestRenderer : public TestRendererBase {
     public:
         OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
@@ -1054,8 +1055,8 @@
         }
         void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
             EXPECT_EQ(1, mIndex++);
-            EXPECT_FLOAT_EQ(50, op.lightCenter.x);
-            EXPECT_FLOAT_EQ(40, op.lightCenter.y);
+            EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x);
+            EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y);
         }
         void onRectOp(const RectOp& op, const BakedOpState& state) override {
             EXPECT_EQ(2, mIndex++);
@@ -1080,7 +1081,9 @@
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(parent), (Vector3) { 100, 100, 100 });
+            TestUtils::createSyncedNodeList(parent),
+            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50},
+            &Caches::getInstance());
     ShadowSaveLayerTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(5, renderer.getIndex());
@@ -1094,8 +1097,9 @@
         }
         void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
             EXPECT_EQ(1, mIndex++);
-            EXPECT_FLOAT_EQ(50, op.lightCenter.x);
-            EXPECT_FLOAT_EQ(40, op.lightCenter.y);
+            EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x);
+            EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y);
+            EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius);
         }
         void onRectOp(const RectOp& op, const BakedOpState& state) override {
             EXPECT_EQ(2, mIndex++);
@@ -1130,7 +1134,9 @@
     LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
     layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100));
     FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            syncedList, (Vector3) { 100, 100, 100 });
+            syncedList,
+            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30},
+            &Caches::getInstance());
     ShadowHwLayerTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(5, renderer.getIndex());
@@ -1159,7 +1165,9 @@
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(parent), sLightCenter);
+            TestUtils::createSyncedNodeList(parent),
+            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50},
+            &Caches::getInstance());
     ShadowLayeringTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(4, renderer.getIndex());
@@ -1187,7 +1195,7 @@
     });
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
     PropertyTestRenderer renderer(opValidateCallback);
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
     EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op";
@@ -1328,7 +1336,8 @@
     });
     auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height
 
-    FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, nodes, sLightCenter);
+    FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+            nodes, sLightGeometry, nullptr);
     SaveLayerAlphaClipTestRenderer renderer(outObservedData);
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
 
diff --git a/libs/hwui/tests/unit/GradientCacheTests.cpp b/libs/hwui/tests/unit/GradientCacheTests.cpp
new file mode 100644
index 0000000..0ee9647
--- /dev/null
+++ b/libs/hwui/tests/unit/GradientCacheTests.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "Extensions.h"
+#include "GradientCache.h"
+#include "tests/common/TestUtils.h"
+
+using namespace android;
+using namespace android::uirenderer;
+
+RENDERTHREAD_TEST(GradientCache, addRemove) {
+    Extensions extensions;
+    GradientCache cache(extensions);
+    ASSERT_LT(1000u, cache.getMaxSize()) << "Expect non-trivial size";
+
+    SkColor colors[] = { 0xFF00FF00, 0xFFFF0000, 0xFF0000FF };
+    float positions[] = { 1, 2, 3 };
+    Texture* texture = cache.get(colors, positions, 3);
+    ASSERT_TRUE(texture);
+    ASSERT_FALSE(texture->cleanup);
+    ASSERT_EQ((uint32_t) texture->objectSize(), cache.getSize());
+    ASSERT_TRUE(cache.getSize());
+    cache.clear();
+    ASSERT_EQ(cache.getSize(), 0u);
+}
diff --git a/libs/hwui/tests/unit/LeakCheckTests.cpp b/libs/hwui/tests/unit/LeakCheckTests.cpp
index 4a635fb..da786c7 100644
--- a/libs/hwui/tests/unit/LeakCheckTests.cpp
+++ b/libs/hwui/tests/unit/LeakCheckTests.cpp
@@ -27,7 +27,8 @@
 using namespace android::uirenderer;
 
 const LayerUpdateQueue sEmptyLayerUpdateQueue;
-const Vector3 sLightCenter = {100, 100, 100};
+const FrameBuilder::LightGeometry sLightGeometery = { {100, 100, 100}, 50};
+const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
 
 RENDERTHREAD_TEST(LeakCheck, saveLayerUnclipped_simple) {
     auto node = TestUtils::createNode(0, 0, 200, 200,
@@ -36,12 +37,11 @@
         canvas.drawRect(0, 0, 200, 200, SkPaint());
         canvas.restore();
     });
-    BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128};
     RenderState& renderState = renderThread.renderState();
     Caches& caches = Caches::getInstance();
 
     FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
-            TestUtils::createSyncedNodeList(node), sLightCenter);
-    BakedOpRenderer renderer(caches, renderState, true, lightInfo);
+            TestUtils::createSyncedNodeList(node), sLightGeometery, nullptr);
+    BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
     frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
 }
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 01bfc5a..20d2f1f 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -455,6 +455,23 @@
     }
 }
 
+TEST(RecordingCanvas, firstClipWillReplace) {
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+        canvas.save(SaveFlags::MatrixClip);
+        // since no explicit clip set on canvas, this should be the one observed on op:
+        canvas.clipRect(-100, -100, 300, 300, SkRegion::kIntersect_Op);
+
+        SkPaint paint;
+        paint.setColor(SK_ColorWHITE);
+        canvas.drawRect(0, 0, 100, 100, paint);
+
+        canvas.restore();
+    });
+    ASSERT_EQ(1u, dl->getOps().size()) << "Must have one op";
+    // first clip must be preserved, even if it extends beyond canvas bounds
+    EXPECT_CLIP_RECT(Rect(-100, -100, 300, 300), dl->getOps()[0]->localClip);
+}
+
 TEST(RecordingCanvas, insertReorderBarrier) {
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
         canvas.drawRect(0, 0, 400, 400, SkPaint());
diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
new file mode 100644
index 0000000..586625b
--- /dev/null
+++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#include "tests/common/TestUtils.h"
+
+#include <gtest/gtest.h>
+#include <SkShader.h>
+
+using namespace android;
+using namespace android::uirenderer;
+
+/**
+ * 1x1 bitmaps must not be optimized into solid color shaders, since HWUI can't
+ * compose/render color shaders
+ */
+TEST(SkiaBehavior, CreateBitmapShader1x1) {
+    SkBitmap origBitmap = TestUtils::createSkBitmap(1, 1);
+    std::unique_ptr<SkShader> s(SkShader::CreateBitmapShader(
+            origBitmap,
+            SkShader::kClamp_TileMode,
+            SkShader::kRepeat_TileMode));
+
+    SkBitmap bitmap;
+    SkShader::TileMode xy[2];
+    ASSERT_TRUE(s->isABitmap(&bitmap, nullptr, xy))
+        << "1x1 bitmap shader must query as bitmap shader";
+    EXPECT_EQ(SkShader::kClamp_TileMode, xy[0]);
+    EXPECT_EQ(SkShader::kRepeat_TileMode, xy[1]);
+    EXPECT_EQ(origBitmap.pixelRef(), bitmap.pixelRef());
+}
diff --git a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
new file mode 100644
index 0000000..c54f2c3
--- /dev/null
+++ b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "GammaFontRenderer.h"
+#include "TextDropShadowCache.h"
+#include "utils/Blur.h"
+#include "tests/common/TestUtils.h"
+
+#include <SkBlurDrawLooper.h>
+#include <SkPaint.h>
+
+using namespace android;
+using namespace android::uirenderer;
+
+RENDERTHREAD_TEST(TextDropShadowCache, addRemove) {
+    GammaFontRenderer gammaFontRenderer;
+    FontRenderer& fontRenderer = gammaFontRenderer.getFontRenderer();
+    TextDropShadowCache cache(5000);
+    cache.setFontRenderer(fontRenderer);
+
+    SkPaint paint;
+    paint.setLooper(SkBlurDrawLooper::Create((SkColor)0xFFFFFFFF,
+            Blur::convertRadiusToSigma(10), 10, 10))->unref();
+    std::string msg("This is a test");
+    std::unique_ptr<float[]> positions(new float[msg.length()]);
+    for (size_t i = 0; i < msg.length(); i++) {
+        positions[i] = i * 10.0f;
+    }
+    fontRenderer.setFont(&paint, SkMatrix::I());
+    ShadowTexture* texture = cache.get(&paint, msg.c_str(), msg.length(),
+            10.0f, positions.get());
+    ASSERT_TRUE(texture);
+    ASSERT_FALSE(texture->cleanup);
+    ASSERT_EQ((uint32_t) texture->objectSize(), cache.getSize());
+    ASSERT_TRUE(cache.getSize());
+    cache.clear();
+    ASSERT_EQ(cache.getSize(), 0u);
+}
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
new file mode 100644
index 0000000..37ef3df79
--- /dev/null
+++ b/location/java/android/location/GnssClock.java
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.location;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A class containing a GPS clock timestamp.
+ * 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
+
+    /** The type of the GPS Clock. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({CLOCK_TYPE_UNKNOWN, CLOCK_TYPE_LOCAL_HW_TIME, CLOCK_TYPE_GPS_TIME})
+    public @interface GnssClockType {}
+
+    /**
+     * The type of the time stored is not available or it is unknown.
+     */
+    public static final byte CLOCK_TYPE_UNKNOWN = 0;
+
+    /**
+     * The source of the time value reported by this class is the 'Local Hardware Clock'.
+     */
+    public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1;
+
+    /**
+     * The source of the time value reported by this class is the 'GPS time' derived from
+     * satellites (epoch = Jan 6, 1980).
+     */
+    public static final byte CLOCK_TYPE_GPS_TIME = 2;
+
+    private static final short HAS_NO_FLAGS = 0;
+    private static final short HAS_LEAP_SECOND = (1<<0);
+    private static final short HAS_TIME_UNCERTAINTY = (1<<1);
+    private static final short HAS_FULL_BIAS = (1<<2);
+    private static final short HAS_BIAS = (1<<3);
+    private static final short HAS_BIAS_UNCERTAINTY = (1<<4);
+    private static final short HAS_DRIFT = (1<<5);
+    private static final short HAS_DRIFT_UNCERTAINTY = (1<<6);
+
+    // End enumerations in sync with gps.h
+
+    private short mFlags;
+    private short mLeapSecond;
+    private byte mType;
+    private long mTimeInNs;
+    private double mTimeUncertaintyInNs;
+    private long mFullBiasInNs;
+    private double mBiasInNs;
+    private double mBiasUncertaintyInNs;
+    private double mDriftInNsPerSec;
+    private double mDriftUncertaintyInNsPerSec;
+    private long mTimeOfLastHwClockDiscontinuityInNs;
+
+    GnssClock() {
+        initialize();
+    }
+
+    /**
+     * Sets all contents to the values stored in the provided object.
+     */
+    public void set(GnssClock clock) {
+        mFlags = clock.mFlags;
+        mLeapSecond = clock.mLeapSecond;
+        mType = clock.mType;
+        mTimeInNs = clock.mTimeInNs;
+        mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs;
+        mFullBiasInNs = clock.mFullBiasInNs;
+        mBiasInNs = clock.mBiasInNs;
+        mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
+        mDriftInNsPerSec = clock.mDriftInNsPerSec;
+        mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
+        mTimeOfLastHwClockDiscontinuityInNs = clock.mTimeOfLastHwClockDiscontinuityInNs;
+    }
+
+    /**
+     * Resets all the contents to its original state.
+     */
+    public void reset() {
+        initialize();
+    }
+
+    /**
+     * Gets the type of time reported by {@link #getTimeInNs()}.
+     */
+    @GnssClockType
+    public byte getType() {
+        return mType;
+    }
+
+    /**
+     * Sets the type of time reported.
+     */
+    public void setType(@GnssClockType byte value) {
+        mType = value;
+    }
+
+    /**
+     * Gets a string representation of the 'type'.
+     * For internal and logging use only.
+     */
+    private String getTypeString() {
+        switch (mType) {
+            case CLOCK_TYPE_UNKNOWN:
+                return "Unknown";
+            case CLOCK_TYPE_GPS_TIME:
+                return "GpsTime";
+            case CLOCK_TYPE_LOCAL_HW_TIME:
+                return "LocalHwClock";
+            default:
+                return "<Invalid:" + mType + ">";
+        }
+    }
+
+    /**
+     * Returns true if {@link #getLeapSecond()} is available, false otherwise.
+     */
+    public boolean hasLeapSecond() {
+        return isFlagSet(HAS_LEAP_SECOND);
+    }
+
+    /**
+     * 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.
+     */
+    public short getLeapSecond() {
+        return mLeapSecond;
+    }
+
+    /**
+     * Sets the leap second associated with the clock's time.
+     */
+    public void setLeapSecond(short leapSecond) {
+        setFlag(HAS_LEAP_SECOND);
+        mLeapSecond = leapSecond;
+    }
+
+    /**
+     * Resets the leap second associated with the clock's time.
+     */
+    public void resetLeapSecond() {
+        resetFlag(HAS_LEAP_SECOND);
+        mLeapSecond = Short.MIN_VALUE;
+    }
+
+    /**
+     * Gets the GPS receiver internal clock value in nanoseconds.
+     * This can be either the 'local hardware clock' value ({@link #CLOCK_TYPE_LOCAL_HW_TIME}), or the
+     * current GPS time derived inside GPS receiver ({@link #CLOCK_TYPE_GPS_TIME}).
+     * {@link #getType()} defines the time reported.
+     *
+     * For 'local hardware clock' this value is expected to be monotonically increasing during the
+     * reporting session. The real GPS time can be derived by compensating
+     * {@link #getFullBiasInNs()} (when it is available) from this value.
+     *
+     * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
+     * receiver can achieve. {@link #getTimeUncertaintyInNs()} should be available when GPS time is
+     * specified.
+     *
+     * Sub-nanosecond accuracy can be provided by means of {@link #getBiasInNs()}.
+     * The reported time includes {@link #getTimeUncertaintyInNs()}.
+     */
+    public long getTimeInNs() {
+        return mTimeInNs;
+    }
+
+    /**
+     * Sets the GPS receiver internal clock in nanoseconds.
+     */
+    public void setTimeInNs(long timeInNs) {
+        mTimeInNs = timeInNs;
+    }
+
+    /**
+     * Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise.
+     */
+    public boolean hasTimeUncertaintyInNs() {
+        return isFlagSet(HAS_TIME_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * The value is only available if {@link #hasTimeUncertaintyInNs()} is true.
+     */
+    public double getTimeUncertaintyInNs() {
+        return mTimeUncertaintyInNs;
+    }
+
+    /**
+     * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
+     */
+    public void setTimeUncertaintyInNs(double timeUncertaintyInNs) {
+        setFlag(HAS_TIME_UNCERTAINTY);
+        mTimeUncertaintyInNs = timeUncertaintyInNs;
+    }
+
+    /**
+     * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
+     */
+    public void resetTimeUncertaintyInNs() {
+        resetFlag(HAS_TIME_UNCERTAINTY);
+        mTimeUncertaintyInNs = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getFullBiasInNs()} is available, false otherwise.
+     */
+    public boolean hasFullBiasInNs() {
+        return isFlagSet(HAS_FULL_BIAS);
+    }
+
+    /**
+     * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
+     * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
+     *
+     * This value is available if {@link #CLOCK_TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved
+     * the clock for GPS time.
+     * {@link #getBiasUncertaintyInNs()} should be used for quality check.
+     *
+     * The sign of the value is defined by the following equation:
+     *      true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
+     *
+     * The reported full bias includes {@link #getBiasUncertaintyInNs()}.
+     * The value is onl available if {@link #hasFullBiasInNs()} is true.
+     */
+    public long getFullBiasInNs() {
+        return mFullBiasInNs;
+    }
+
+    /**
+     * Sets the full bias in nanoseconds.
+     */
+    public void setFullBiasInNs(long value) {
+        setFlag(HAS_FULL_BIAS);
+        mFullBiasInNs = value;
+    }
+
+    /**
+     * Resets the full bias in nanoseconds.
+     */
+    public void resetFullBiasInNs() {
+        resetFlag(HAS_FULL_BIAS);
+        mFullBiasInNs = Long.MIN_VALUE;
+    }
+
+    /**
+     * Returns true if {@link #getBiasInNs()} is available, false otherwise.
+     */
+    public boolean hasBiasInNs() {
+        return isFlagSet(HAS_BIAS);
+    }
+
+    /**
+     * Gets the clock's sub-nanosecond bias.
+     * The reported bias includes {@link #getBiasUncertaintyInNs()}.
+     *
+     * The value is only available if {@link #hasBiasInNs()} is true.
+     */
+    public double getBiasInNs() {
+        return mBiasInNs;
+    }
+
+    /**
+     * Sets the sub-nanosecond bias.
+     */
+    public void setBiasInNs(double biasInNs) {
+        setFlag(HAS_BIAS);
+        mBiasInNs = biasInNs;
+    }
+
+    /**
+     * Resets the clock's Bias in nanoseconds.
+     */
+    public void resetBiasInNs() {
+        resetFlag(HAS_BIAS);
+        mBiasInNs = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise.
+     */
+    public boolean hasBiasUncertaintyInNs() {
+        return isFlagSet(HAS_BIAS_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
+     *
+     * The value is only available if {@link #hasBiasUncertaintyInNs()} is true.
+     */
+    public double getBiasUncertaintyInNs() {
+        return mBiasUncertaintyInNs;
+    }
+
+    /**
+     * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
+     */
+    public void setBiasUncertaintyInNs(double biasUncertaintyInNs) {
+        setFlag(HAS_BIAS_UNCERTAINTY);
+        mBiasUncertaintyInNs = biasUncertaintyInNs;
+    }
+
+    /**
+     * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
+     */
+    public void resetBiasUncertaintyInNs() {
+        resetFlag(HAS_BIAS_UNCERTAINTY);
+        mBiasUncertaintyInNs = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise.
+     */
+    public boolean hasDriftInNsPerSec() {
+        return isFlagSet(HAS_DRIFT);
+    }
+
+    /**
+     * Gets the clock's Drift in nanoseconds per second.
+     * A positive value indicates that the frequency is higher than the nominal frequency.
+     * The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}.
+     *
+     * The value is only available if {@link #hasDriftInNsPerSec()} is true.
+     */
+    public double getDriftInNsPerSec() {
+        return mDriftInNsPerSec;
+    }
+
+    /**
+     * Sets the clock's Drift in nanoseconds per second.
+     */
+    public void setDriftInNsPerSec(double driftInNsPerSec) {
+        setFlag(HAS_DRIFT);
+        mDriftInNsPerSec = driftInNsPerSec;
+    }
+
+    /**
+     * Resets the clock's Drift in nanoseconds per second.
+     */
+    public void resetDriftInNsPerSec() {
+        resetFlag(HAS_DRIFT);
+        mDriftInNsPerSec = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise.
+     */
+    public boolean hasDriftUncertaintyInNsPerSec() {
+        return isFlagSet(HAS_DRIFT_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
+     *
+     * The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true.
+     */
+    public double getDriftUncertaintyInNsPerSec() {
+        return mDriftUncertaintyInNsPerSec;
+    }
+
+    /**
+     * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
+     */
+    public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) {
+        setFlag(HAS_DRIFT_UNCERTAINTY);
+        mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec;
+    }
+
+    /**
+     * Gets time of last hardware clock discontinuity.
+     */
+    public long getTimeOfLastHwClockDiscontinuityInNs() {
+        return mTimeOfLastHwClockDiscontinuityInNs;
+    }
+
+    /**
+     * Sets time of last hardware clock discontinuity.
+     */
+    public void setTimeOfLastHwClockDiscontinuityInNs(long timeOfLastHwClockDiscontinuityInNs) {
+        mTimeOfLastHwClockDiscontinuityInNs = timeOfLastHwClockDiscontinuityInNs;
+    }
+
+    /**
+     * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
+     */
+    public void resetDriftUncertaintyInNsPerSec() {
+        resetFlag(HAS_DRIFT_UNCERTAINTY);
+        mDriftUncertaintyInNsPerSec = Double.NaN;
+    }
+
+    public static final Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
+        @Override
+        public GnssClock createFromParcel(Parcel parcel) {
+            GnssClock gpsClock = new GnssClock();
+
+            gpsClock.mFlags = (short) parcel.readInt();
+            gpsClock.mLeapSecond = (short) parcel.readInt();
+            gpsClock.mType = parcel.readByte();
+            gpsClock.mTimeInNs = parcel.readLong();
+            gpsClock.mTimeUncertaintyInNs = parcel.readDouble();
+            gpsClock.mFullBiasInNs = parcel.readLong();
+            gpsClock.mBiasInNs = parcel.readDouble();
+            gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
+            gpsClock.mDriftInNsPerSec = parcel.readDouble();
+            gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
+            gpsClock.mTimeOfLastHwClockDiscontinuityInNs = parcel.readLong();
+
+            return gpsClock;
+        }
+
+        @Override
+        public GnssClock[] newArray(int size) {
+            return new GnssClock[size];
+        }
+    };
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mFlags);
+        parcel.writeInt(mLeapSecond);
+        parcel.writeByte(mType);
+        parcel.writeLong(mTimeInNs);
+        parcel.writeDouble(mTimeUncertaintyInNs);
+        parcel.writeLong(mFullBiasInNs);
+        parcel.writeDouble(mBiasInNs);
+        parcel.writeDouble(mBiasUncertaintyInNs);
+        parcel.writeDouble(mDriftInNsPerSec);
+        parcel.writeDouble(mDriftUncertaintyInNsPerSec);
+        parcel.writeLong(mTimeOfLastHwClockDiscontinuityInNs);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        final String format = "   %-15s = %s\n";
+        final String formatWithUncertainty = "   %-15s = %-25s   %-26s = %s\n";
+        StringBuilder builder = new StringBuilder("GnssClock:\n");
+
+        builder.append(String.format(format, "Type", getTypeString()));
+
+        builder.append(String.format(format, "LeapSecond", hasLeapSecond() ? mLeapSecond : null));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "TimeInNs",
+                mTimeInNs,
+                "TimeUncertaintyInNs",
+                hasTimeUncertaintyInNs() ? mTimeUncertaintyInNs : null));
+
+        builder.append(String.format(
+                format,
+                "FullBiasInNs",
+                hasFullBiasInNs() ? mFullBiasInNs : null));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "BiasInNs",
+                hasBiasInNs() ? mBiasInNs : null,
+                "BiasUncertaintyInNs",
+                hasBiasUncertaintyInNs() ? mBiasUncertaintyInNs : null));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "DriftInNsPerSec",
+                hasDriftInNsPerSec() ? mDriftInNsPerSec : null,
+                "DriftUncertaintyInNsPerSec",
+                hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));
+
+        builder.append(String.format(format, "TimeOfLastHwClockDiscontinuityInNs",
+                getType() == CLOCK_TYPE_LOCAL_HW_TIME
+                        ? mTimeOfLastHwClockDiscontinuityInNs : null));
+
+        return builder.toString();
+    }
+
+    private void initialize() {
+        mFlags = HAS_NO_FLAGS;
+        resetLeapSecond();
+        setType(CLOCK_TYPE_UNKNOWN);
+        setTimeInNs(Long.MIN_VALUE);
+        resetTimeUncertaintyInNs();
+        resetFullBiasInNs();
+        resetBiasInNs();
+        resetBiasUncertaintyInNs();
+        resetDriftInNsPerSec();
+        resetDriftUncertaintyInNsPerSec();
+        setTimeOfLastHwClockDiscontinuityInNs(Long.MIN_VALUE);
+    }
+
+    private void setFlag(short flag) {
+        mFlags |= flag;
+    }
+
+    private void resetFlag(short flag) {
+        mFlags &= ~flag;
+    }
+
+    private boolean isFlagSet(short flag) {
+        return (mFlags & flag) == flag;
+    }
+}
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
new file mode 100644
index 0000000..d8f507c
--- /dev/null
+++ b/location/java/android/location/GnssMeasurement.java
@@ -0,0 +1,1471 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.location;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A class representing a GPS satellite measurement, containing raw and computed information.
+ */
+public final class GnssMeasurement implements Parcelable {
+    private int mFlags;
+    private byte mPrn;
+    private double mTimeOffsetInNs;
+    private short mState;
+    private long mReceivedGpsTowInNs;
+    private long mReceivedGpsTowUncertaintyInNs;
+    private double mCn0InDbHz;
+    private double mPseudorangeRateInMetersPerSec;
+    private double mPseudorangeRateUncertaintyInMetersPerSec;
+    private short mAccumulatedDeltaRangeState;
+    private double mAccumulatedDeltaRangeInMeters;
+    private double mAccumulatedDeltaRangeUncertaintyInMeters;
+    private double mPseudorangeInMeters;
+    private double mPseudorangeUncertaintyInMeters;
+    private double mCodePhaseInChips;
+    private double mCodePhaseUncertaintyInChips;
+    private float mCarrierFrequencyInHz;
+    private long mCarrierCycles;
+    private double mCarrierPhase;
+    private double mCarrierPhaseUncertainty;
+    private byte mLossOfLock;
+    private int mBitNumber;
+    private short mTimeFromLastBitInMs;
+    private double mDopplerShiftInHz;
+    private double mDopplerShiftUncertaintyInHz;
+    private byte mMultipathIndicator;
+    private double mSnrInDb;
+    private double mElevationInDeg;
+    private double mElevationUncertaintyInDeg;
+    private double mAzimuthInDeg;
+    private double mAzimuthUncertaintyInDeg;
+    private boolean mUsedInFix;
+    private double mPseudorangeRateCarrierInMetersPerSec;
+    private double mPseudorangeRateCarrierUncertaintyInMetersPerSec;
+
+    // The following enumerations must be in sync with the values declared in gps.h
+
+    private static final int HAS_NO_FLAGS = 0;
+    private static final int HAS_SNR = (1<<0);
+    private static final int HAS_ELEVATION = (1<<1);
+    private static final int HAS_ELEVATION_UNCERTAINTY = (1<<2);
+    private static final int HAS_AZIMUTH = (1<<3);
+    private static final int HAS_AZIMUTH_UNCERTAINTY = (1<<4);
+    private static final int HAS_PSEUDORANGE = (1<<5);
+    private static final int HAS_PSEUDORANGE_UNCERTAINTY = (1<<6);
+    private static final int HAS_CODE_PHASE = (1<<7);
+    private static final int HAS_CODE_PHASE_UNCERTAINTY = (1<<8);
+    private static final int HAS_CARRIER_FREQUENCY = (1<<9);
+    private static final int HAS_CARRIER_CYCLES = (1<<10);
+    private static final int HAS_CARRIER_PHASE = (1<<11);
+    private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12);
+    private static final int HAS_BIT_NUMBER = (1<<13);
+    private static final int HAS_TIME_FROM_LAST_BIT = (1<<14);
+    private static final int HAS_DOPPLER_SHIFT = (1<<15);
+    private static final int HAS_DOPPLER_SHIFT_UNCERTAINTY = (1<<16);
+    private static final int HAS_USED_IN_FIX = (1<<17);
+    private static final int GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18);
+
+    /** The status of 'loss of lock'. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({LOSS_OF_LOCK_UNKNOWN, LOSS_OF_LOCK_OK, LOSS_OF_LOCK_CYCLE_SLIP})
+    public @interface LossOfLockStatus {}
+
+    /**
+     * The indicator is not available or it is unknown.
+     */
+    public static final byte LOSS_OF_LOCK_UNKNOWN = 0;
+
+    /**
+     * The measurement does not present any indication of 'loss of lock'.
+     */
+    public static final byte LOSS_OF_LOCK_OK = 1;
+
+    /**
+     * 'Loss of lock' detected between the previous and current observation: cycle slip possible.
+     */
+    public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2;
+
+    /** The status of multipath. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({MULTIPATH_INDICATOR_UNKNOWN, MULTIPATH_INDICATOR_DETECTED,
+        MULTIPATH_INDICATOR_NOT_USED})
+    public @interface MultipathIndicator {}
+
+    /**
+     * The indicator is not available or it is unknown.
+     */
+    public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0;
+
+    /**
+     * The measurement has been indicated to use multi-path.
+     */
+    public static final byte MULTIPATH_INDICATOR_DETECTED = 1;
+
+    /**
+     * The measurement has been indicated not tu use multi-path.
+     */
+    public static final byte MULTIPATH_INDICATOR_NOT_USED = 2;
+
+    /**
+     * The state of GPS receiver the measurement is invalid or unknown.
+     */
+    public static final short STATE_UNKNOWN = 0;
+
+    /**
+     * The state of the GPS receiver is ranging code lock.
+     */
+    public static final short STATE_CODE_LOCK = (1<<0);
+
+    /**
+     * The state of the GPS receiver is in bit sync.
+     */
+    public static final short STATE_BIT_SYNC = (1<<1);
+
+    /**
+     *The state of the GPS receiver is in sub-frame sync.
+     */
+    public static final short STATE_SUBFRAME_SYNC = (1<<2);
+
+    /**
+     * The state of the GPS receiver has TOW decoded.
+     */
+    public static final short STATE_TOW_DECODED = (1<<3);
+
+    /**
+     * The state of the GPS receiver contains millisecond ambiguity.
+     */
+    public static final short STATE_MSEC_AMBIGUOUS = (1<<4);
+
+    /**
+     * All the GPS receiver state flags.
+     */
+    private static final short STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
+            | STATE_TOW_DECODED | STATE_MSEC_AMBIGUOUS;
+
+    /**
+     * The state of the 'Accumulated Delta Range' is invalid or unknown.
+     */
+    public static final short ADR_STATE_UNKNOWN = 0;
+
+    /**
+     * The state of the 'Accumulated Delta Range' is valid.
+     */
+    public static final short ADR_STATE_VALID = (1<<0);
+
+    /**
+     * The state of the 'Accumulated Delta Range' has detected a reset.
+     */
+    public static final short ADR_STATE_RESET = (1<<1);
+
+    /**
+     * The state of the 'Accumulated Delta Range' has a cycle slip detected.
+     */
+    public static final short ADR_STATE_CYCLE_SLIP = (1<<2);
+
+    /**
+     * All the 'Accumulated Delta Range' flags.
+     */
+    private static final short ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
+
+    // End enumerations in sync with gps.h
+
+    GnssMeasurement() {
+        initialize();
+    }
+
+    /**
+     * Sets all contents to the values stored in the provided object.
+     */
+    public void set(GnssMeasurement measurement) {
+        mFlags = measurement.mFlags;
+        mPrn = measurement.mPrn;
+        mTimeOffsetInNs = measurement.mTimeOffsetInNs;
+        mState = measurement.mState;
+        mReceivedGpsTowInNs = measurement.mReceivedGpsTowInNs;
+        mReceivedGpsTowUncertaintyInNs = measurement.mReceivedGpsTowUncertaintyInNs;
+        mCn0InDbHz = measurement.mCn0InDbHz;
+        mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec;
+        mPseudorangeRateUncertaintyInMetersPerSec =
+                measurement.mPseudorangeRateUncertaintyInMetersPerSec;
+        mAccumulatedDeltaRangeState = measurement.mAccumulatedDeltaRangeState;
+        mAccumulatedDeltaRangeInMeters = measurement.mAccumulatedDeltaRangeInMeters;
+        mAccumulatedDeltaRangeUncertaintyInMeters =
+                measurement.mAccumulatedDeltaRangeUncertaintyInMeters;
+        mPseudorangeInMeters = measurement.mPseudorangeInMeters;
+        mPseudorangeUncertaintyInMeters = measurement.mPseudorangeUncertaintyInMeters;
+        mCodePhaseInChips = measurement.mCodePhaseInChips;
+        mCodePhaseUncertaintyInChips = measurement.mCodePhaseUncertaintyInChips;
+        mCarrierFrequencyInHz = measurement.mCarrierFrequencyInHz;
+        mCarrierCycles = measurement.mCarrierCycles;
+        mCarrierPhase = measurement.mCarrierPhase;
+        mCarrierPhaseUncertainty = measurement.mCarrierPhaseUncertainty;
+        mLossOfLock = measurement.mLossOfLock;
+        mBitNumber = measurement.mBitNumber;
+        mTimeFromLastBitInMs = measurement.mTimeFromLastBitInMs;
+        mDopplerShiftInHz = measurement.mDopplerShiftInHz;
+        mDopplerShiftUncertaintyInHz = measurement.mDopplerShiftUncertaintyInHz;
+        mMultipathIndicator = measurement.mMultipathIndicator;
+        mSnrInDb = measurement.mSnrInDb;
+        mElevationInDeg = measurement.mElevationInDeg;
+        mElevationUncertaintyInDeg = measurement.mElevationUncertaintyInDeg;
+        mAzimuthInDeg = measurement.mAzimuthInDeg;
+        mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg;
+        mUsedInFix = measurement.mUsedInFix;
+        mPseudorangeRateCarrierInMetersPerSec =
+                measurement.mPseudorangeRateCarrierInMetersPerSec;
+        mPseudorangeRateCarrierUncertaintyInMetersPerSec =
+                measurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec;
+    }
+
+    /**
+     * Resets all the contents to its original state.
+     */
+    public void reset() {
+        initialize();
+    }
+
+    /**
+     * Gets the Pseudo-random number (PRN).
+     * Range: [1, 32]
+     */
+    public byte getPrn() {
+        return mPrn;
+    }
+
+    /**
+     * Sets the Pseud-random number (PRN).
+     */
+    public void setPrn(byte value) {
+        mPrn = value;
+    }
+
+    /**
+     * Gets the time offset at which the measurement was taken in nanoseconds.
+     * The reference receiver's time is specified by {@link GnssClock#getTimeInNs()} and should be
+     * interpreted in the same way as indicated by {@link GnssClock#getType()}.
+     *
+     * The sign of this value is given by the following equation:
+     *      measurement time = time_ns + time_offset_ns
+     *
+     * The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
+     * accuracy.
+     */
+    public double getTimeOffsetInNs() {
+        return mTimeOffsetInNs;
+    }
+
+    /**
+     * Sets the time offset at which the measurement was taken in nanoseconds.
+     */
+    public void setTimeOffsetInNs(double value) {
+        mTimeOffsetInNs = value;
+    }
+
+    /**
+     * Gets per-satellite sync state.
+     * It represents the current sync state for the associated satellite.
+     *
+     * This value helps interpret {@link #getReceivedGpsTowInNs()}.
+     */
+    public short getState() {
+        return mState;
+    }
+
+    /**
+     * Sets the sync state.
+     */
+    public void setState(short value) {
+        mState = value;
+    }
+
+    /**
+     * Gets a string representation of the 'sync state'.
+     * For internal and logging use only.
+     */
+    private String getStateString() {
+        if (mState == STATE_UNKNOWN) {
+            return "Unknown";
+        }
+        StringBuilder builder = new StringBuilder();
+        if ((mState & STATE_CODE_LOCK) == STATE_CODE_LOCK) {
+            builder.append("CodeLock|");
+        }
+        if ((mState & STATE_BIT_SYNC) == STATE_BIT_SYNC) {
+            builder.append("BitSync|");
+        }
+        if ((mState & STATE_SUBFRAME_SYNC) == STATE_SUBFRAME_SYNC) {
+            builder.append("SubframeSync|");
+        }
+        if ((mState & STATE_TOW_DECODED) == STATE_TOW_DECODED) {
+            builder.append("TowDecoded|");
+        }
+        if ((mState & STATE_MSEC_AMBIGUOUS) == STATE_MSEC_AMBIGUOUS) {
+            builder.append("MsecAmbiguous");
+        }
+        int remainingStates = mState & ~STATE_ALL;
+        if (remainingStates > 0) {
+            builder.append("Other(");
+            builder.append(Integer.toBinaryString(remainingStates));
+            builder.append(")|");
+        }
+        builder.deleteCharAt(builder.length() - 1);
+        return builder.toString();
+    }
+
+    /**
+     * Gets the received GPS Time-of-Week at the measurement time, in nanoseconds.
+     * The value is relative to the beginning of the current GPS week.
+     *
+     * Given {@link #getState()} of the GPS receiver, the range of this field can be:
+     *      Searching           : [ 0           ]   : {@link #STATE_UNKNOWN} is set
+     *      Ranging code lock   : [ 0    1 ms   ]   : {@link #STATE_CODE_LOCK} is set
+     *      Bit sync            : [ 0   20 ms   ]   : {@link #STATE_BIT_SYNC} is set
+     *      Subframe sync       : [ 0    6 ms   ]   : {@link #STATE_SUBFRAME_SYNC} is set
+     *      TOW decoded         : [ 0    1 week ]   : {@link #STATE_TOW_DECODED} is set
+     */
+    public long getReceivedGpsTowInNs() {
+        return mReceivedGpsTowInNs;
+    }
+
+    /**
+     * Sets the received GPS time-of-week in nanoseconds.
+     */
+    public void setReceivedGpsTowInNs(long value) {
+        mReceivedGpsTowInNs = value;
+    }
+
+    /**
+     * Gets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds.
+     */
+    public long getReceivedGpsTowUncertaintyInNs() {
+        return mReceivedGpsTowUncertaintyInNs;
+    }
+
+    /**
+     * Sets the received GPS time-of-week's uncertainty (1-Sigma) in nanoseconds.
+     */
+    public void setReceivedGpsTowUncertaintyInNs(long value) {
+        mReceivedGpsTowUncertaintyInNs = value;
+    }
+
+    /**
+     * 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.
+     */
+    public double getCn0InDbHz() {
+        return mCn0InDbHz;
+    }
+
+    /**
+     * Sets the carrier-to-noise density in dB-Hz.
+     */
+    public void setCn0InDbHz(double value) {
+        mCn0InDbHz = value;
+    }
+
+    /**
+     * Gets the Pseudorange rate at the timestamp in m/s.
+     * The reported value includes {@link #getPseudorangeRateUncertaintyInMetersPerSec()}.
+     *
+     * The correction of a given Pseudorange Rate value includes corrections from receiver and
+     * satellite clock frequency errors.
+     * {@link #isPseudorangeRateCorrected()} identifies the type of value reported.
+     *
+     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
+     * The sign of the 'uncorrected' Pseudorange Rate and its relation to the sign of
+     * {@link #getDopplerShiftInHz()} is given by the equation:
+     *      pseudorange rate = -k * doppler shift   (where k is a constant)
+     */
+    public double getPseudorangeRateInMetersPerSec() {
+        return mPseudorangeRateInMetersPerSec;
+    }
+
+    /**
+     * Sets the pseudorange rate at the timestamp in m/s.
+     */
+    public void setPseudorangeRateInMetersPerSec(double value) {
+        mPseudorangeRateInMetersPerSec = value;
+    }
+
+    /**
+     * See {@link #getPseudorangeRateInMetersPerSec()} for more details.
+     *
+     * @return {@code true} if {@link #getPseudorangeRateInMetersPerSec()} contains a corrected
+     *         value, {@code false} if it contains an uncorrected value.
+     */
+    public boolean isPseudorangeRateCorrected() {
+        return !isFlagSet(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE);
+    }
+
+    /**
+     * Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
+     * The uncertainty is represented as an absolute (single sided) value.
+     */
+    public double getPseudorangeRateUncertaintyInMetersPerSec() {
+        return mPseudorangeRateUncertaintyInMetersPerSec;
+    }
+
+    /**
+     * Sets the pseudorange's rate uncertainty (1-Sigma) in m/s.
+     */
+    public void setPseudorangeRateUncertaintyInMetersPerSec(double value) {
+        mPseudorangeRateUncertaintyInMetersPerSec = value;
+    }
+
+    /**
+     * Gets 'Accumulated Delta Range' state.
+     * It indicates whether {@link #getAccumulatedDeltaRangeInMeters()} is reset or there is a
+     * cycle slip (indicating 'loss of lock').
+     */
+    public short getAccumulatedDeltaRangeState() {
+        return mAccumulatedDeltaRangeState;
+    }
+
+    /**
+     * Sets the 'Accumulated Delta Range' state.
+     */
+    public void setAccumulatedDeltaRangeState(short value) {
+        mAccumulatedDeltaRangeState = value;
+    }
+
+    /**
+     * Gets a string representation of the 'Accumulated Delta Range state'.
+     * For internal and logging use only.
+     */
+    private String getAccumulatedDeltaRangeStateString() {
+        if (mAccumulatedDeltaRangeState == ADR_STATE_UNKNOWN) {
+            return "Unknown";
+        }
+        StringBuilder builder = new StringBuilder();
+        if ((mAccumulatedDeltaRangeState & ADR_STATE_VALID) == ADR_STATE_VALID) {
+            builder.append("Valid|");
+        }
+        if ((mAccumulatedDeltaRangeState & ADR_STATE_RESET) == ADR_STATE_RESET) {
+            builder.append("Reset|");
+        }
+        if ((mAccumulatedDeltaRangeState & ADR_STATE_CYCLE_SLIP) == ADR_STATE_CYCLE_SLIP) {
+            builder.append("CycleSlip|");
+        }
+        int remainingStates = mAccumulatedDeltaRangeState & ~ADR_ALL;
+        if (remainingStates > 0) {
+            builder.append("Other(");
+            builder.append(Integer.toBinaryString(remainingStates));
+            builder.append(")|");
+        }
+        builder.deleteCharAt(builder.length() - 1);
+        return builder.toString();
+    }
+
+    /**
+     * Gets the accumulated delta range since the last channel reset, in meters.
+     * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyInMeters()}.
+     *
+     * The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+     *
+     * A positive value indicates that the SV is moving away from the receiver.
+     * The sign of {@link #getAccumulatedDeltaRangeInMeters()} and its relation to the sign of
+     * {@link #getCarrierPhase()} is given by the equation:
+     *          accumulated delta range = -k * carrier phase    (where k is a constant)
+     */
+    public double getAccumulatedDeltaRangeInMeters() {
+        return mAccumulatedDeltaRangeInMeters;
+    }
+
+    /**
+     * Sets the accumulated delta range in meters.
+     */
+    public void setAccumulatedDeltaRangeInMeters(double value) {
+        mAccumulatedDeltaRangeInMeters = value;
+    }
+
+    /**
+     * 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()}.
+     */
+    public double getAccumulatedDeltaRangeUncertaintyInMeters() {
+        return mAccumulatedDeltaRangeUncertaintyInMeters;
+    }
+
+    /**
+     * Sets the accumulated delta range's uncertainty (1-sigma) in meters.
+     *
+     * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+     */
+    public void setAccumulatedDeltaRangeUncertaintyInMeters(double value) {
+        mAccumulatedDeltaRangeUncertaintyInMeters = value;
+    }
+
+    /**
+     * Returns true if {@link #getPseudorangeInMeters()} is available, false otherwise.
+     */
+    public boolean hasPseudorangeInMeters() {
+        return isFlagSet(HAS_PSEUDORANGE);
+    }
+
+    /**
+     * Gets the best derived pseudorange by the chipset, in meters.
+     * The reported pseudorange includes {@link #getPseudorangeUncertaintyInMeters()}.
+     *
+     * The value is only available if {@link #hasPseudorangeInMeters()} is true.
+     */
+    public double getPseudorangeInMeters() {
+        return mPseudorangeInMeters;
+    }
+
+    /**
+     * Sets the Pseudo-range in meters.
+     */
+    public void setPseudorangeInMeters(double value) {
+        setFlag(HAS_PSEUDORANGE);
+        mPseudorangeInMeters = value;
+    }
+
+    /**
+     * Resets the Pseudo-range in meters.
+     */
+    public void resetPseudorangeInMeters() {
+        resetFlag(HAS_PSEUDORANGE);
+        mPseudorangeInMeters = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getPseudorangeUncertaintyInMeters()} is available, false otherwise.
+     */
+    public boolean hasPseudorangeUncertaintyInMeters() {
+        return isFlagSet(HAS_PSEUDORANGE_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the pseudorange's uncertainty (1-Sigma) in meters.
+     * The value contains the 'pseudorange' and 'clock' uncertainty in it.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * The value is only available if {@link #hasPseudorangeUncertaintyInMeters()} is true.
+     */
+    public double getPseudorangeUncertaintyInMeters() {
+        return mPseudorangeUncertaintyInMeters;
+    }
+
+    /**
+     * Sets the pseudo-range's uncertainty (1-Sigma) in meters.
+     */
+    public void setPseudorangeUncertaintyInMeters(double value) {
+        setFlag(HAS_PSEUDORANGE_UNCERTAINTY);
+        mPseudorangeUncertaintyInMeters = value;
+    }
+
+    /**
+     * Resets the pseudo-range's uncertainty (1-Sigma) in meters.
+     */
+    public void resetPseudorangeUncertaintyInMeters() {
+        resetFlag(HAS_PSEUDORANGE_UNCERTAINTY);
+        mPseudorangeUncertaintyInMeters = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getCodePhaseInChips()} is available, false otherwise.
+     */
+    public boolean hasCodePhaseInChips() {
+        return isFlagSet(HAS_CODE_PHASE);
+    }
+
+    /**
+     * Gets the fraction of the current C/A code cycle.
+     * Range: [0, 1023]
+     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+     * The reported code-phase includes {@link #getCodePhaseUncertaintyInChips()}.
+     *
+     * The value is only available if {@link #hasCodePhaseInChips()} is true.
+     */
+    public double getCodePhaseInChips() {
+        return mCodePhaseInChips;
+    }
+
+    /**
+     * Sets the Code-phase in chips.
+     */
+    public void setCodePhaseInChips(double value) {
+        setFlag(HAS_CODE_PHASE);
+        mCodePhaseInChips = value;
+    }
+
+    /**
+     * Resets the Code-phase in chips.
+     */
+    public void resetCodePhaseInChips() {
+        resetFlag(HAS_CODE_PHASE);
+        mCodePhaseInChips = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getCodePhaseUncertaintyInChips()} is available, false otherwise.
+     */
+    public boolean hasCodePhaseUncertaintyInChips() {
+        return isFlagSet(HAS_CODE_PHASE_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the code-phase's uncertainty (1-Sigma) as a fraction of chips.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * The value is only available if {@link #hasCodePhaseUncertaintyInChips()} is true.
+     */
+    public double getCodePhaseUncertaintyInChips() {
+        return mCodePhaseUncertaintyInChips;
+    }
+
+    /**
+     * Sets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
+     */
+    public void setCodePhaseUncertaintyInChips(double value) {
+        setFlag(HAS_CODE_PHASE_UNCERTAINTY);
+        mCodePhaseUncertaintyInChips = value;
+    }
+
+    /**
+     * Resets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
+     */
+    public void resetCodePhaseUncertaintyInChips() {
+        resetFlag(HAS_CODE_PHASE_UNCERTAINTY);
+        mCodePhaseUncertaintyInChips = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getCarrierFrequencyInHz()} is available, false otherwise.
+     */
+    public boolean hasCarrierFrequencyInHz() {
+        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.
+     *
+     * The value is only available if {@link #hasCarrierFrequencyInHz()} is true.
+     */
+    public float getCarrierFrequencyInHz() {
+        return mCarrierFrequencyInHz;
+    }
+
+    /**
+     * Sets the Carrier frequency (L1 or L2) in Hz.
+     */
+    public void setCarrierFrequencyInHz(float carrierFrequencyInHz) {
+        setFlag(HAS_CARRIER_FREQUENCY);
+        mCarrierFrequencyInHz = carrierFrequencyInHz;
+    }
+
+    /**
+     * Resets the Carrier frequency (L1 or L2) in Hz.
+     */
+    public void resetCarrierFrequencyInHz() {
+        resetFlag(HAS_CARRIER_FREQUENCY);
+        mCarrierFrequencyInHz = Float.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getCarrierCycles()} is available, false otherwise.
+     */
+    public boolean hasCarrierCycles() {
+        return isFlagSet(HAS_CARRIER_CYCLES);
+    }
+
+    /**
+     * The number of full carrier cycles between the satellite and the receiver.
+     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+     *
+     * The value is only available if {@link #hasCarrierCycles()} is true.
+     */
+    public long getCarrierCycles() {
+        return mCarrierCycles;
+    }
+
+    /**
+     * Sets the number of full carrier cycles between the satellite and the receiver.
+     */
+    public void setCarrierCycles(long value) {
+        setFlag(HAS_CARRIER_CYCLES);
+        mCarrierCycles = value;
+    }
+
+    /**
+     * Resets the number of full carrier cycles between the satellite and the receiver.
+     */
+    public void resetCarrierCycles() {
+        resetFlag(HAS_CARRIER_CYCLES);
+        mCarrierCycles = Long.MIN_VALUE;
+    }
+
+    /**
+     * Returns true if {@link #getCarrierPhase()} is available, false otherwise.
+     */
+    public boolean hasCarrierPhase() {
+        return isFlagSet(HAS_CARRIER_PHASE);
+    }
+
+    /**
+     * 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 #getCarrierFrequencyInHz()}.
+     * The reported carrier-phase includes {@link #getCarrierPhaseUncertainty()}.
+     *
+     * The value is only available if {@link #hasCarrierPhase()} is true.
+     */
+    public double getCarrierPhase() {
+        return mCarrierPhase;
+    }
+
+    /**
+     * Sets the RF phase detected by the receiver.
+     */
+    public void setCarrierPhase(double value) {
+        setFlag(HAS_CARRIER_PHASE);
+        mCarrierPhase = value;
+    }
+
+    /**
+     * Resets the RF phase detected by the receiver.
+     */
+    public void resetCarrierPhase() {
+        resetFlag(HAS_CARRIER_PHASE);
+        mCarrierPhase = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getCarrierPhaseUncertainty()} is available, false otherwise.
+     */
+    public boolean hasCarrierPhaseUncertainty() {
+        return isFlagSet(HAS_CARRIER_PHASE_UNCERTAINTY);
+    }
+
+    /**
+     * 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.
+     */
+    public double getCarrierPhaseUncertainty() {
+        return mCarrierPhaseUncertainty;
+    }
+
+    /**
+     * Sets the Carrier-phase's uncertainty (1-Sigma) in cycles.
+     */
+    public void setCarrierPhaseUncertainty(double value) {
+        setFlag(HAS_CARRIER_PHASE_UNCERTAINTY);
+        mCarrierPhaseUncertainty = value;
+    }
+
+    /**
+     * Resets the Carrier-phase's uncertainty (1-Sigma) in cycles.
+     */
+    public void resetCarrierPhaseUncertainty() {
+        resetFlag(HAS_CARRIER_PHASE_UNCERTAINTY);
+        mCarrierPhaseUncertainty = Double.NaN;
+    }
+
+    /**
+     * Gets a value indicating the 'loss of lock' state of the event.
+     */
+    @LossOfLockStatus
+    public byte getLossOfLock() {
+        return mLossOfLock;
+    }
+
+    /**
+     * Sets the 'loss of lock' status.
+     */
+    public void setLossOfLock(@LossOfLockStatus byte value) {
+        mLossOfLock = value;
+    }
+
+    /**
+     * Gets a string representation of the 'loss of lock'.
+     * For internal and logging use only.
+     */
+    private String getLossOfLockString() {
+        switch (mLossOfLock) {
+            case LOSS_OF_LOCK_UNKNOWN:
+                return "Unknown";
+            case LOSS_OF_LOCK_OK:
+                return "Ok";
+            case LOSS_OF_LOCK_CYCLE_SLIP:
+                return "CycleSlip";
+            default:
+                return "<Invalid:" + mLossOfLock + ">";
+        }
+    }
+
+    /**
+     * Returns true if {@link #getBitNumber()} is available, false otherwise.
+     */
+    public boolean hasBitNumber() {
+        return isFlagSet(HAS_BIT_NUMBER);
+    }
+
+    /**
+     * Gets the number of GPS bits transmitted since Sat-Sun midnight (GPS week).
+     *
+     * The value is only available if {@link #hasBitNumber()} is true.
+     */
+    public int getBitNumber() {
+        return mBitNumber;
+    }
+
+    /**
+     * Sets the bit number within the broadcast frame.
+     */
+    public void setBitNumber(int bitNumber) {
+        setFlag(HAS_BIT_NUMBER);
+        mBitNumber = bitNumber;
+    }
+
+    /**
+     * Resets the bit number within the broadcast frame.
+     */
+    public void resetBitNumber() {
+        resetFlag(HAS_BIT_NUMBER);
+        mBitNumber = Integer.MIN_VALUE;
+    }
+
+    /**
+     * Returns true if {@link #getTimeFromLastBitInMs()} is available, false otherwise.
+     */
+    public boolean hasTimeFromLastBitInMs() {
+        return isFlagSet(HAS_TIME_FROM_LAST_BIT);
+    }
+
+    /**
+     * Gets the elapsed time since the last received bit in milliseconds.
+     * Range: [0, 20].
+     *
+     * The value is only available if {@link #hasTimeFromLastBitInMs()} is true.
+     */
+    public short getTimeFromLastBitInMs() {
+        return mTimeFromLastBitInMs;
+    }
+
+    /**
+     * Sets the elapsed time since the last received bit in milliseconds.
+     */
+    public void setTimeFromLastBitInMs(short value) {
+        setFlag(HAS_TIME_FROM_LAST_BIT);
+        mTimeFromLastBitInMs = value;
+    }
+
+    /**
+     * Resets the elapsed time since the last received bit in milliseconds.
+     */
+    public void resetTimeFromLastBitInMs() {
+        resetFlag(HAS_TIME_FROM_LAST_BIT);
+        mTimeFromLastBitInMs = Short.MIN_VALUE;
+    }
+
+    /**
+     * Returns true if {@link #getDopplerShiftInHz()} is available, false otherwise.
+     */
+    public boolean hasDopplerShiftInHz() {
+        return isFlagSet(HAS_DOPPLER_SHIFT);
+    }
+
+    /**
+     * Gets the Doppler Shift in Hz.
+     * A positive value indicates that the SV is moving toward the receiver.
+     *
+     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+     * The reported doppler shift includes {@link #getDopplerShiftUncertaintyInHz()}.
+     *
+     * The value is only available if {@link #hasDopplerShiftInHz()} is true.
+     */
+    public double getDopplerShiftInHz() {
+        return mDopplerShiftInHz;
+    }
+
+    /**
+     * Sets the Doppler shift in Hz.
+     */
+    public void setDopplerShiftInHz(double value) {
+        setFlag(HAS_DOPPLER_SHIFT);
+        mDopplerShiftInHz = value;
+    }
+
+    /**
+     * Resets the Doppler shift in Hz.
+     */
+    public void resetDopplerShiftInHz() {
+        resetFlag(HAS_DOPPLER_SHIFT);
+        mDopplerShiftInHz = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getDopplerShiftUncertaintyInHz()} is available, false otherwise.
+     */
+    public boolean hasDopplerShiftUncertaintyInHz() {
+        return isFlagSet(HAS_DOPPLER_SHIFT_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the Doppler's Shift uncertainty (1-Sigma) in Hz.
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * The value is only available if {@link #hasDopplerShiftUncertaintyInHz()} is true.
+     */
+    public double getDopplerShiftUncertaintyInHz() {
+        return mDopplerShiftUncertaintyInHz;
+    }
+
+    /**
+     * Sets the Doppler's shift uncertainty (1-Sigma) in Hz.
+     */
+    public void setDopplerShiftUncertaintyInHz(double value) {
+        setFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
+        mDopplerShiftUncertaintyInHz = value;
+    }
+
+    /**
+     * Resets the Doppler's shift uncertainty (1-Sigma) in Hz.
+     */
+    public void resetDopplerShiftUncertaintyInHz() {
+        resetFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
+        mDopplerShiftUncertaintyInHz = Double.NaN;
+    }
+
+    /**
+     * Gets a value indicating the 'multipath' state of the event.
+     */
+    @MultipathIndicator
+    public byte getMultipathIndicator() {
+        return mMultipathIndicator;
+    }
+
+    /**
+     * Sets the 'multi-path' indicator.
+     */
+    public void setMultipathIndicator(@MultipathIndicator byte value) {
+        mMultipathIndicator = value;
+    }
+
+    /**
+     * Gets a string representation of the 'multi-path indicator'.
+     * For internal and logging use only.
+     */
+    private String getMultipathIndicatorString() {
+        switch(mMultipathIndicator) {
+            case MULTIPATH_INDICATOR_UNKNOWN:
+                return "Unknown";
+            case MULTIPATH_INDICATOR_DETECTED:
+                return "Detected";
+            case MULTIPATH_INDICATOR_NOT_USED:
+                return "NotUsed";
+            default:
+                return "<Invalid:" + mMultipathIndicator + ">";
+        }
+    }
+
+    /**
+     * Returns true if {@link #getSnrInDb()} is available, false otherwise.
+     */
+    public boolean hasSnrInDb() {
+        return isFlagSet(HAS_SNR);
+    }
+
+    /**
+     * Gets the Signal-to-Noise ratio (SNR) in dB.
+     *
+     * The value is only available if {@link #hasSnrInDb()} is true.
+     */
+    public double getSnrInDb() {
+        return mSnrInDb;
+    }
+
+    /**
+     * Sets the Signal-to-noise ratio (SNR) in dB.
+     */
+    public void setSnrInDb(double snrInDb) {
+        setFlag(HAS_SNR);
+        mSnrInDb = snrInDb;
+    }
+
+    /**
+     * Resets the Signal-to-noise ratio (SNR) in dB.
+     */
+    public void resetSnrInDb() {
+        resetFlag(HAS_SNR);
+        mSnrInDb = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getElevationInDeg()} is available, false otherwise.
+     */
+    public boolean hasElevationInDeg() {
+        return isFlagSet(HAS_ELEVATION);
+    }
+
+    /**
+     * Gets the Elevation in degrees.
+     * Range: [-90, 90]
+     * The reported elevation includes {@link #getElevationUncertaintyInDeg()}.
+     *
+     * The value is only available if {@link #hasElevationInDeg()} is true.
+     */
+    public double getElevationInDeg() {
+        return mElevationInDeg;
+    }
+
+    /**
+     * Sets the Elevation in degrees.
+     */
+    public void setElevationInDeg(double elevationInDeg) {
+        setFlag(HAS_ELEVATION);
+        mElevationInDeg = elevationInDeg;
+    }
+
+    /**
+     * Resets the Elevation in degrees.
+     */
+    public void resetElevationInDeg() {
+        resetFlag(HAS_ELEVATION);
+        mElevationInDeg = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getElevationUncertaintyInDeg()} is available, false otherwise.
+     */
+    public boolean hasElevationUncertaintyInDeg() {
+        return isFlagSet(HAS_ELEVATION_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the elevation's uncertainty (1-Sigma) in degrees.
+     * Range: [0, 90]
+     *
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * The value is only available if {@link #hasElevationUncertaintyInDeg()} is true.
+     */
+    public double getElevationUncertaintyInDeg() {
+        return mElevationUncertaintyInDeg;
+    }
+
+    /**
+     * Sets the elevation's uncertainty (1-Sigma) in degrees.
+     */
+    public void setElevationUncertaintyInDeg(double value) {
+        setFlag(HAS_ELEVATION_UNCERTAINTY);
+        mElevationUncertaintyInDeg = value;
+    }
+
+    /**
+     * Resets the elevation's uncertainty (1-Sigma) in degrees.
+     */
+    public void resetElevationUncertaintyInDeg() {
+        resetFlag(HAS_ELEVATION_UNCERTAINTY);
+        mElevationUncertaintyInDeg = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getAzimuthInDeg()} is available, false otherwise.
+     */
+    public boolean hasAzimuthInDeg() {
+        return isFlagSet(HAS_AZIMUTH);
+    }
+
+    /**
+     * Gets the azimuth in degrees.
+     * Range: [0, 360).
+     *
+     * The reported azimuth includes {@link #getAzimuthUncertaintyInDeg()}.
+     *
+     * The value is only available if {@link #hasAzimuthInDeg()} is true.
+     */
+    public double getAzimuthInDeg() {
+        return mAzimuthInDeg;
+    }
+
+    /**
+     * Sets the Azimuth in degrees.
+     */
+    public void setAzimuthInDeg(double value) {
+        setFlag(HAS_AZIMUTH);
+        mAzimuthInDeg = value;
+    }
+
+    /**
+     * Resets the Azimuth in degrees.
+     */
+    public void resetAzimuthInDeg() {
+        resetFlag(HAS_AZIMUTH);
+        mAzimuthInDeg = Double.NaN;
+    }
+
+    /**
+     * Returns true if {@link #getAzimuthUncertaintyInDeg()} is available, false otherwise.
+     */
+    public boolean hasAzimuthUncertaintyInDeg() {
+        return isFlagSet(HAS_AZIMUTH_UNCERTAINTY);
+    }
+
+    /**
+     * Gets the azimuth's uncertainty (1-Sigma) in degrees.
+     * Range: [0, 180].
+     *
+     * The uncertainty is represented as an absolute (single sided) value.
+     *
+     * The value is only available if {@link #hasAzimuthUncertaintyInDeg()} is true.
+     */
+    public double getAzimuthUncertaintyInDeg() {
+        return mAzimuthUncertaintyInDeg;
+    }
+
+    /**
+     * Sets the Azimuth's uncertainty (1-Sigma) in degrees.
+     */
+    public void setAzimuthUncertaintyInDeg(double value) {
+        setFlag(HAS_AZIMUTH_UNCERTAINTY);
+        mAzimuthUncertaintyInDeg = value;
+    }
+
+    /**
+     * Resets the Azimuth's uncertainty (1-Sigma) in degrees.
+     */
+    public void resetAzimuthUncertaintyInDeg() {
+        resetFlag(HAS_AZIMUTH_UNCERTAINTY);
+        mAzimuthUncertaintyInDeg = Double.NaN;
+    }
+
+    /**
+     * Gets a flag indicating whether the GPS represented by the measurement was used for computing
+     * the most recent fix.
+     *
+     * @return A non-null value if the data is available, null otherwise.
+     */
+    public boolean isUsedInFix() {
+        return mUsedInFix;
+    }
+
+    /**
+     * Sets the Used-in-Fix flag.
+     */
+    public void setUsedInFix(boolean value) {
+        mUsedInFix = value;
+    }
+
+    /**
+     * Gets pseudorange rate (based on carrier phase changes) at the timestamp in m/s.
+     */
+    public double getPseudorangeRateCarrierInMetersPerSec() {
+        return mPseudorangeRateCarrierInMetersPerSec;
+    }
+
+    /**
+     * Sets pseudorange rate (based on carrier phase changes) at the timestamp in m/s.
+     */
+    public void setPseudorangeRateCarrierInMetersPerSec(double value) {
+        mPseudorangeRateCarrierInMetersPerSec = value;
+    }
+
+    /**
+     * Gets 1-Sigma uncertainty of the pseudorange rate carrier.
+     */
+    public double getPseudorangeRateCarrierUncertaintyInMetersPerSec() {
+        return mPseudorangeRateCarrierUncertaintyInMetersPerSec;
+    }
+
+    /**
+     * Sets 1-Sigma uncertainty of the pseudorange rate carrier.
+     */
+    public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double value) {
+        mPseudorangeRateCarrierUncertaintyInMetersPerSec = value;
+    }
+
+    public static final Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
+        @Override
+        public GnssMeasurement createFromParcel(Parcel parcel) {
+            GnssMeasurement gnssMeasurement = new GnssMeasurement();
+
+            gnssMeasurement.mFlags = parcel.readInt();
+            gnssMeasurement.mPrn = parcel.readByte();
+            gnssMeasurement.mTimeOffsetInNs = parcel.readDouble();
+            gnssMeasurement.mState = (short) parcel.readInt();
+            gnssMeasurement.mReceivedGpsTowInNs = parcel.readLong();
+            gnssMeasurement.mReceivedGpsTowUncertaintyInNs = parcel.readLong();
+            gnssMeasurement.mCn0InDbHz = parcel.readDouble();
+            gnssMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble();
+            gnssMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble();
+            gnssMeasurement.mAccumulatedDeltaRangeState = (short) parcel.readInt();
+            gnssMeasurement.mAccumulatedDeltaRangeInMeters = parcel.readDouble();
+            gnssMeasurement.mAccumulatedDeltaRangeUncertaintyInMeters = parcel.readDouble();
+            gnssMeasurement.mPseudorangeInMeters = parcel.readDouble();
+            gnssMeasurement.mPseudorangeUncertaintyInMeters = parcel.readDouble();
+            gnssMeasurement.mCodePhaseInChips = parcel.readDouble();
+            gnssMeasurement.mCodePhaseUncertaintyInChips = parcel.readDouble();
+            gnssMeasurement.mCarrierFrequencyInHz = parcel.readFloat();
+            gnssMeasurement.mCarrierCycles = parcel.readLong();
+            gnssMeasurement.mCarrierPhase = parcel.readDouble();
+            gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
+            gnssMeasurement.mLossOfLock = parcel.readByte();
+            gnssMeasurement.mBitNumber = parcel.readInt();
+            gnssMeasurement.mTimeFromLastBitInMs = (short) parcel.readInt();
+            gnssMeasurement.mDopplerShiftInHz = parcel.readDouble();
+            gnssMeasurement.mDopplerShiftUncertaintyInHz = parcel.readDouble();
+            gnssMeasurement.mMultipathIndicator = parcel.readByte();
+            gnssMeasurement.mSnrInDb = parcel.readDouble();
+            gnssMeasurement.mElevationInDeg = parcel.readDouble();
+            gnssMeasurement.mElevationUncertaintyInDeg = parcel.readDouble();
+            gnssMeasurement.mAzimuthInDeg = parcel.readDouble();
+            gnssMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble();
+            gnssMeasurement.mUsedInFix = parcel.readInt() != 0;
+            gnssMeasurement.mPseudorangeRateCarrierInMetersPerSec = parcel.readDouble();
+            gnssMeasurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec = parcel.readDouble();
+
+            return gnssMeasurement;
+        }
+
+        @Override
+        public GnssMeasurement[] newArray(int i) {
+            return new GnssMeasurement[i];
+        }
+    };
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mFlags);
+        parcel.writeByte(mPrn);
+        parcel.writeDouble(mTimeOffsetInNs);
+        parcel.writeInt(mState);
+        parcel.writeLong(mReceivedGpsTowInNs);
+        parcel.writeLong(mReceivedGpsTowUncertaintyInNs);
+        parcel.writeDouble(mCn0InDbHz);
+        parcel.writeDouble(mPseudorangeRateInMetersPerSec);
+        parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec);
+        parcel.writeInt(mAccumulatedDeltaRangeState);
+        parcel.writeDouble(mAccumulatedDeltaRangeInMeters);
+        parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyInMeters);
+        parcel.writeDouble(mPseudorangeInMeters);
+        parcel.writeDouble(mPseudorangeUncertaintyInMeters);
+        parcel.writeDouble(mCodePhaseInChips);
+        parcel.writeDouble(mCodePhaseUncertaintyInChips);
+        parcel.writeFloat(mCarrierFrequencyInHz);
+        parcel.writeLong(mCarrierCycles);
+        parcel.writeDouble(mCarrierPhase);
+        parcel.writeDouble(mCarrierPhaseUncertainty);
+        parcel.writeByte(mLossOfLock);
+        parcel.writeInt(mBitNumber);
+        parcel.writeInt(mTimeFromLastBitInMs);
+        parcel.writeDouble(mDopplerShiftInHz);
+        parcel.writeDouble(mDopplerShiftUncertaintyInHz);
+        parcel.writeByte(mMultipathIndicator);
+        parcel.writeDouble(mSnrInDb);
+        parcel.writeDouble(mElevationInDeg);
+        parcel.writeDouble(mElevationUncertaintyInDeg);
+        parcel.writeDouble(mAzimuthInDeg);
+        parcel.writeDouble(mAzimuthUncertaintyInDeg);
+        parcel.writeInt(mUsedInFix ? 1 : 0);
+        parcel.writeDouble(mPseudorangeRateCarrierInMetersPerSec);
+        parcel.writeDouble(mPseudorangeRateCarrierUncertaintyInMetersPerSec);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        final String format = "   %-29s = %s\n";
+        final String formatWithUncertainty = "   %-29s = %-25s   %-40s = %s\n";
+        StringBuilder builder = new StringBuilder("GnssMeasurement:\n");
+
+        builder.append(String.format(format, "Prn", mPrn));
+
+        builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs));
+
+        builder.append(String.format(format, "State", getStateString()));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "ReceivedGpsTowInNs",
+                mReceivedGpsTowInNs,
+                "ReceivedGpsTowUncertaintyInNs",
+                mReceivedGpsTowUncertaintyInNs));
+
+        builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "PseudorangeRateInMetersPerSec",
+                mPseudorangeRateInMetersPerSec,
+                "PseudorangeRateUncertaintyInMetersPerSec",
+                mPseudorangeRateUncertaintyInMetersPerSec));
+        builder.append(String.format(
+                format,
+                "PseudorangeRateIsCorrected",
+                isPseudorangeRateCorrected()));
+
+        builder.append(String.format(
+                format,
+                "AccumulatedDeltaRangeState",
+                getAccumulatedDeltaRangeStateString()));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "AccumulatedDeltaRangeInMeters",
+                mAccumulatedDeltaRangeInMeters,
+                "AccumulatedDeltaRangeUncertaintyInMeters",
+                mAccumulatedDeltaRangeUncertaintyInMeters));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "PseudorangeInMeters",
+                hasPseudorangeInMeters() ? mPseudorangeInMeters : null,
+                "PseudorangeUncertaintyInMeters",
+                hasPseudorangeUncertaintyInMeters() ? mPseudorangeUncertaintyInMeters : null));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "CodePhaseInChips",
+                hasCodePhaseInChips() ? mCodePhaseInChips : null,
+                "CodePhaseUncertaintyInChips",
+                hasCodePhaseUncertaintyInChips() ? mCodePhaseUncertaintyInChips : null));
+
+        builder.append(String.format(
+                format,
+                "CarrierFrequencyInHz",
+                hasCarrierFrequencyInHz() ? mCarrierFrequencyInHz : null));
+
+        builder.append(String.format(
+                format,
+                "CarrierCycles",
+                hasCarrierCycles() ? mCarrierCycles : null));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "CarrierPhase",
+                hasCarrierPhase() ? mCarrierPhase : null,
+                "CarrierPhaseUncertainty",
+                hasCarrierPhaseUncertainty() ? mCarrierPhaseUncertainty : null));
+
+        builder.append(String.format(format, "LossOfLock", getLossOfLockString()));
+
+        builder.append(String.format(
+                format,
+                "BitNumber",
+                hasBitNumber() ? mBitNumber : null));
+
+        builder.append(String.format(
+                format,
+                "TimeFromLastBitInMs",
+                hasTimeFromLastBitInMs() ? mTimeFromLastBitInMs : null));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "DopplerShiftInHz",
+                hasDopplerShiftInHz() ? mDopplerShiftInHz : null,
+                "DopplerShiftUncertaintyInHz",
+                hasDopplerShiftUncertaintyInHz() ? mDopplerShiftUncertaintyInHz : null));
+
+        builder.append(String.format(format, "MultipathIndicator", getMultipathIndicatorString()));
+
+        builder.append(String.format(
+                format,
+                "SnrInDb",
+                hasSnrInDb() ? mSnrInDb : null));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "ElevationInDeg",
+                hasElevationInDeg() ? mElevationInDeg : null,
+                "ElevationUncertaintyInDeg",
+                hasElevationUncertaintyInDeg() ? mElevationUncertaintyInDeg : null));
+
+        builder.append(String.format(
+                formatWithUncertainty,
+                "AzimuthInDeg",
+                hasAzimuthInDeg() ? mAzimuthInDeg : null,
+                "AzimuthUncertaintyInDeg",
+                hasAzimuthUncertaintyInDeg() ? mAzimuthUncertaintyInDeg : null));
+
+        builder.append(String.format(format, "UsedInFix", mUsedInFix));
+
+        builder.append(String.format(format, "PseudorangeRateCarrierInMetersPerSec",
+                    mPseudorangeRateCarrierInMetersPerSec));
+        builder.append(String.format(format, "PseudorangeRateCarrierUncertaintyInMetersPerSec",
+                    mPseudorangeRateCarrierUncertaintyInMetersPerSec));
+
+        return builder.toString();
+    }
+
+    private void initialize() {
+        mFlags = HAS_NO_FLAGS;
+        setPrn(Byte.MIN_VALUE);
+        setTimeOffsetInNs(Long.MIN_VALUE);
+        setState(STATE_UNKNOWN);
+        setReceivedGpsTowInNs(Long.MIN_VALUE);
+        setReceivedGpsTowUncertaintyInNs(Long.MAX_VALUE);
+        setCn0InDbHz(Double.MIN_VALUE);
+        setPseudorangeRateInMetersPerSec(Double.MIN_VALUE);
+        setPseudorangeRateUncertaintyInMetersPerSec(Double.MIN_VALUE);
+        setAccumulatedDeltaRangeState(ADR_STATE_UNKNOWN);
+        setAccumulatedDeltaRangeInMeters(Double.MIN_VALUE);
+        setAccumulatedDeltaRangeUncertaintyInMeters(Double.MIN_VALUE);
+        resetPseudorangeInMeters();
+        resetPseudorangeUncertaintyInMeters();
+        resetCodePhaseInChips();
+        resetCodePhaseUncertaintyInChips();
+        resetCarrierFrequencyInHz();
+        resetCarrierCycles();
+        resetCarrierPhase();
+        resetCarrierPhaseUncertainty();
+        setLossOfLock(LOSS_OF_LOCK_UNKNOWN);
+        resetBitNumber();
+        resetTimeFromLastBitInMs();
+        resetDopplerShiftInHz();
+        resetDopplerShiftUncertaintyInHz();
+        setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
+        resetSnrInDb();
+        resetElevationInDeg();
+        resetElevationUncertaintyInDeg();
+        resetAzimuthInDeg();
+        resetAzimuthUncertaintyInDeg();
+        setUsedInFix(false);
+        setPseudorangeRateCarrierInMetersPerSec(Double.MIN_VALUE);
+        setPseudorangeRateCarrierUncertaintyInMetersPerSec(Double.MIN_VALUE);
+    }
+
+    private void setFlag(int flag) {
+        mFlags |= flag;
+    }
+
+    private void resetFlag(int flag) {
+        mFlags &= ~flag;
+    }
+
+    private boolean isFlagSet(int flag) {
+        return (mFlags & flag) == flag;
+    }
+}
diff --git a/location/java/android/location/GnssMeasurementCallbackTransport.java b/location/java/android/location/GnssMeasurementCallbackTransport.java
new file mode 100644
index 0000000..21f6306
--- /dev/null
+++ b/location/java/android/location/GnssMeasurementCallbackTransport.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.location;
+
+import android.content.Context;
+import android.os.RemoteException;
+
+/**
+ * A handler class to manage transport callbacks for {@link GnssMeasurementsEvent.Callback}.
+ *
+ * @hide
+ */
+class GnssMeasurementCallbackTransport
+        extends LocalListenerHelper<GnssMeasurementsEvent.Callback> {
+    private final ILocationManager mLocationManager;
+
+    private final IGnssMeasurementsListener mListenerTransport = new ListenerTransport();
+
+    public GnssMeasurementCallbackTransport(Context context, ILocationManager locationManager) {
+        super(context, "GnssMeasurementListenerTransport");
+        mLocationManager = locationManager;
+    }
+
+    @Override
+    protected boolean registerWithServer() throws RemoteException {
+        return mLocationManager.addGnssMeasurementsListener(
+                mListenerTransport,
+                getContext().getPackageName());
+    }
+
+    @Override
+    protected void unregisterFromServer() throws RemoteException {
+        mLocationManager.removeGnssMeasurementsListener(mListenerTransport);
+    }
+
+    private class ListenerTransport extends IGnssMeasurementsListener.Stub {
+        @Override
+        public void onGnssMeasurementsReceived(final GnssMeasurementsEvent event) {
+            ListenerOperation<GnssMeasurementsEvent.Callback> operation =
+                    new ListenerOperation<GnssMeasurementsEvent.Callback>() {
+                @Override
+                public void execute(GnssMeasurementsEvent.Callback callback)
+                        throws RemoteException {
+                    callback.onGnssMeasurementsReceived(event);
+                }
+            };
+            foreach(operation);
+        }
+
+        @Override
+        public void onStatusChanged(final int status) {
+            ListenerOperation<GnssMeasurementsEvent.Callback> operation =
+                    new ListenerOperation<GnssMeasurementsEvent.Callback>() {
+                @Override
+                public void execute(GnssMeasurementsEvent.Callback callback)
+                        throws RemoteException {
+                    callback.onStatusChanged(status);
+                }
+            };
+            foreach(operation);
+        }
+    }
+}
diff --git a/location/java/android/location/GpsNavigationMessageEvent.aidl b/location/java/android/location/GnssMeasurementsEvent.aidl
similarity index 94%
rename from location/java/android/location/GpsNavigationMessageEvent.aidl
rename to location/java/android/location/GnssMeasurementsEvent.aidl
index f84c2f7..5ce594d 100644
--- a/location/java/android/location/GpsNavigationMessageEvent.aidl
+++ b/location/java/android/location/GnssMeasurementsEvent.aidl
@@ -16,4 +16,4 @@
 
 package android.location;
 
-parcelable GpsNavigationMessageEvent;
+parcelable GnssMeasurementsEvent;
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
new file mode 100644
index 0000000..b744a03
--- /dev/null
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.location;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.security.InvalidParameterException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A class implementing a container for data associated with a measurement event.
+ * Events are delivered to registered instances of {@link Callback}.
+ */
+public final class GnssMeasurementsEvent implements Parcelable {
+    /** The status of GPS measurements event. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+    public @interface GnssMeasurementsStatus {}
+
+    /**
+     * The system does not support tracking of GPS Measurements. This status will not change in the
+     * future.
+     */
+    public static final int STATUS_NOT_SUPPORTED = 0;
+
+    /**
+     * GPS Measurements are successfully being tracked, it will receive updates once they are
+     * 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_GPS_LOCATION_DISABLED = 2;
+
+    private final GnssClock mClock;
+    private final Collection<GnssMeasurement> mReadOnlyMeasurements;
+
+    /**
+     * Used for receiving GPS satellite measurements from the GPS engine.
+     * Each measurement contains raw and computed data identifying a satellite.
+     * You can implement this interface and call
+     * {@link LocationManager#registerGnssMeasurementCallback}.
+     */
+    public static abstract class Callback {
+
+        /**
+         * Returns the latest collected GPS Measurements.
+         */
+        public void onGnssMeasurementsReceived(GnssMeasurementsEvent eventArgs) {}
+
+        /**
+         * Returns the latest status of the GPS Measurements sub-system.
+         */
+        public void onStatusChanged(@GnssMeasurementsStatus int status) {}
+    }
+
+    public GnssMeasurementsEvent(GnssClock clock, GnssMeasurement[] measurements) {
+        if (clock == null) {
+            throw new InvalidParameterException("Parameter 'clock' must not be null.");
+        }
+        if (measurements == null || measurements.length == 0) {
+            throw new InvalidParameterException(
+                    "Parameter 'measurements' must not be null or empty.");
+        }
+
+        mClock = clock;
+        Collection<GnssMeasurement> measurementCollection = Arrays.asList(measurements);
+        mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection);
+    }
+
+    @NonNull
+    public GnssClock getClock() {
+        return mClock;
+    }
+
+    /**
+     * Gets a read-only collection of measurements associated with the current event.
+     */
+    @NonNull
+    public Collection<GnssMeasurement> getMeasurements() {
+        return mReadOnlyMeasurements;
+    }
+
+    public static final Creator<GnssMeasurementsEvent> CREATOR =
+            new Creator<GnssMeasurementsEvent>() {
+        @Override
+        public GnssMeasurementsEvent createFromParcel(Parcel in) {
+            ClassLoader classLoader = getClass().getClassLoader();
+
+            GnssClock clock = in.readParcelable(classLoader);
+
+            int measurementsLength = in.readInt();
+            GnssMeasurement[] measurementsArray = new GnssMeasurement[measurementsLength];
+            in.readTypedArray(measurementsArray, GnssMeasurement.CREATOR);
+
+            return new GnssMeasurementsEvent(clock, measurementsArray);
+        }
+
+        @Override
+        public GnssMeasurementsEvent[] newArray(int size) {
+            return new GnssMeasurementsEvent[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeParcelable(mClock, flags);
+
+        int measurementsCount = mReadOnlyMeasurements.size();
+        GnssMeasurement[] measurementsArray =
+                mReadOnlyMeasurements.toArray(new GnssMeasurement[measurementsCount]);
+        parcel.writeInt(measurementsArray.length);
+        parcel.writeTypedArray(measurementsArray, flags);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("[ GnssMeasurementsEvent:\n\n");
+
+        builder.append(mClock.toString());
+        builder.append("\n");
+
+        for (GnssMeasurement measurement : mReadOnlyMeasurements) {
+            builder.append(measurement.toString());
+            builder.append("\n");
+        }
+
+        builder.append("]");
+
+        return builder.toString();
+    }
+}
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
new file mode 100644
index 0000000..0e011d5
--- /dev/null
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.location;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.security.InvalidParameterException;
+
+/**
+ * A class containing a GPS satellite Navigation Message.
+ */
+public final class GnssNavigationMessage implements Parcelable {
+
+    private static final byte[] EMPTY_ARRAY = new byte[0];
+
+    /** The type of the GPS Clock. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({MESSAGE_TYPE_UNKNOWN, MESSAGE_TYPE_L1CA, MESSAGE_TYPE_L2CNAV, MESSAGE_TYPE_L5CNAV,
+            MESSAGE_TYPE_CNAV2})
+    public @interface GnssNavigationMessageType {}
+
+    // The following enumerations must be in sync with the values declared in gps.h
+
+    /**
+     * The type of the navigation message is not available or unknown.
+     */
+    public static final byte MESSAGE_TYPE_UNKNOWN = 0;
+
+    /**
+     * The Navigation Message is of type L1 C/A.
+     */
+    public static final byte MESSAGE_TYPE_L1CA = 1;
+
+    /**
+     * The Navigation Message is of type L1-CNAV.
+     */
+    public static final byte MESSAGE_TYPE_L2CNAV = 2;
+
+    /**
+     * The Navigation Message is of type L5-CNAV.
+     */
+    public static final byte MESSAGE_TYPE_L5CNAV = 3;
+
+    /**
+     * The Navigation Message is of type CNAV-2.
+     */
+    public static final byte MESSAGE_TYPE_CNAV2 = 4;
+
+    /**
+     * The Navigation Message Status is 'unknown'.
+     */
+    public static final short STATUS_UNKNOWN = 0;
+
+    /**
+     * The Navigation Message was received without any parity error in its navigation words.
+     */
+    public static final short STATUS_PARITY_PASSED = (1<<0);
+
+    /**
+     * The Navigation Message was received with words that failed parity check, but the receiver was
+     * able to correct those words.
+     */
+    public static final short STATUS_PARITY_REBUILT = (1<<1);
+
+    // End enumerations in sync with gps.h
+
+    private byte mType;
+    private byte mPrn;
+    private short mMessageId;
+    private short mSubmessageId;
+    private byte[] mData;
+    private short mStatus;
+
+    GnssNavigationMessage() {
+        initialize();
+    }
+
+    /**
+     * Sets all contents to the values stored in the provided object.
+     */
+    public void set(GnssNavigationMessage navigationMessage) {
+        mType = navigationMessage.mType;
+        mPrn = navigationMessage.mPrn;
+        mMessageId = navigationMessage.mMessageId;
+        mSubmessageId = navigationMessage.mSubmessageId;
+        mData = navigationMessage.mData;
+        mStatus = navigationMessage.mStatus;
+    }
+
+    /**
+     * Resets all the contents to its original state.
+     */
+    public void reset() {
+        initialize();
+    }
+
+    /**
+     * Gets the type of the navigation message contained in the object.
+     */
+    @GnssNavigationMessageType
+    public byte getType() {
+        return mType;
+    }
+
+    /**
+     * Sets the type of the navigation message.
+     */
+    public void setType(@GnssNavigationMessageType byte value) {
+        mType = value;
+    }
+
+    /**
+     * Gets a string representation of the 'type'.
+     * For internal and logging use only.
+     */
+    private String getTypeString() {
+        switch (mType) {
+            case MESSAGE_TYPE_UNKNOWN:
+                return "Unknown";
+            case MESSAGE_TYPE_L1CA:
+                return "L1 C/A";
+            case MESSAGE_TYPE_L2CNAV:
+                return "L2-CNAV";
+            case MESSAGE_TYPE_L5CNAV:
+                return "L5-CNAV";
+            case MESSAGE_TYPE_CNAV2:
+                return "CNAV-2";
+            default:
+                return "<Invalid:" + mType + ">";
+        }
+    }
+
+    /**
+     * Gets the Pseudo-random number.
+     * Range: [1, 32].
+     */
+    public byte getPrn() {
+        return mPrn;
+    }
+
+    /**
+     * Sets the Pseud-random number.
+     */
+    public void setPrn(byte value) {
+        mPrn = value;
+    }
+
+    /**
+     * 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.
+     */
+    public short getMessageId() {
+        return mMessageId;
+    }
+
+    /**
+     * Sets the Message Identifier.
+     */
+    public void setMessageId(short value) {
+        mMessageId = value;
+    }
+
+    /**
+     * 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.
+     */
+    public short getSubmessageId() {
+        return mSubmessageId;
+    }
+
+    /**
+     * Sets the Sub-message identifier.
+     */
+    public void setSubmessageId(short value) {
+        mSubmessageId = value;
+    }
+
+    /**
+     * Gets the data associated with the Navigation Message.
+     * The bytes (or words) specified using big endian format (MSB first).
+     */
+    @NonNull
+    public byte[] getData() {
+        return mData;
+    }
+
+    /**
+     * Sets the data associated with the Navigation Message.
+     */
+    public void setData(byte[] value) {
+        if (value == null) {
+            throw new InvalidParameterException("Data must be a non-null array");
+        }
+
+        mData = value;
+    }
+
+    /**
+     * Gets the Status of the navigation message contained in the object.
+     */
+    public short getStatus() {
+        return mStatus;
+    }
+
+    /**
+     * Sets the status of the navigation message.
+     */
+    public void setStatus(short value) {
+        mStatus = value;
+    }
+
+    /**
+     * Gets a string representation of the 'status'.
+     * For internal and logging use only.
+     */
+    private String getStatusString() {
+        switch (mStatus) {
+            case STATUS_UNKNOWN:
+                return "Unknown";
+            case STATUS_PARITY_PASSED:
+                return "ParityPassed";
+            case STATUS_PARITY_REBUILT:
+                return "ParityRebuilt";
+            default:
+                return "<Invalid:" + mStatus + ">";
+        }
+    }
+
+    public static final Creator<GnssNavigationMessage> CREATOR =
+            new Creator<GnssNavigationMessage>() {
+        @Override
+        public GnssNavigationMessage createFromParcel(Parcel parcel) {
+            GnssNavigationMessage navigationMessage = new GnssNavigationMessage();
+
+            navigationMessage.setType(parcel.readByte());
+            navigationMessage.setPrn(parcel.readByte());
+            navigationMessage.setMessageId((short) parcel.readInt());
+            navigationMessage.setSubmessageId((short) parcel.readInt());
+
+            int dataLength = parcel.readInt();
+            byte[] data = new byte[dataLength];
+            parcel.readByteArray(data);
+            navigationMessage.setData(data);
+
+            if (parcel.dataAvail() >= Integer.SIZE) {
+                int status = parcel.readInt();
+                navigationMessage.setStatus((short) status);
+            } else {
+                navigationMessage.setStatus(STATUS_UNKNOWN);
+            }
+
+            return navigationMessage;
+        }
+
+        @Override
+        public GnssNavigationMessage[] newArray(int size) {
+            return new GnssNavigationMessage[size];
+        }
+    };
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeByte(mType);
+        parcel.writeByte(mPrn);
+        parcel.writeInt(mMessageId);
+        parcel.writeInt(mSubmessageId);
+        parcel.writeInt(mData.length);
+        parcel.writeByteArray(mData);
+        parcel.writeInt(mStatus);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        final String format = "   %-15s = %s\n";
+        StringBuilder builder = new StringBuilder("GnssNavigationMessage:\n");
+
+        builder.append(String.format(format, "Type", getTypeString()));
+        builder.append(String.format(format, "Prn", mPrn));
+        builder.append(String.format(format, "Status", getStatusString()));
+        builder.append(String.format(format, "MessageId", mMessageId));
+        builder.append(String.format(format, "SubmessageId", mSubmessageId));
+
+        builder.append(String.format(format, "Data", "{"));
+        String prefix = "        ";
+        for(byte value : mData) {
+            builder.append(prefix);
+            builder.append(value);
+            prefix = ", ";
+        }
+        builder.append(" }");
+
+        return builder.toString();
+    }
+
+    private void initialize() {
+        mType = MESSAGE_TYPE_UNKNOWN;
+        mPrn = 0;
+        mMessageId = -1;
+        mSubmessageId = -1;
+        mData = EMPTY_ARRAY;
+        mStatus = STATUS_UNKNOWN;
+    }
+}
diff --git a/location/java/android/location/GnssNavigationMessageCallbackTransport.java b/location/java/android/location/GnssNavigationMessageCallbackTransport.java
new file mode 100644
index 0000000..4204b99
--- /dev/null
+++ b/location/java/android/location/GnssNavigationMessageCallbackTransport.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.location;
+
+import android.content.Context;
+import android.os.RemoteException;
+
+/**
+ * A handler class to manage transport callback for {@link GnssNavigationMessageEvent.Callback}.
+ *
+ * @hide
+ */
+class GnssNavigationMessageCallbackTransport
+        extends LocalListenerHelper<GnssNavigationMessageEvent.Callback> {
+    private final ILocationManager mLocationManager;
+
+    private final IGnssNavigationMessageListener mListenerTransport = new ListenerTransport();
+
+    public GnssNavigationMessageCallbackTransport(
+            Context context,
+            ILocationManager locationManager) {
+        super(context, "GnssNavigationMessageCallbackTransport");
+        mLocationManager = locationManager;
+    }
+
+    @Override
+    protected boolean registerWithServer() throws RemoteException {
+        return mLocationManager.addGnssNavigationMessageListener(
+                mListenerTransport,
+                getContext().getPackageName());
+    }
+
+    @Override
+    protected void unregisterFromServer() throws RemoteException {
+        mLocationManager.removeGnssNavigationMessageListener(mListenerTransport);
+    }
+
+    private class ListenerTransport extends IGnssNavigationMessageListener.Stub {
+        @Override
+        public void onGnssNavigationMessageReceived(final GnssNavigationMessageEvent event) {
+            ListenerOperation<GnssNavigationMessageEvent.Callback> operation =
+                    new ListenerOperation<GnssNavigationMessageEvent.Callback>() {
+                @Override
+                public void execute(GnssNavigationMessageEvent.Callback callback)
+                        throws RemoteException {
+                    callback.onGnssNavigationMessageReceived(event);
+                }
+            };
+            foreach(operation);
+        }
+
+        @Override
+        public void onStatusChanged(final int status) {
+            ListenerOperation<GnssNavigationMessageEvent.Callback> operation =
+                    new ListenerOperation<GnssNavigationMessageEvent.Callback>() {
+                @Override
+                public void execute(GnssNavigationMessageEvent.Callback callback)
+                        throws RemoteException {
+                    callback.onStatusChanged(status);
+                }
+            };
+            foreach(operation);
+        }
+    }
+}
diff --git a/location/java/android/location/GpsNavigationMessageEvent.aidl b/location/java/android/location/GnssNavigationMessageEvent.aidl
similarity index 94%
copy from location/java/android/location/GpsNavigationMessageEvent.aidl
copy to location/java/android/location/GnssNavigationMessageEvent.aidl
index f84c2f7..e765739 100644
--- a/location/java/android/location/GpsNavigationMessageEvent.aidl
+++ b/location/java/android/location/GnssNavigationMessageEvent.aidl
@@ -16,4 +16,4 @@
 
 package android.location;
 
-parcelable GpsNavigationMessageEvent;
+parcelable GnssNavigationMessageEvent;
diff --git a/location/java/android/location/GnssNavigationMessageEvent.java b/location/java/android/location/GnssNavigationMessageEvent.java
new file mode 100644
index 0000000..19c82e9
--- /dev/null
+++ b/location/java/android/location/GnssNavigationMessageEvent.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.location;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.security.InvalidParameterException;
+
+/**
+ * A class implementing a container for data associated with a navigation message event.
+ * Events are delivered to registered instances of {@link Callback}.
+ */
+public final class GnssNavigationMessageEvent implements Parcelable {
+    /** The status of GPS measurements event. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+    public @interface GnssNavigationMessageStatus {}
+
+    /**
+     * The system does not support tracking of GPS 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.
+     */
+    public static final int STATUS_READY = 1;
+
+    /**
+     * GPS provider or Location is disabled, updated will not be received until they are enabled.
+     */
+    public static final int STATUS_GPS_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
+     * {@link LocationManager#registerGnssNavigationMessageCallback}.
+     */
+    public static abstract class Callback {
+
+        /**
+         * Returns the latest collected GPS Navigation Message.
+         */
+        public void onGnssNavigationMessageReceived(GnssNavigationMessageEvent event) {}
+
+        /**
+         * Returns the latest status of the GPS Navigation Messages sub-system.
+         */
+        public void onStatusChanged(@GnssNavigationMessageStatus int status) {}
+    }
+
+    public GnssNavigationMessageEvent(GnssNavigationMessage message) {
+        if (message == null) {
+            throw new InvalidParameterException("Parameter 'message' must not be null.");
+        }
+        mNavigationMessage = message;
+    }
+
+    @NonNull
+    public GnssNavigationMessage getNavigationMessage() {
+        return mNavigationMessage;
+    }
+
+    public static final Creator<GnssNavigationMessageEvent> CREATOR =
+            new Creator<GnssNavigationMessageEvent>() {
+                @Override
+                public GnssNavigationMessageEvent createFromParcel(Parcel in) {
+                    ClassLoader classLoader = getClass().getClassLoader();
+                    GnssNavigationMessage navigationMessage = in.readParcelable(classLoader);
+                    return new GnssNavigationMessageEvent(navigationMessage);
+                }
+
+                @Override
+                public GnssNavigationMessageEvent[] newArray(int size) {
+                    return new GnssNavigationMessageEvent[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeParcelable(mNavigationMessage, flags);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("[ GnssNavigationMessageEvent:\n\n");
+        builder.append(mNavigationMessage.toString());
+        builder.append("\n]");
+        return builder.toString();
+    }
+}
diff --git a/location/java/android/location/GpsClock.java b/location/java/android/location/GpsClock.java
index 719e56f..4135a1c 100644
--- a/location/java/android/location/GpsClock.java
+++ b/location/java/android/location/GpsClock.java
@@ -16,41 +16,36 @@
 
 package android.location;
 
-import android.annotation.IntDef;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * A class containing a GPS clock timestamp.
  * It represents a measurement of the GPS receiver's clock.
+ *
+ * @hide
  */
-public final class GpsClock implements Parcelable {
+@SystemApi
+public class GpsClock implements Parcelable {
 
     // The following enumerations must be in sync with the values declared in gps.h
 
-    /** The type of the GPS Clock. */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({CLOCK_TYPE_UNKNOWN, CLOCK_TYPE_LOCAL_HW_TIME, CLOCK_TYPE_GPS_TIME})
-    public @interface GpsClockType {}
-
     /**
      * The type of the time stored is not available or it is unknown.
      */
-    public static final byte CLOCK_TYPE_UNKNOWN = 0;
+    public static final byte TYPE_UNKNOWN = 0;
 
     /**
      * The source of the time value reported by this class is the 'Local Hardware Clock'.
      */
-    public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1;
+    public static final byte TYPE_LOCAL_HW_TIME = 1;
 
     /**
      * The source of the time value reported by this class is the 'GPS time' derived from
      * satellites (epoch = Jan 6, 1980).
      */
-    public static final byte CLOCK_TYPE_GPS_TIME = 2;
+    public static final byte TYPE_GPS_TIME = 2;
 
     private static final short HAS_NO_FLAGS = 0;
     private static final short HAS_LEAP_SECOND = (1<<0);
@@ -73,7 +68,6 @@
     private double mBiasUncertaintyInNs;
     private double mDriftInNsPerSec;
     private double mDriftUncertaintyInNsPerSec;
-    private long mTimeOfLastHwClockDiscontinuityInNs;
 
     GpsClock() {
         initialize();
@@ -93,7 +87,6 @@
         mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
         mDriftInNsPerSec = clock.mDriftInNsPerSec;
         mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
-        mTimeOfLastHwClockDiscontinuityInNs = clock.mTimeOfLastHwClockDiscontinuityInNs;
     }
 
     /**
@@ -106,7 +99,6 @@
     /**
      * Gets the type of time reported by {@link #getTimeInNs()}.
      */
-    @GpsClockType
     public byte getType() {
         return mType;
     }
@@ -114,7 +106,7 @@
     /**
      * Sets the type of time reported.
      */
-    public void setType(@GpsClockType byte value) {
+    public void setType(byte value) {
         mType = value;
     }
 
@@ -124,11 +116,11 @@
      */
     private String getTypeString() {
         switch (mType) {
-            case CLOCK_TYPE_UNKNOWN:
+            case TYPE_UNKNOWN:
                 return "Unknown";
-            case CLOCK_TYPE_GPS_TIME:
+            case TYPE_GPS_TIME:
                 return "GpsTime";
-            case CLOCK_TYPE_LOCAL_HW_TIME:
+            case TYPE_LOCAL_HW_TIME:
                 return "LocalHwClock";
             default:
                 return "<Invalid:" + mType + ">";
@@ -171,8 +163,8 @@
 
     /**
      * Gets the GPS receiver internal clock value in nanoseconds.
-     * This can be either the 'local hardware clock' value ({@link #CLOCK_TYPE_LOCAL_HW_TIME}), or the
-     * current GPS time derived inside GPS receiver ({@link #CLOCK_TYPE_GPS_TIME}).
+     * This can be either the 'local hardware clock' value ({@link #TYPE_LOCAL_HW_TIME}), or the
+     * current GPS time derived inside GPS receiver ({@link #TYPE_GPS_TIME}).
      * {@link #getType()} defines the time reported.
      *
      * For 'local hardware clock' this value is expected to be monotonically increasing during the
@@ -231,7 +223,7 @@
     }
 
     /**
-     * Returns true if {@link #getFullBiasInNs()} is available, false otherwise.
+     * Returns true if {@link @getFullBiasInNs()} is available, false otherwise.
      */
     public boolean hasFullBiasInNs() {
         return isFlagSet(HAS_FULL_BIAS);
@@ -241,7 +233,7 @@
      * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
      * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
      *
-     * This value is available if {@link #CLOCK_TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved
+     * This value is available if {@link #TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved
      * the clock for GPS time.
      * {@link #getBiasUncertaintyInNs()} should be used for quality check.
      *
@@ -395,20 +387,6 @@
     }
 
     /**
-     * Gets time of last hardware clock discontinuity.
-     */
-    public long getTimeOfLastHwClockDiscontinuityInNs() {
-        return mTimeOfLastHwClockDiscontinuityInNs;
-    }
-
-    /**
-     * Sets time of last hardware clock discontinuity.
-     */
-    public void setTimeOfLastHwClockDiscontinuityInNs(long timeOfLastHwClockDiscontinuityInNs) {
-        mTimeOfLastHwClockDiscontinuityInNs = timeOfLastHwClockDiscontinuityInNs;
-    }
-
-    /**
      * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
      */
     public void resetDriftUncertaintyInNsPerSec() {
@@ -431,7 +409,6 @@
             gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
             gpsClock.mDriftInNsPerSec = parcel.readDouble();
             gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
-            gpsClock.mTimeOfLastHwClockDiscontinuityInNs = parcel.readLong();
 
             return gpsClock;
         }
@@ -453,7 +430,6 @@
         parcel.writeDouble(mBiasUncertaintyInNs);
         parcel.writeDouble(mDriftInNsPerSec);
         parcel.writeDouble(mDriftUncertaintyInNsPerSec);
-        parcel.writeLong(mTimeOfLastHwClockDiscontinuityInNs);
     }
 
     @Override
@@ -497,17 +473,13 @@
                 "DriftUncertaintyInNsPerSec",
                 hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));
 
-        builder.append(String.format(format, "TimeOfLastHwClockDiscontinuityInNs",
-                getType() == CLOCK_TYPE_LOCAL_HW_TIME
-                        ? mTimeOfLastHwClockDiscontinuityInNs : null));
-
         return builder.toString();
     }
 
     private void initialize() {
         mFlags = HAS_NO_FLAGS;
         resetLeapSecond();
-        setType(CLOCK_TYPE_UNKNOWN);
+        setType(TYPE_UNKNOWN);
         setTimeInNs(Long.MIN_VALUE);
         resetTimeUncertaintyInNs();
         resetFullBiasInNs();
@@ -515,7 +487,6 @@
         resetBiasUncertaintyInNs();
         resetDriftInNsPerSec();
         resetDriftUncertaintyInNsPerSec();
-        setTimeOfLastHwClockDiscontinuityInNs(Long.MIN_VALUE);
     }
 
     private void setFlag(short flag) {
diff --git a/location/java/android/location/GpsMeasurement.java b/location/java/android/location/GpsMeasurement.java
index 366ad61..f13a440 100644
--- a/location/java/android/location/GpsMeasurement.java
+++ b/location/java/android/location/GpsMeasurement.java
@@ -16,17 +16,17 @@
 
 package android.location;
 
-import android.annotation.IntDef;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * A class representing a GPS satellite measurement, containing raw and computed information.
+ *
+ * @hide
  */
-public final class GpsMeasurement implements Parcelable {
+@SystemApi
+public class GpsMeasurement implements Parcelable {
     private int mFlags;
     private byte mPrn;
     private double mTimeOffsetInNs;
@@ -59,8 +59,6 @@
     private double mAzimuthInDeg;
     private double mAzimuthUncertaintyInDeg;
     private boolean mUsedInFix;
-    private double mPseudorangeRateCarrierInMetersPerSec;
-    private double mPseudorangeRateCarrierUncertaintyInMetersPerSec;
 
     // The following enumerations must be in sync with the values declared in gps.h
 
@@ -85,11 +83,6 @@
     private static final int HAS_USED_IN_FIX = (1<<17);
     private static final int GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18);
 
-    /** The status of 'loss of lock'. */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({LOSS_OF_LOCK_UNKNOWN, LOSS_OF_LOCK_OK, LOSS_OF_LOCK_CYCLE_SLIP})
-    public @interface LossOfLockStatus {}
-
     /**
      * The indicator is not available or it is unknown.
      */
@@ -105,12 +98,6 @@
      */
     public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2;
 
-    /** The status of multipath. */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({MULTIPATH_INDICATOR_UNKNOWN, MULTIPATH_INDICATOR_DETECTED,
-        MULTIPATH_INDICATOR_NOT_USED})
-    public @interface MultipathIndicator {}
-
     /**
      * The indicator is not available or it is unknown.
      */
@@ -231,10 +218,6 @@
         mAzimuthInDeg = measurement.mAzimuthInDeg;
         mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg;
         mUsedInFix = measurement.mUsedInFix;
-        mPseudorangeRateCarrierInMetersPerSec =
-                measurement.mPseudorangeRateCarrierInMetersPerSec;
-        mPseudorangeRateCarrierUncertaintyInMetersPerSec =
-                measurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec;
     }
 
     /**
@@ -793,7 +776,6 @@
     /**
      * Gets a value indicating the 'loss of lock' state of the event.
      */
-    @LossOfLockStatus
     public byte getLossOfLock() {
         return mLossOfLock;
     }
@@ -801,7 +783,7 @@
     /**
      * Sets the 'loss of lock' status.
      */
-    public void setLossOfLock(@LossOfLockStatus byte value) {
+    public void setLossOfLock(byte value) {
         mLossOfLock = value;
     }
 
@@ -959,7 +941,6 @@
     /**
      * Gets a value indicating the 'multipath' state of the event.
      */
-    @MultipathIndicator
     public byte getMultipathIndicator() {
         return mMultipathIndicator;
     }
@@ -967,7 +948,7 @@
     /**
      * Sets the 'multi-path' indicator.
      */
-    public void setMultipathIndicator(@MultipathIndicator byte value) {
+    public void setMultipathIndicator(byte value) {
         mMultipathIndicator = value;
     }
 
@@ -1176,34 +1157,6 @@
         mUsedInFix = value;
     }
 
-    /**
-     * Gets pseudorange rate (based on carrier phase changes) at the timestamp in m/s.
-     */
-    public double getPseudorangeRateCarrierInMetersPerSec() {
-        return mPseudorangeRateCarrierInMetersPerSec;
-    }
-
-    /**
-     * Sets pseudorange rate (based on carrier phase changes) at the timestamp in m/s.
-     */
-    public void setPseudorangeRateCarrierInMetersPerSec(double value) {
-        mPseudorangeRateCarrierInMetersPerSec = value;
-    }
-
-    /**
-     * Gets 1-Sigma uncertainty of the pseudorange rate carrier.
-     */
-    public double getPseudorangeRateCarrierUncertaintyInMetersPerSec() {
-        return mPseudorangeRateCarrierUncertaintyInMetersPerSec;
-    }
-
-    /**
-     * Sets 1-Sigma uncertainty of the pseudorange rate carrier.
-     */
-    public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double value) {
-        mPseudorangeRateCarrierUncertaintyInMetersPerSec = value;
-    }
-
     public static final Creator<GpsMeasurement> CREATOR = new Creator<GpsMeasurement>() {
         @Override
         public GpsMeasurement createFromParcel(Parcel parcel) {
@@ -1241,8 +1194,6 @@
             gpsMeasurement.mAzimuthInDeg = parcel.readDouble();
             gpsMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble();
             gpsMeasurement.mUsedInFix = parcel.readInt() != 0;
-            gpsMeasurement.mPseudorangeRateCarrierInMetersPerSec = parcel.readDouble();
-            gpsMeasurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec = parcel.readDouble();
 
             return gpsMeasurement;
         }
@@ -1286,8 +1237,6 @@
         parcel.writeDouble(mAzimuthInDeg);
         parcel.writeDouble(mAzimuthUncertaintyInDeg);
         parcel.writeInt(mUsedInFix ? 1 : 0);
-        parcel.writeDouble(mPseudorangeRateCarrierInMetersPerSec);
-        parcel.writeDouble(mPseudorangeRateCarrierUncertaintyInMetersPerSec);
     }
 
     @Override
@@ -1412,11 +1361,6 @@
 
         builder.append(String.format(format, "UsedInFix", mUsedInFix));
 
-        builder.append(String.format(format, "PseudorangeRateCarrierInMetersPerSec",
-                    mPseudorangeRateCarrierInMetersPerSec));
-        builder.append(String.format(format, "PseudorangeRateCarrierUncertaintyInMetersPerSec",
-                    mPseudorangeRateCarrierUncertaintyInMetersPerSec));
-
         return builder.toString();
     }
 
@@ -1453,8 +1397,6 @@
         resetAzimuthInDeg();
         resetAzimuthUncertaintyInDeg();
         setUsedInFix(false);
-        setPseudorangeRateCarrierInMetersPerSec(Double.MIN_VALUE);
-        setPseudorangeRateCarrierUncertaintyInMetersPerSec(Double.MIN_VALUE);
     }
 
     private void setFlag(int flag) {
diff --git a/location/java/android/location/GpsMeasurementCallbackTransport.java b/location/java/android/location/GpsMeasurementCallbackTransport.java
deleted file mode 100644
index 02d9026..0000000
--- a/location/java/android/location/GpsMeasurementCallbackTransport.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.location;
-
-import android.content.Context;
-import android.os.RemoteException;
-
-/**
- * A handler class to manage transport callbacks for {@link GpsMeasurementsEvent.Callback}.
- *
- * @hide
- */
-class GpsMeasurementCallbackTransport
-        extends LocalListenerHelper<GpsMeasurementsEvent.Callback> {
-    private final ILocationManager mLocationManager;
-
-    private final IGpsMeasurementsListener mListenerTransport = new ListenerTransport();
-
-    public GpsMeasurementCallbackTransport(Context context, ILocationManager locationManager) {
-        super(context, "GpsMeasurementListenerTransport");
-        mLocationManager = locationManager;
-    }
-
-    @Override
-    protected boolean registerWithServer() throws RemoteException {
-        return mLocationManager.addGpsMeasurementsListener(
-                mListenerTransport,
-                getContext().getPackageName());
-    }
-
-    @Override
-    protected void unregisterFromServer() throws RemoteException {
-        mLocationManager.removeGpsMeasurementsListener(mListenerTransport);
-    }
-
-    private class ListenerTransport extends IGpsMeasurementsListener.Stub {
-        @Override
-        public void onGpsMeasurementsReceived(final GpsMeasurementsEvent event) {
-            ListenerOperation<GpsMeasurementsEvent.Callback> operation =
-                    new ListenerOperation<GpsMeasurementsEvent.Callback>() {
-                @Override
-                public void execute(GpsMeasurementsEvent.Callback callback) throws RemoteException {
-                    callback.onGpsMeasurementsReceived(event);
-                }
-            };
-            foreach(operation);
-        }
-
-        @Override
-        public void onStatusChanged(final int status) {
-            ListenerOperation<GpsMeasurementsEvent.Callback> operation =
-                    new ListenerOperation<GpsMeasurementsEvent.Callback>() {
-                @Override
-                public void execute(GpsMeasurementsEvent.Callback callback) throws RemoteException {
-                    callback.onStatusChanged(status);
-                }
-            };
-            foreach(operation);
-        }
-    }
-}
diff --git a/location/java/android/location/GpsMeasurementsEvent.aidl b/location/java/android/location/GpsMeasurementsEvent.aidl
deleted file mode 100644
index 2c46262..0000000
--- a/location/java/android/location/GpsMeasurementsEvent.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2014, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.location;
-
-parcelable GpsMeasurementsEvent;
diff --git a/location/java/android/location/GpsMeasurementsEvent.java b/location/java/android/location/GpsMeasurementsEvent.java
index ef9edeb..1366873 100644
--- a/location/java/android/location/GpsMeasurementsEvent.java
+++ b/location/java/android/location/GpsMeasurementsEvent.java
@@ -16,13 +16,11 @@
 
 package android.location;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.security.InvalidParameterException;
 import java.util.Arrays;
 import java.util.Collection;
@@ -30,13 +28,12 @@
 
 /**
  * A class implementing a container for data associated with a measurement event.
- * Events are delivered to registered instances of {@link Callback}.
+ * Events are delivered to registered instances of {@link Listener}.
+ *
+ * @hide
  */
-public final class GpsMeasurementsEvent implements Parcelable {
-    /** The status of GPS measurements event. */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
-    public @interface GpsMeasurementsStatus {}
+@SystemApi
+public class GpsMeasurementsEvent implements Parcelable {
 
     /**
      * The system does not support tracking of GPS Measurements. This status will not change in the
@@ -61,20 +58,22 @@
     /**
      * Used for receiving GPS satellite measurements from the GPS engine.
      * Each measurement contains raw and computed data identifying a satellite.
-     * You can implement this interface and call
-     * {@link LocationManager#registerGpsMeasurementCallback}.
+     * You can implement this interface and call {@link LocationManager#addGpsMeasurementListener}.
+     *
+     * @hide
      */
-    public static abstract class Callback {
+    @SystemApi
+    public interface Listener {
 
         /**
          * Returns the latest collected GPS Measurements.
          */
-        public void onGpsMeasurementsReceived(GpsMeasurementsEvent eventArgs) {}
+        void onGpsMeasurementsReceived(GpsMeasurementsEvent eventArgs);
 
         /**
          * Returns the latest status of the GPS Measurements sub-system.
          */
-        public void onStatusChanged(@GpsMeasurementsStatus int status) {}
+        void onStatusChanged(int status);
     }
 
     public GpsMeasurementsEvent(GpsClock clock, GpsMeasurement[] measurements) {
diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java
index d799572..5c3c710 100644
--- a/location/java/android/location/GpsNavigationMessage.java
+++ b/location/java/android/location/GpsNavigationMessage.java
@@ -16,54 +16,49 @@
 
 package android.location;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.security.InvalidParameterException;
 
 /**
  * A class containing a GPS satellite Navigation Message.
+ *
+ * @hide
  */
-public final class GpsNavigationMessage implements Parcelable {
+@SystemApi
+public class GpsNavigationMessage implements Parcelable {
 
     private static final byte[] EMPTY_ARRAY = new byte[0];
 
-    /** The type of the GPS Clock. */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({MESSAGE_TYPE_UNKNOWN, MESSAGE_TYPE_L1CA, MESSAGE_TYPE_L2CNAV, MESSAGE_TYPE_L5CNAV,
-            MESSAGE_TYPE_CNAV2})
-    public @interface GpsNavigationMessageType {}
-
     // The following enumerations must be in sync with the values declared in gps.h
 
     /**
      * The type of the navigation message is not available or unknown.
      */
-    public static final byte MESSAGE_TYPE_UNKNOWN = 0;
+    public static final byte TYPE_UNKNOWN = 0;
 
     /**
      * The Navigation Message is of type L1 C/A.
      */
-    public static final byte MESSAGE_TYPE_L1CA = 1;
+    public static final byte TYPE_L1CA = 1;
 
     /**
      * The Navigation Message is of type L1-CNAV.
      */
-    public static final byte MESSAGE_TYPE_L2CNAV = 2;
+    public static final byte TYPE_L2CNAV = 2;
 
     /**
      * The Navigation Message is of type L5-CNAV.
      */
-    public static final byte MESSAGE_TYPE_L5CNAV = 3;
+    public static final byte TYPE_L5CNAV = 3;
 
     /**
      * The Navigation Message is of type CNAV-2.
      */
-    public static final byte MESSAGE_TYPE_CNAV2 = 4;
+    public static final byte TYPE_CNAV2 = 4;
 
     /**
      * The Navigation Message Status is 'unknown'.
@@ -116,7 +111,6 @@
     /**
      * Gets the type of the navigation message contained in the object.
      */
-    @GpsNavigationMessageType
     public byte getType() {
         return mType;
     }
@@ -124,7 +118,7 @@
     /**
      * Sets the type of the navigation message.
      */
-    public void setType(@GpsNavigationMessageType byte value) {
+    public void setType(byte value) {
         mType = value;
     }
 
@@ -134,15 +128,15 @@
      */
     private String getTypeString() {
         switch (mType) {
-            case MESSAGE_TYPE_UNKNOWN:
+            case TYPE_UNKNOWN:
                 return "Unknown";
-            case MESSAGE_TYPE_L1CA:
+            case TYPE_L1CA:
                 return "L1 C/A";
-            case MESSAGE_TYPE_L2CNAV:
+            case TYPE_L2CNAV:
                 return "L2-CNAV";
-            case MESSAGE_TYPE_L5CNAV:
+            case TYPE_L5CNAV:
                 return "L5-CNAV";
-            case MESSAGE_TYPE_CNAV2:
+            case TYPE_CNAV2:
                 return "CNAV-2";
             default:
                 return "<Invalid:" + mType + ">";
@@ -320,7 +314,7 @@
     }
 
     private void initialize() {
-        mType = MESSAGE_TYPE_UNKNOWN;
+        mType = TYPE_UNKNOWN;
         mPrn = 0;
         mMessageId = -1;
         mSubmessageId = -1;
diff --git a/location/java/android/location/GpsNavigationMessageCallbackTransport.java b/location/java/android/location/GpsNavigationMessageCallbackTransport.java
deleted file mode 100644
index 155d96d..0000000
--- a/location/java/android/location/GpsNavigationMessageCallbackTransport.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.location;
-
-import android.content.Context;
-import android.os.RemoteException;
-
-/**
- * A handler class to manage transport callback for {@link GpsNavigationMessageEvent.Callback}.
- *
- * @hide
- */
-class GpsNavigationMessageCallbackTransport
-        extends LocalListenerHelper<GpsNavigationMessageEvent.Callback> {
-    private final ILocationManager mLocationManager;
-
-    private final IGpsNavigationMessageListener mListenerTransport = new ListenerTransport();
-
-    public GpsNavigationMessageCallbackTransport(
-            Context context,
-            ILocationManager locationManager) {
-        super(context, "GpsNavigationMessageCallbackTransport");
-        mLocationManager = locationManager;
-    }
-
-    @Override
-    protected boolean registerWithServer() throws RemoteException {
-        return mLocationManager.addGpsNavigationMessageListener(
-                mListenerTransport,
-                getContext().getPackageName());
-    }
-
-    @Override
-    protected void unregisterFromServer() throws RemoteException {
-        mLocationManager.removeGpsNavigationMessageListener(mListenerTransport);
-    }
-
-    private class ListenerTransport extends IGpsNavigationMessageListener.Stub {
-        @Override
-        public void onGpsNavigationMessageReceived(final GpsNavigationMessageEvent event) {
-            ListenerOperation<GpsNavigationMessageEvent.Callback> operation =
-                    new ListenerOperation<GpsNavigationMessageEvent.Callback>() {
-                @Override
-                public void execute(GpsNavigationMessageEvent.Callback callback)
-                        throws RemoteException {
-                    callback.onGpsNavigationMessageReceived(event);
-                }
-            };
-            foreach(operation);
-        }
-
-        @Override
-        public void onStatusChanged(final int status) {
-            ListenerOperation<GpsNavigationMessageEvent.Callback> operation =
-                    new ListenerOperation<GpsNavigationMessageEvent.Callback>() {
-                @Override
-                public void execute(GpsNavigationMessageEvent.Callback callback)
-                        throws RemoteException {
-                    callback.onStatusChanged(status);
-                }
-            };
-            foreach(operation);
-        }
-    }
-}
diff --git a/location/java/android/location/GpsNavigationMessageEvent.java b/location/java/android/location/GpsNavigationMessageEvent.java
index b16a485..bd6921c 100644
--- a/location/java/android/location/GpsNavigationMessageEvent.java
+++ b/location/java/android/location/GpsNavigationMessageEvent.java
@@ -16,60 +16,60 @@
 
 package android.location;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.security.InvalidParameterException;
 
 /**
  * A class implementing a container for data associated with a navigation message event.
- * Events are delivered to registered instances of {@link Callback}.
+ * Events are delivered to registered instances of {@link Listener}.
+ *
+ * @hide
  */
-public final class GpsNavigationMessageEvent implements Parcelable {
-    /** The status of GPS measurements event. */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
-    public @interface GpsNavigationMessageStatus {}
+@SystemApi
+public class GpsNavigationMessageEvent implements Parcelable {
 
     /**
      * The system does not support tracking of GPS Navigation Messages. This status will not change
      * in the future.
      */
-    public static final int STATUS_NOT_SUPPORTED = 0;
+    public static int STATUS_NOT_SUPPORTED = 0;
 
     /**
      * GPS Navigation Messages are successfully being tracked, it will receive updates once they are
      * available.
      */
-    public static final int STATUS_READY = 1;
+    public static int STATUS_READY = 1;
 
     /**
      * GPS provider or Location is disabled, updated will not be received until they are enabled.
      */
-    public static final int STATUS_GPS_LOCATION_DISABLED = 2;
+    public static int STATUS_GPS_LOCATION_DISABLED = 2;
 
     private final GpsNavigationMessage mNavigationMessage;
 
     /**
      * Used for receiving GPS satellite Navigation Messages from the GPS engine.
      * You can implement this interface and call
-     * {@link LocationManager#registerGpsNavigationMessageCallback}.
+     * {@link LocationManager#addGpsNavigationMessageListener}.
+     *
+     * @hide
      */
-    public static abstract class Callback {
+    @SystemApi
+    public interface Listener {
 
         /**
          * Returns the latest collected GPS Navigation Message.
          */
-        public void onGpsNavigationMessageReceived(GpsNavigationMessageEvent event) {}
+        void onGpsNavigationMessageReceived(GpsNavigationMessageEvent event);
 
         /**
          * Returns the latest status of the GPS Navigation Messages sub-system.
          */
-        public void onStatusChanged(@GpsNavigationMessageStatus int status) {}
+        void onStatusChanged(int status);
     }
 
     public GpsNavigationMessageEvent(GpsNavigationMessage message) {
diff --git a/location/java/android/location/IGpsMeasurementsListener.aidl b/location/java/android/location/IGnssMeasurementsListener.aidl
similarity index 81%
rename from location/java/android/location/IGpsMeasurementsListener.aidl
rename to location/java/android/location/IGnssMeasurementsListener.aidl
index cbd3100..69fa48a 100644
--- a/location/java/android/location/IGpsMeasurementsListener.aidl
+++ b/location/java/android/location/IGnssMeasurementsListener.aidl
@@ -16,12 +16,12 @@
 
 package android.location;
 
-import android.location.GpsMeasurementsEvent;
+import android.location.GnssMeasurementsEvent;
 
 /**
  * {@hide}
  */
-oneway interface IGpsMeasurementsListener {
-    void onGpsMeasurementsReceived(in GpsMeasurementsEvent event);
+oneway interface IGnssMeasurementsListener {
+    void onGnssMeasurementsReceived(in GnssMeasurementsEvent event);
     void onStatusChanged(in int status);
 }
diff --git a/location/java/android/location/IGpsNavigationMessageListener.aidl b/location/java/android/location/IGnssNavigationMessageListener.aidl
similarity index 79%
rename from location/java/android/location/IGpsNavigationMessageListener.aidl
rename to location/java/android/location/IGnssNavigationMessageListener.aidl
index a708ea6..de6129c 100644
--- a/location/java/android/location/IGpsNavigationMessageListener.aidl
+++ b/location/java/android/location/IGnssNavigationMessageListener.aidl
@@ -16,12 +16,12 @@
 
 package android.location;
 
-import android.location.GpsNavigationMessageEvent;
+import android.location.GnssNavigationMessageEvent;
 
 /**
  * {@hide}
  */
-oneway interface IGpsNavigationMessageListener {
-    void onGpsNavigationMessageReceived(in GpsNavigationMessageEvent event);
+oneway interface IGnssNavigationMessageListener {
+    void onGnssNavigationMessageReceived(in GnssNavigationMessageEvent event);
     void onStatusChanged(in int status);
 }
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 49d841f..4f1e039 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -21,9 +21,9 @@
 import android.location.Criteria;
 import android.location.GeocoderParams;
 import android.location.Geofence;
+import android.location.IGnssMeasurementsListener;
 import android.location.IGnssStatusListener;
-import android.location.IGpsMeasurementsListener;
-import android.location.IGpsNavigationMessageListener;
+import android.location.IGnssNavigationMessageListener;
 import android.location.ILocationListener;
 import android.location.Location;
 import android.location.LocationRequest;
@@ -61,13 +61,13 @@
 
     boolean sendNiResponse(int notifId, int userResponse);
 
-    boolean addGpsMeasurementsListener(in IGpsMeasurementsListener listener, in String packageName);
-    void removeGpsMeasurementsListener(in IGpsMeasurementsListener listener);
+    boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener, in String packageName);
+    void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
 
-    boolean addGpsNavigationMessageListener(
-            in IGpsNavigationMessageListener listener,
+    boolean addGnssNavigationMessageListener(
+            in IGnssNavigationMessageListener listener,
             in String packageName);
-    void removeGpsNavigationMessageListener(in IGpsNavigationMessageListener listener);
+    void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener);
 
     int getGpsYearOfHardware();
 
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 5447bb1..30cf101 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -64,8 +64,8 @@
 
     private final Context mContext;
     private final ILocationManager mService;
-    private final GpsMeasurementCallbackTransport mGpsMeasurementCallbackTransport;
-    private final GpsNavigationMessageCallbackTransport mGpsNavigationMessageCallbackTransport;
+    private final GnssMeasurementCallbackTransport mGnssMeasurementCallbackTransport;
+    private final GnssNavigationMessageCallbackTransport mGnssNavigationMessageCallbackTransport;
     private final HashMap<GpsStatus.Listener, GnssStatusListenerTransport> mGpsStatusListeners =
             new HashMap<>();
     private final HashMap<GpsStatus.NmeaListener, GnssStatusListenerTransport> mGpsNmeaListeners =
@@ -321,9 +321,9 @@
     public LocationManager(Context context, ILocationManager service) {
         mService = service;
         mContext = context;
-        mGpsMeasurementCallbackTransport = new GpsMeasurementCallbackTransport(mContext, mService);
-        mGpsNavigationMessageCallbackTransport =
-                new GpsNavigationMessageCallbackTransport(mContext, mService);
+        mGnssMeasurementCallbackTransport = new GnssMeasurementCallbackTransport(mContext, mService);
+        mGnssNavigationMessageCallbackTransport =
+                new GnssNavigationMessageCallbackTransport(mContext, mService);
     }
 
     private LocationProvider createProvider(String name, ProviderProperties properties) {
@@ -1817,73 +1817,119 @@
     }
 
     /**
-     * Registers a GPS Measurement callback.
-     *
-     * @param callback a {@link GpsMeasurementsEvent.Callback} object to register.
-     * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     * No-op method to keep backward-compatibility.
+     * Don't use it. Use {@link #registerGnssMeasurementCallback} instead.
+     * @hide
+     * @deprecated
      */
-    @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGpsMeasurementCallback(GpsMeasurementsEvent.Callback callback) {
-        return registerGpsMeasurementCallback(callback, null);
+    @Deprecated
+    @SystemApi
+    public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
+        return false;
     }
 
     /**
      * Registers a GPS Measurement callback.
      *
-     * @param callback a {@link GpsMeasurementsEvent.Callback} object to register.
+     * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
+     * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
+        return registerGnssMeasurementCallback(callback, null);
+    }
+
+    /**
+     * Registers a GPS Measurement callback.
+     *
+     * @param callback a {@link GnssMeasurementsEvent.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 registerGpsMeasurementCallback(GpsMeasurementsEvent.Callback callback,
+    public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback,
             Handler handler) {
-        return mGpsMeasurementCallbackTransport.add(callback, handler);
+        return mGnssMeasurementCallbackTransport.add(callback, handler);
+    }
+
+    /**
+     * No-op method to keep backward-compatibility.
+     * Don't use it. Use {@link #unregisterGnssMeasurementCallback} instead.
+     * @hide
+     * @deprecated
+     */
+    @Deprecated
+    @SystemApi
+    public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
     }
 
     /**
      * Unregisters a GPS Measurement callback.
      *
-     * @param callback a {@link GpsMeasurementsEvent.Callback} object to remove.
+     * @param callback a {@link GnssMeasurementsEvent.Callback} object to remove.
      */
-    public void unregisterGpsMeasurementCallback(GpsMeasurementsEvent.Callback callback) {
-        mGpsMeasurementCallbackTransport.remove(callback);
+    public void unregisterGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
+        mGnssMeasurementCallbackTransport.remove(callback);
+    }
+
+    /**
+     * No-op method to keep backward-compatibility.
+     * Don't use it. Use {@link #registerGnssNavigationMessageCallback} instead.
+     * @hide
+     * @deprecated
+     */
+    @Deprecated
+    @SystemApi
+    public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
+        return false;
     }
 
     /**
      * Registers a GPS Navigation Message callback.
      *
-     * @param callback a {@link GpsNavigationMessageEvent.Callback} object to register.
+     * @param callback a {@link GnssNavigationMessageEvent.Callback} object to register.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
-    public boolean registerGpsNavigationMessageCallback(
-            GpsNavigationMessageEvent.Callback callback) {
-        return registerGpsNavigationMessageCallback(callback, null);
+    public boolean registerGnssNavigationMessageCallback(
+            GnssNavigationMessageEvent.Callback callback) {
+        return registerGnssNavigationMessageCallback(callback, null);
     }
 
     /**
      * Registers a GPS Navigation Message callback.
      *
-     * @param callback a {@link GpsNavigationMessageEvent.Callback} object to register.
+     * @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.
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGpsNavigationMessageCallback(
-            GpsNavigationMessageEvent.Callback callback, Handler handler) {
-        return mGpsNavigationMessageCallbackTransport.add(callback, handler);
+    public boolean registerGnssNavigationMessageCallback(
+            GnssNavigationMessageEvent.Callback callback, Handler handler) {
+        return mGnssNavigationMessageCallbackTransport.add(callback, handler);
     }
 
     /**
      * Unregisters a GPS Navigation Message callback.
      *
-     * @param callback a {@link GpsNavigationMessageEvent.Callback} object to remove.
+     * @param callback a {@link GnssNavigationMessageEvent.Callback} object to remove.
      */
-    public void unregisterGpsNavigationMessageCallback(
-            GpsNavigationMessageEvent.Callback callback) {
-        mGpsNavigationMessageCallbackTransport.remove(callback);
+    public void unregisterGnssNavigationMessageCallback(
+            GnssNavigationMessageEvent.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/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 3007d86..b26b310 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1784,9 +1784,9 @@
      * Note that the actual playback of this data might occur after this function returns.
      *
      * @param audioData the array that holds the data to play.
-     * @param offsetInBytes the offset expressed in bytes in audioData where the data to play
+     * @param offsetInBytes the offset expressed in bytes in audioData where the data to write
      *    starts.
-     * @param sizeInBytes the number of bytes to read in audioData after the offset.
+     * @param sizeInBytes the number of bytes to write in audioData after the offset.
      * @return zero or the positive number of bytes that were written, or
      *    {@link #ERROR_INVALID_OPERATION}
      *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
@@ -1821,9 +1821,9 @@
      * Note that the actual playback of this data might occur after this function returns.
      *
      * @param audioData the array that holds the data to play.
-     * @param offsetInBytes the offset expressed in bytes in audioData where the data to play
+     * @param offsetInBytes the offset expressed in bytes in audioData where the data to write
      *    starts.
-     * @param sizeInBytes the number of bytes to read in audioData after the offset.
+     * @param sizeInBytes the number of bytes to write in audioData after the offset.
      * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
      *     effect in static mode.
      *     <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
@@ -1920,8 +1920,8 @@
      * In static buffer mode, copies the data to the buffer starting at offset 0.
      * Note that the actual playback of this data might occur after this function returns.
      *
-     * @param audioData the array that holds the data to play.
-     * @param offsetInShorts the offset expressed in shorts in audioData where the data to play
+     * @param audioData the array that holds the data to write.
+     * @param offsetInShorts the offset expressed in shorts in audioData where the data to write
      *     starts.
      * @param sizeInShorts the number of shorts to read in audioData after the offset.
      * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
@@ -1987,7 +1987,7 @@
      * and the write mode is ignored.
      * Note that the actual playback of this data might occur after this function returns.
      *
-     * @param audioData the array that holds the data to play.
+     * @param audioData the array that holds the data to write.
      *     The implementation does not clip for sample values within the nominal range
      *     [-1.0f, 1.0f], provided that all gains in the audio pipeline are
      *     less than or equal to unity (1.0f), and in the absence of post-processing effects
@@ -1998,8 +1998,8 @@
      *     and later processing in the audio path.  Therefore applications are encouraged
      *     to provide samples values within the nominal range.
      * @param offsetInFloats the offset, expressed as a number of floats,
-     *     in audioData where the data to play starts.
-     * @param sizeInFloats the number of floats to read in audioData after the offset.
+     *     in audioData where the data to write starts.
+     * @param sizeInFloats the number of floats to write in audioData after the offset.
      * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
      *     effect in static mode.
      *     <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
@@ -2070,7 +2070,7 @@
      * and the write mode is ignored.
      * Note that the actual playback of this data might occur after this function returns.
      *
-     * @param audioData the buffer that holds the data to play, starting at the position reported
+     * @param audioData the buffer that holds the data to write, starting at the position reported
      *     by <code>audioData.position()</code>.
      *     <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
      *     have been advanced to reflect the amount of data that was successfully written to
@@ -2137,7 +2137,7 @@
     /**
      * Writes the audio data to the audio sink for playback in streaming mode on a HW_AV_SYNC track.
      * The blocking behavior will depend on the write mode.
-     * @param audioData the buffer that holds the data to play, starting at the position reported
+     * @param audioData the buffer that holds the data to write, starting at the position reported
      *     by <code>audioData.position()</code>.
      *     <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
      *     have been advanced to reflect the amount of data that was successfully written to
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index f9fdd8d..54543ec 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -428,8 +428,17 @@
                     }
                 }
                 // rule didn't exist, add it
-                // FIXME doesn't work with RULE_MATCH_UID yet
-                mCriteria.add(new AttributeMatchCriterion(attrToMatch, rule));
+                switch (match_rule) {
+                    case RULE_MATCH_ATTRIBUTE_USAGE:
+                    case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+                        mCriteria.add(new AttributeMatchCriterion(attrToMatch, rule));
+                        break;
+                    case RULE_MATCH_UID:
+                        mCriteria.add(new AttributeMatchCriterion(intProp, rule));
+                        break;
+                    default:
+                        throw new IllegalStateException("Unreachable code in addRuleInternal()");
+                }
             }
             return this;
         }
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 93e6dac..56b2514 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -115,8 +115,11 @@
      * @param callback The connection callback.
      * @param rootHints An optional bundle of service-specific arguments to send
      * to the media browse service when connecting and retrieving the root id
-     * for browsing, or null if none.  The contents of this bundle may affect
+     * for browsing, or null if none. The contents of this bundle may affect
      * the information returned when browsing.
+     * @see android.service.media.MediaBrowserService.BrowserRoot#EXTRA_RECENT
+     * @see android.service.media.MediaBrowserService.BrowserRoot#EXTRA_OFFLINE
+     * @see android.service.media.MediaBrowserService.BrowserRoot#EXTRA_SUGGESTED
      */
     public MediaBrowser(Context context, ComponentName serviceComponent,
             ConnectionCallback callback, Bundle rootHints) {
@@ -178,9 +181,9 @@
         }
 
         if (!bound) {
-            // Tell them that it didn't work.  We are already on the main thread,
-            // but we don't want to do callbacks inside of connect().  So post it,
-            // and then check that we are on the same ServiceConnection.  We know
+            // Tell them that it didn't work. We are already on the main thread,
+            // but we don't want to do callbacks inside of connect(). So post it,
+            // and then check that we are on the same ServiceConnection. We know
             // we won't also get an onServiceConnected or onServiceDisconnected,
             // so we won't be doing double callbacks.
             mHandler.post(new Runnable() {
@@ -207,13 +210,13 @@
      */
     public void disconnect() {
         // It's ok to call this any state, because allowing this lets apps not have
-        // to check isConnected() unnecessarily.  They won't appreciate the extra
-        // assertions for this.  We do everything we can here to go back to a sane state.
+        // to check isConnected() unnecessarily. They won't appreciate the extra
+        // assertions for this. We do everything we can here to go back to a sane state.
         if (mServiceCallbacks != null) {
             try {
                 mServiceBinder.disconnect(mServiceCallbacks);
             } catch (RemoteException ex) {
-                // We are disconnecting anyway.  Log, just for posterity but it's not
+                // We are disconnecting anyway. Log, just for posterity but it's not
                 // a big problem.
                 Log.w(TAG, "RemoteException during connect for " + mServiceComponent);
             }
@@ -227,12 +230,12 @@
     }
 
     /**
-     * Null out the variables and unbind from the service.  This doesn't include
+     * Null out the variables and unbind from the service. This doesn't include
      * calling disconnect on the service, because we only try to do that in the
      * clean shutdown cases.
      * <p>
      * Everywhere that calls this EXCEPT for disconnect() should follow it with
-     * a call to mCallback.onConnectionFailed().  Disconnect doesn't do that callback
+     * a call to mCallback.onConnectionFailed(). Disconnect doesn't do that callback
      * for a clean shutdown, but everywhere else is a dirty shutdown and should
      * notify the app.
      */
@@ -455,8 +458,8 @@
 
     private void subscribeInternal(String parentId, Bundle options, SubscriptionCallback callback) {
         // Check arguments.
-        if (parentId == null) {
-            throw new IllegalArgumentException("parentId is null");
+        if (TextUtils.isEmpty(parentId)) {
+            throw new IllegalArgumentException("parentId is empty.");
         }
         if (callback == null) {
             throw new IllegalArgumentException("callback is null");
@@ -659,7 +662,7 @@
     }
 
     /**
-     * Return true if {@code callback} is the current ServiceCallbacks.  Also logs if it's not.
+     * Return true if {@code callback} is the current ServiceCallbacks. Also logs if it's not.
      */
     private boolean isCurrent(IMediaBrowserServiceCallbacks callback, String funcName) {
         if (mServiceCallbacks != callback) {
@@ -955,8 +958,8 @@
                                 mServiceCallbacks);
                     } catch (RemoteException ex) {
                         // Connect failed, which isn't good. But the auto-reconnect on the service
-                        // will take over and we will come back.  We will also get the
-                        // onServiceDisconnected, which has all the cleanup code.  So let that do
+                        // will take over and we will come back. We will also get the
+                        // onServiceDisconnected, which has all the cleanup code. So let that do
                         // it.
                         Log.w(TAG, "RemoteException during connect for " + mServiceComponent);
                         if (DBG) {
@@ -1005,7 +1008,7 @@
         }
 
         /**
-         * Return true if this is the current ServiceConnection.  Also logs if it's not.
+         * Return true if this is the current ServiceConnection. Also logs if it's not.
          */
         private boolean isCurrent(String funcName) {
             if (mServiceConnection != this) {
@@ -1031,7 +1034,7 @@
         }
 
         /**
-         * The other side has acknowledged our connection.  The parameters to this function
+         * The other side has acknowledged our connection. The parameters to this function
          * are the initial data as requested.
          */
         @Override
@@ -1044,7 +1047,7 @@
         }
 
         /**
-         * The other side does not like us.  Tell the app via onConnectionFailed.
+         * The other side does not like us. Tell the app via onConnectionFailed.
          */
         @Override
         public void onConnectFailed() {
diff --git a/media/java/android/media/browse/MediaBrowserUtils.java b/media/java/android/media/browse/MediaBrowserUtils.java
index 4f198ac..b06e598 100644
--- a/media/java/android/media/browse/MediaBrowserUtils.java
+++ b/media/java/android/media/browse/MediaBrowserUtils.java
@@ -40,10 +40,10 @@
     }
 
     public static boolean hasDuplicatedItems(Bundle options1, Bundle options2) {
-        int page1 = options1.getInt(MediaBrowser.EXTRA_PAGE, -1);
-        int page2 = options2.getInt(MediaBrowser.EXTRA_PAGE, -1);
-        int pageSize1 = options1.getInt(MediaBrowser.EXTRA_PAGE_SIZE, -1);
-        int pageSize2 = options2.getInt(MediaBrowser.EXTRA_PAGE_SIZE, -1);
+        int page1 = options1 == null ? -1 : options1.getInt(MediaBrowser.EXTRA_PAGE, -1);
+        int page2 = options2 == null ? -1 : options2.getInt(MediaBrowser.EXTRA_PAGE, -1);
+        int pageSize1 = options1 == null ? -1 : options1.getInt(MediaBrowser.EXTRA_PAGE_SIZE, -1);
+        int pageSize2 = options2 == null ? -1 : options2.getInt(MediaBrowser.EXTRA_PAGE_SIZE, -1);
 
         int startIndex1, startIndex2, endIndex1, endIndex2;
         if (page1 == -1 || pageSize1 == -1) {
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 20491e4..f9a23f9 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -32,6 +32,7 @@
 import android.graphics.drawable.Icon;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
@@ -114,6 +115,7 @@
     private final int mTunerCount;
     private final boolean mCanRecord;
     private final boolean mIsHardwareInput;
+    private final Bundle mExtras;
 
     // Attributes from XML meta data.
     private String mSetupActivity;
@@ -252,7 +254,7 @@
      */
     private TvInputInfo(ResolveInfo service, String id, String parentId, int type,
             boolean isHardwareInput, boolean isConnectedToHdmiSwitch, int tunerCount,
-            boolean canRecord) {
+            boolean canRecord, Bundle extras) {
         mService = service;
         mId = id;
         mParentId = parentId;
@@ -261,6 +263,7 @@
         mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
         mTunerCount = tunerCount;
         mCanRecord = canRecord;
+        mExtras = extras;
     }
 
     /**
@@ -362,6 +365,14 @@
     }
 
     /**
+     * Returns the extras associated with this TV input.
+     * @hide
+     */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    /**
      * Returns the HDMI device information of this TV input.
      * @hide
      */
@@ -524,6 +535,7 @@
         dest.writeInt(mLabelResId);
         dest.writeString(mLabel);
         dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
+        dest.writeBundle(mExtras);
     }
 
     private Drawable loadServiceIcon(Context context) {
@@ -563,6 +575,7 @@
         mLabelResId = in.readInt();
         mLabel = in.readString();
         mIsConnectedToHdmiSwitch = in.readByte() == 1;
+        mExtras = in.readBundle();
     }
 
     /**
@@ -604,6 +617,7 @@
         private HdmiDeviceInfo mHdmiDeviceInfo;
         private String mParentId;
         private TvInputHardwareInfo mTvInputHardwareInfo;
+        private Bundle mExtras;
 
         /**
          * Constructs a new builder for {@link TvInputInfo}.
@@ -732,6 +746,18 @@
         }
 
         /**
+         * Sets the extras associated with this TV input.
+         *
+         * @param extras The extras associated with this TV input.
+         * @return This Builder object to allow for chaining of calls to builder methods.
+         * @hide
+         */
+        public Builder setExtras(Bundle extras) {
+            this.mExtras = extras;
+            return this;
+        }
+
+        /**
          * Creates a {@link TvInputInfo} instance with the specified fields. Most of the information
          * is obtained by parsing the AndroidManifest and {@link TvInputService#SERVICE_META_DATA}
          * for the {@link TvInputService} this TV input implements.
@@ -765,7 +791,7 @@
             }
 
             TvInputInfo info = new TvInputInfo(mResolveInfo, id, mParentId, type, isHardwareInput,
-                    isConnectedToHdmiSwitch, mTunerCount, mCanRecord);
+                    isConnectedToHdmiSwitch, mTunerCount, mCanRecord, mExtras);
             return parseServiceMetadata(type, info);
         }
 
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 73f1e32..1d80068 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -285,6 +285,18 @@
         }
 
         @Override
+        void onConnected(TvInputManager.Session session) {
+            if (DEBUG) {
+                Log.d(TAG, "onConnected()");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onConnected - session not created");
+                return;
+            }
+            mCallback.onConnected();
+        }
+
+        @Override
         public void onSessionReleased(TvInputManager.Session session) {
             if (DEBUG) {
                 Log.d(TAG, "onSessionReleased()");
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 299b770..3372524 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -16,6 +16,7 @@
 
 package android.service.media;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
@@ -41,6 +42,8 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -49,7 +52,7 @@
  * Base class for media browse services.
  * <p>
  * Media browse services enable applications to browse media content provided by an application
- * and ask the application to start playing it.  They may also be used to control content that
+ * and ask the application to start playing it. They may also be used to control content that
  * is already playing by way of a {@link MediaSession}.
  * </p>
  *
@@ -86,6 +89,11 @@
 
     private static final int RESULT_FLAG_OPTION_NOT_HANDLED = 0x00000001;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag=true, value = { RESULT_FLAG_OPTION_NOT_HANDLED })
+    private @interface ResultFlags { }
+
     private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap<>();
     private final Handler mHandler = new Handler();
     private ServiceBinder mBinder;
@@ -106,10 +114,10 @@
      * Completion handler for asynchronous callback methods in {@link MediaBrowserService}.
      * <p>
      * Each of the methods that takes one of these to send the result must call
-     * {@link #sendResult} to respond to the caller with the given results.  If those
+     * {@link #sendResult} to respond to the caller with the given results. If those
      * functions return without calling {@link #sendResult}, they must instead call
      * {@link #detach} before returning, and then may call {@link #sendResult} when
-     * they are done.  If more than one of those methods is called, an exception will
+     * they are done. If more than one of those methods is called, an exception will
      * be thrown.
      *
      * @see MediaBrowserService#onLoadChildren
@@ -119,7 +127,7 @@
         private Object mDebug;
         private boolean mDetachCalled;
         private boolean mSendResultCalled;
-        private int mFlag;
+        private int mFlags;
 
         Result(Object debug) {
             mDebug = debug;
@@ -133,7 +141,7 @@
                 throw new IllegalStateException("sendResult() called twice for: " + mDebug);
             }
             mSendResultCalled = true;
-            onResultSent(result, mFlag);
+            onResultSent(result, mFlags);
         }
 
         /**
@@ -156,15 +164,15 @@
             return mDetachCalled || mSendResultCalled;
         }
 
-        void setFlag(int flag) {
-            mFlag = flag;
+        void setFlags(@ResultFlags int flags) {
+            mFlags = flags;
         }
 
         /**
          * Called when the result is sent, after assertions about not being called twice
          * have happened.
          */
-        void onResultSent(T result, int flag) {
+        void onResultSent(T result, @ResultFlags int flags) {
         }
     }
 
@@ -184,7 +192,7 @@
                     public void run() {
                         final IBinder b = callbacks.asBinder();
 
-                        // Clear out the old subscriptions.  We are getting new ones.
+                        // Clear out the old subscriptions. We are getting new ones.
                         mConnections.remove(b);
 
                         final ConnectionRecord connection = new ConnectionRecord();
@@ -228,7 +236,7 @@
                     public void run() {
                         final IBinder b = callbacks.asBinder();
 
-                        // Clear out the old subscriptions.  We are getting new ones.
+                        // Clear out the old subscriptions. We are getting new ones.
                         final ConnectionRecord old = mConnections.remove(b);
                         if (old != null) {
                             // TODO
@@ -343,6 +351,9 @@
      *            root id for browsing, or null if none. The contents of this
      *            bundle may affect the information returned when browsing.
      * @return The {@link BrowserRoot} for accessing this app's content or null.
+     * @see BrowserRoot#EXTRA_RECENT
+     * @see BrowserRoot#EXTRA_OFFLINE
+     * @see BrowserRoot#EXTRA_SUGGESTED
      */
     public abstract @Nullable BrowserRoot onGetRoot(@NonNull String clientPackageName,
             int clientUid, @Nullable Bundle rootHints);
@@ -388,7 +399,7 @@
         // To support backward compatibility, when the implementation of MediaBrowserService doesn't
         // override onLoadChildren() with options, onLoadChildren() without options will be used
         // instead, and the options will be applied in the implementation of result.onResultSent().
-        result.setFlag(RESULT_FLAG_OPTION_NOT_HANDLED);
+        result.setFlags(RESULT_FLAG_OPTION_NOT_HANDLED);
         onLoadChildren(parentId, result);
     }
 
@@ -574,7 +585,7 @@
         final Result<List<MediaBrowser.MediaItem>> result
                 = new Result<List<MediaBrowser.MediaItem>>(parentId) {
             @Override
-            void onResultSent(List<MediaBrowser.MediaItem> list, int flag) {
+            void onResultSent(List<MediaBrowser.MediaItem> list, @ResultFlags int flag) {
                 if (mConnections.get(connection.callbacks.asBinder()) != connection) {
                     if (DBG) {
                         Log.d(TAG, "Not sending onLoadChildren result for connection that has"
@@ -639,7 +650,7 @@
         final Result<MediaBrowser.MediaItem> result =
                 new Result<MediaBrowser.MediaItem>(itemId) {
             @Override
-            void onResultSent(MediaBrowser.MediaItem item, int flag) {
+            void onResultSent(MediaBrowser.MediaItem item, @ResultFlags int flag) {
                 Bundle bundle = new Bundle();
                 bundle.putParcelable(KEY_MEDIA_ITEM, item);
                 receiver.send(0, bundle);
@@ -659,6 +670,57 @@
      * when first connected.
      */
     public static final class BrowserRoot {
+        /**
+         * The lookup key for a boolean that indicates whether the browser service should return a
+         * browser root for recently played media items.
+         *
+         * <p>When creating a media browser for a given media browser service, this key can be
+         * supplied as a root hint for retrieving media items that are recently played.
+         * If the media browser service can provide such media items, the implementation must return
+         * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back.
+         *
+         * <p>The root hint may contain multiple keys.
+         *
+         * @see #EXTRA_OFFLINE
+         * @see #EXTRA_SUGGESTED
+         */
+        public static final String EXTRA_RECENT = "android.service.media.extra.RECENT";
+
+        /**
+         * The lookup key for a boolean that indicates whether the browser service should return a
+         * browser root for offline media items.
+         *
+         * <p>When creating a media browser for a given media browser service, this key can be
+         * supplied as a root hint for retrieving media items that are can be played without an
+         * internet connection.
+         * If the media browser service can provide such media items, the implementation must return
+         * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back.
+         *
+         * <p>The root hint may contain multiple keys.
+         *
+         * @see #EXTRA_RECENT
+         * @see #EXTRA_SUGGESTED
+         */
+        public static final String EXTRA_OFFLINE = "android.service.media.extra.OFFLINE";
+
+        /**
+         * The lookup key for a boolean that indicates whether the browser service should return a
+         * browser root for suggested media items.
+         *
+         * <p>When creating a media browser for a given media browser service, this key can be
+         * supplied as a root hint for retrieving the media items suggested by the media browser
+         * service. The list of media items passed in {@link android.media.browse.MediaBrowser.SubscriptionCallback#onChildrenLoaded(String, List)}
+         * is considered ordered by relevance, first being the top suggestion.
+         * If the media browser service can provide such media items, the implementation must return
+         * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back.
+         *
+         * <p>The root hint may contain multiple keys.
+         *
+         * @see #EXTRA_RECENT
+         * @see #EXTRA_OFFLINE
+         */
+        public static final String EXTRA_SUGGESTED = "android.service.media.extra.SUGGESTED";
+
         final private String mRootId;
         final private Bundle mExtras;
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
index 74da2c9..e718742 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewTestCase.java
@@ -90,7 +90,7 @@
     private static final int WAIT_FOR_SURFACE_CHANGE_TIMEOUT_MS = 1000;
 
     // Instrumentation arguments
-    protected static final String ARG_KEY_REPEAT = "repeat";
+    protected static final String ARG_KEY_ITERATIONS = "iterations";
     protected static final String ARG_KEY_WAIT_INTERVAL_MS = "waitIntervalMs";
     protected static final String ARG_KEY_RESULT_TO_FILE = "resultToFile";
 
@@ -126,8 +126,8 @@
 
     protected WindowManager mWindowManager;
 
-    // Repeat tests a given times. Default to 1.
-    protected int mRepeat = 1;
+    // Set the number of iterations to run stress testing. Default to 1.
+    protected int mIterations = 1;
     // The interval between test iterations used for stress test.
     protected long mTestWaitIntervalMs = 1 * 1000;  // 1 sec
     protected boolean mWriteToFile = true;
@@ -165,10 +165,10 @@
 
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
 
-        mRepeat = getArgumentsAsNumber(ARG_KEY_REPEAT, 1).intValue();
+        mIterations = getArgumentsAsNumber(ARG_KEY_ITERATIONS, 1).intValue();
         mTestWaitIntervalMs = getArgumentsAsNumber(ARG_KEY_WAIT_INTERVAL_MS, 1000).longValue();
         mWriteToFile = getArgumentsAsBoolean(ARG_KEY_RESULT_TO_FILE, true);
-        Log.i(TAG, "Argument: repeat count=" + mRepeat);
+        Log.i(TAG, "Argument: iteration count=" + mIterations);
         Log.i(TAG, "Argument: interval (ms)=" + mTestWaitIntervalMs);
         Log.i(TAG, "Argument: result to file=" + (mWriteToFile ? "true" : "false"));
         mResultPrinter = new CameraTestResultPrinter(getInstrumentation(), mWriteToFile);
@@ -790,8 +790,8 @@
         return defaultValue;
     }
 
-    protected int getRepeatCount() {
-        return mRepeat;
+    protected int getIterationCount() {
+        return mIterations;
     }
 
     protected long getTestWaitIntervalMs() {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java
index b152975..ebfd92e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java
@@ -24,7 +24,6 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.util.Log;
-import android.util.Rational;
 import android.util.Size;
 
 import java.util.Arrays;
@@ -47,7 +46,7 @@
  *
  * adb shell am instrument \
  *    -e class com.android.mediaframeworktest.stress.Camera2CaptureRequestTest#testAeModeAndLock \
- *    -e repeat 10 \
+ *    -e iterations 10 \
  *    -e waitIntervalMs 1000 \
  *    -e resultToFile false \
  *    -r -w com.android.mediaframeworktest/.Camera2InstrumentationTestRunner
@@ -100,16 +99,16 @@
                 updatePreviewSurface(maxPreviewSz);
 
                 // Test iteration starts...
-                for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
-                    Log.v(TAG, String.format("AE mode and lock: %d/%d", repeat + 1,
-                            getRepeatCount()));
+                for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+                    Log.v(TAG, String.format("AE mode and lock: %d/%d", iteration + 1,
+                            getIterationCount()));
 
                     // Test aeMode and lock
                     int[] aeModes = mStaticInfo.getAeAvailableModesChecked();
                     for (int mode : aeModes) {
                         aeModeAndLockTestByMode(mode);
                     }
-                    getResultPrinter().printStatus(getRepeatCount(), repeat + 1, mCameraIds[i]);
+                    getResultPrinter().printStatus(getIterationCount(), iteration + 1, mCameraIds[i]);
                     Thread.sleep(getTestWaitIntervalMs());
                 }
             } finally {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
index e7c91cf..a9b6bfd 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
@@ -67,7 +67,7 @@
  *
  * adb shell am instrument \
  *    -e class com.android.mediaframeworktest.stress.Camera2RecordingTest#testBasicRecording \
- *    -e repeat 10 \
+ *    -e iterations 10 \
  *    -e waitIntervalMs 1000 \
  *    -e resultToFile false \
  *    -r -w com.android.mediaframeworktest/.Camera2InstrumentationTestRunner
@@ -142,11 +142,12 @@
                 initSupportedVideoSize(mCameraIds[i]);
 
                 // Test iteration starts...
-                for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
-                    Log.v(TAG, String.format("Recording video: %d/%d", repeat + 1,
-                            getRepeatCount()));
+                for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+                    Log.v(TAG, String.format("Recording video: %d/%d", iteration + 1,
+                            getIterationCount()));
                     basicRecordingTestByCamera(mCamcorderProfileList, useVideoStab);
-                    getResultPrinter().printStatus(getRepeatCount(), repeat + 1, mCameraIds[i]);
+                    getResultPrinter().printStatus(getIterationCount(), iteration + 1,
+                            mCameraIds[i]);
                     Thread.sleep(getTestWaitIntervalMs());
                 }
             } finally {
@@ -206,9 +207,9 @@
                 }
 
                 // Test iteration starts...
-                for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
-                    Log.v(TAG, String.format("Constrained high speed recording: %d/%d", repeat + 1,
-                            getRepeatCount()));
+                for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+                    Log.v(TAG, String.format("Constrained high speed recording: %d/%d",
+                            iteration + 1, getIterationCount()));
 
                     StreamConfigurationMap config =
                             mStaticInfo.getValueFromKeyNonNull(
@@ -257,7 +258,7 @@
                             validateRecording(size, durationMs);
                         }
 
-                    getResultPrinter().printStatus(getRepeatCount(), repeat + 1, id);
+                    getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
                     Thread.sleep(getTestWaitIntervalMs());
                     }
                 }
@@ -481,11 +482,11 @@
                     initSupportedVideoSize(id);
 
                     // Test iteration starts...
-                    for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
-                        Log.v(TAG, String.format("Video snapshot: %d/%d", repeat + 1,
-                                getRepeatCount()));
+                    for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+                        Log.v(TAG, String.format("Video snapshot: %d/%d", iteration + 1,
+                                getIterationCount()));
                         videoSnapshotTestByCamera(burstTest);
-                        getResultPrinter().printStatus(getRepeatCount(), repeat + 1, id);
+                        getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
                         Thread.sleep(getTestWaitIntervalMs());
                     }
                 } finally {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2ReprocessCaptureTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2ReprocessCaptureTest.java
index 2dac371..8f94897 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2ReprocessCaptureTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2ReprocessCaptureTest.java
@@ -58,7 +58,7 @@
  * adb shell am instrument \
  *    -e class \
  *    com.android.mediaframeworktest.stress.Camera2StillCaptureTest#Camera2ReprocessCaptureTest \
- *    -e repeat 1 \
+ *    -e iterations 1 \
  *    -e waitIntervalMs 1000 \
  *    -e resultToFile false \
  *    -r -w com.android.mediaframeworktest/.Camera2InstrumentationTestRunner
@@ -110,12 +110,12 @@
             }
 
             // Test iteration starts...
-            for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
-                Log.v(TAG, String.format("Reprocessing YUV to JPEG: %d/%d", repeat + 1,
-                        getRepeatCount()));
+            for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+                Log.v(TAG, String.format("Reprocessing YUV to JPEG: %d/%d", iteration + 1,
+                        getIterationCount()));
                 // YUV_420_888 -> JPEG must be supported.
                 testBasicReprocessing(id, ImageFormat.YUV_420_888, ImageFormat.JPEG);
-                getResultPrinter().printStatus(getRepeatCount(), repeat + 1, id);
+                getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
                 Thread.sleep(getTestWaitIntervalMs());
             }
         }
@@ -131,12 +131,12 @@
             }
 
             // Test iteration starts...
-            for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
-                Log.v(TAG, String.format("Reprocessing OPAQUE to JPEG: %d/%d", repeat + 1,
-                        getRepeatCount()));
+            for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+                Log.v(TAG, String.format("Reprocessing OPAQUE to JPEG: %d/%d", iteration + 1,
+                        getIterationCount()));
                 // OPAQUE -> JPEG must be supported.
                 testBasicReprocessing(id, ImageFormat.PRIVATE, ImageFormat.JPEG);
-                getResultPrinter().printStatus(getRepeatCount(), repeat + 1, id);
+                getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
                 Thread.sleep(getTestWaitIntervalMs());
             }
 
@@ -157,12 +157,12 @@
                 openDevice(id);
 
                 // Test iteration starts...
-                for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
+                for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
                     Log.v(TAG, String.format("Reprocessing size format with preview: %d/%d",
-                            repeat + 1, getRepeatCount()));
+                            iteration + 1, getIterationCount()));
                     testReprocessingAllCombinations(id, mOrderedPreviewSizes.get(0),
                             CaptureTestCase.SINGLE_SHOT);
-                    getResultPrinter().printStatus(getRepeatCount(), repeat + 1, id);
+                    getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
                     Thread.sleep(getTestWaitIntervalMs());
                 }
             } finally {
@@ -185,16 +185,16 @@
                 openDevice(id);
 
                 // Test iteration starts...
-                for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
+                for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
                     Log.v(TAG, String.format("Reprocessing mixed burst with or without preview: "
-                            + "%d/%d", repeat + 1, getRepeatCount()));
+                            + "%d/%d", iteration + 1, getIterationCount()));
                     // no preview
                     testReprocessingAllCombinations(id, /*previewSize*/null,
                             CaptureTestCase.MIXED_BURST);
                     // with preview
                     testReprocessingAllCombinations(id, mOrderedPreviewSizes.get(0),
                             CaptureTestCase.MIXED_BURST);
-                    getResultPrinter().printStatus(getRepeatCount(), repeat + 1, id);
+                    getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
                     Thread.sleep(getTestWaitIntervalMs());
                 }
             } finally {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java
index 16dfb2b..812543b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java
@@ -59,7 +59,7 @@
  *
  * adb shell am instrument \
  *    -e class com.android.mediaframeworktest.stress.Camera2StillCaptureTest#testTakePicture \
- *    -e repeat 200 \
+ *    -e iterations 200 \
  *    -e waitIntervalMs 1000 \
  *    -e resultToFile false \
  *    -r -w com.android.mediaframeworktest/.Camera2InstrumentationTestRunner
@@ -108,12 +108,12 @@
                 }
 
                 // Test iteration starts...
-                for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
-                    Log.v(TAG, String.format("Taking pictures: %d/%d", repeat + 1,
-                            getRepeatCount()));
+                for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+                    Log.v(TAG, String.format("Taking pictures: %d/%d", iteration + 1,
+                            getIterationCount()));
                     takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null,
                             /*afRegions*/null);
-                    getResultPrinter().printStatus(getRepeatCount(), repeat + 1, id);
+                    getResultPrinter().printStatus(getIterationCount(), iteration + 1, id);
                     Thread.sleep(getTestWaitIntervalMs());
                 }
             } finally {
@@ -144,11 +144,12 @@
                 }
 
                 // Test iteration starts...
-                for (int repeat = 0; repeat < getRepeatCount(); ++repeat) {
-                    Log.v(TAG, String.format("Taking full RAW pictures: %d/%d", repeat + 1,
-                            getRepeatCount()));
+                for (int iteration = 0; iteration < getIterationCount(); ++iteration) {
+                    Log.v(TAG, String.format("Taking full RAW pictures: %d/%d", iteration + 1,
+                            getIterationCount()));
                     fullRawCaptureTestByCamera();
-                    getResultPrinter().printStatus(getRepeatCount(), repeat + 1, mCameraIds[i]);
+                    getResultPrinter().printStatus(getIterationCount(), iteration + 1,
+                            mCameraIds[i]);
                     Thread.sleep(getTestWaitIntervalMs());
                 }
             } finally {
diff --git a/packages/BackupRestoreConfirmation/res/values-ro/strings.xml b/packages/BackupRestoreConfirmation/res/values-ro/strings.xml
index b5731f0918..c80617c 100644
--- a/packages/BackupRestoreConfirmation/res/values-ro/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ro/strings.xml
@@ -18,10 +18,10 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="backup_confirm_title" msgid="827563724209303345">"Copiere de rezervă completă"</string>
     <string name="restore_confirm_title" msgid="5469365809567486602">"Restabilire completă"</string>
-    <string name="backup_confirm_text" msgid="1878021282758896593">"S-a solicitat crearea unei copii de rezervă complete a tuturor datelor pe un computer desktop conectat. Doriți să permiteți acest lucru?\n\nDacă nu aţi solicitat dvs. copierea de rezervă, nu permiteți ca operațiunea să continue."</string>
+    <string name="backup_confirm_text" msgid="1878021282758896593">"S-a solicitat crearea unei copii de rezervă complete a tuturor datelor pe un computer desktop conectat. Doriți să permiteți acest lucru?\n\nDacă nu ați solicitat dvs. copierea de rezervă, nu permiteți ca operațiunea să continue."</string>
     <string name="allow_backup_button_label" msgid="4217228747769644068">"Creați copii de rezervă pentru datele dvs."</string>
     <string name="deny_backup_button_label" msgid="6009119115581097708">"Nu creați copii de rezervă"</string>
-    <string name="restore_confirm_text" msgid="7499866728030461776">"S-a solicitat o restabilire completă a tuturor datelor de pe un computer desktop conectat. Doriți să permiteți acest lucru?\n\nDacă nu dvs. aţi solicitat această restabilire, nu permiteți continuarea operațiunii. Acest proces va înlocui toate datele existente în prezent pe dispozitiv!"</string>
+    <string name="restore_confirm_text" msgid="7499866728030461776">"S-a solicitat o restabilire completă a tuturor datelor de pe un computer desktop conectat. Doriți să permiteți acest lucru?\n\nDacă nu dvs. ați solicitat această restabilire, nu permiteți continuarea operațiunii. Acest proces va înlocui toate datele existente în prezent pe dispozitiv!"</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"Restabiliţi datele dvs."</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"Nu restabiliţi"</string>
     <string name="current_password_text" msgid="8268189555578298067">"Introduceţi mai jos parola actuală pentru copia de rezervă:"</string>
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index fa9ff01..9ac929b 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -75,6 +75,19 @@
                 <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" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:mimeType="application/zip"
+                    android:host="com.android.providers.downloads.documents"
+                    android:scheme="content" />
+                <data android:mimeType="application/x-zip"
+                    android:host="com.android.providers.downloads.documents"
+                    android:scheme="content" />
+                <data android:mimeType="application/x-zip-compressed"
+                    android:host="com.android.providers.downloads.documents"
+                    android:scheme="content" />
+            </intent-filter>
         </activity>
 
         <activity
diff --git a/packages/DocumentsUI/lint.xml b/packages/DocumentsUI/lint.xml
new file mode 100644
index 0000000..09661ba
--- /dev/null
+++ b/packages/DocumentsUI/lint.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+    <!--
+        Lint configuration for the framework-lint tool (go/fwlint).  See
+        http://tools.android.com/tips/lint for full docs on the lint tool.
+    -->
+
+    <!-- min-sdk doesn't apply to platform apps. -->
+    <issue id="UsesMinSdkAttributes" severity="ignore" />
+
+    <!-- Protected permissions don't apply to system apps. -->
+    <issue id="ProtectedPermissions" severity="ignore" />
+
+    <!-- Other recommended suppressions copied from go/fwlint. -->
+    <issue id="Assert" severity="ignore" />
+    <issue id="ClickableViewAccessibility" severity="ignore" />
+    <issue id="GoogleAppIndexingWarning" severity="ignore" />
+    <issue id="MissingPermission" severity="ignore" />
+    <issue id="ParcelClassLoader" severity="ignore" />
+    <issue id="ParcelCreator" severity="ignore" />
+    <issue id="Registered" severity="ignore" />
+    <issue id="RtlHardcoded" severity="ignore" />
+    <issue id="ShiftFlags" severity="ignore" />
+    <issue id="SuspiciousImport" severity="ignore" />
+
+    <!-- Don't lint automatically translated strings. -->
+    <issue id="all">
+      <ignore path="res/values-*/strings.xml" />
+    </issue>
+
+    <!-- Don't warn about missing translations. -->
+    <issue id="MissingTranslation">
+      <ignore path="res/values/strings.xml" />
+    </issue>
+    
+</lint>
diff --git a/packages/DocumentsUI/res/animator-ldrtl/dir_down.xml b/packages/DocumentsUI/res/animator-ldrtl/dir_enter.xml
similarity index 100%
rename from packages/DocumentsUI/res/animator-ldrtl/dir_down.xml
rename to packages/DocumentsUI/res/animator-ldrtl/dir_enter.xml
diff --git a/packages/DocumentsUI/res/animator-ldrtl/dir_up.xml b/packages/DocumentsUI/res/animator-ldrtl/dir_leave.xml
similarity index 100%
rename from packages/DocumentsUI/res/animator-ldrtl/dir_up.xml
rename to packages/DocumentsUI/res/animator-ldrtl/dir_leave.xml
diff --git a/packages/DocumentsUI/res/animator/dir_down.xml b/packages/DocumentsUI/res/animator/dir_enter.xml
similarity index 100%
rename from packages/DocumentsUI/res/animator/dir_down.xml
rename to packages/DocumentsUI/res/animator/dir_enter.xml
diff --git a/packages/DocumentsUI/res/animator/dir_up.xml b/packages/DocumentsUI/res/animator/dir_leave.xml
similarity index 100%
rename from packages/DocumentsUI/res/animator/dir_up.xml
rename to packages/DocumentsUI/res/animator/dir_leave.xml
diff --git a/packages/DocumentsUI/res/drawable/cabinet.png b/packages/DocumentsUI/res/drawable/cabinet.png
deleted file mode 100644
index da44023..0000000
--- a/packages/DocumentsUI/res/drawable/cabinet.png
+++ /dev/null
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable/cabinet.xml b/packages/DocumentsUI/res/drawable/cabinet.xml
new file mode 100644
index 0000000..843ffc7
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/cabinet.xml
@@ -0,0 +1,81 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT 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="672dp"
+        android:height="921dp"
+        android:viewportWidth="672.0"
+        android:viewportHeight="921.0">
+    <path
+        android:pathData="M286,0c5,0,10,0,15,0c0.1,1.8,1.5,1.8,2.8,2.1c11.1,2,22.1,4,33.2,6.1c31.8,6.1,63.7,12.3,95.5,18.5  c16.1,3.1,32.1,6.2,48.2,9.3c26,4.9,52.1,9.3,78,14.6c10.8,2.2,21.6,4.6,32.3,6.5c11.3,2,22.6,4.7,34,6c7.9,0.9,7.9,1.1,7.9,9.2  c0,237.3,0,474.5,0,711.8c-1.5,0.9,-3,2,-4.6,2.8c-18.3,8.3,-36.6,16.6,-54.8,25c-29.3,13.4,-58.5,26.8,-87.8,40.3  c-23.5,10.9,-47,21.8,-70.4,32.8c-2.1,1,-4.2,1.5,-6.3,1.1c-6.8,-1.3,-13.6,-2.5,-20.1,-4.9c5.9,-0.3,11.4,1.9,17.1,2.9c5.9,1.1,5.9,1,5.9,-4.9  c0,-17.1,0.1,-34.3,0,-51.4c-0.3,-68.9,-0.7,-137.8,-1,-206.7c0,-35.8,0,-71.6,0.1,-107.4c0,-3.8,-0.6,-5.2,-4.7,-3.7c-7.9,2.9,-16,5.4,-24.1,7.8  c-14.1,4.3,-27.8,10,-42.2,13.2c0,-64,0,-127.9,-0.1,-191.9c0,-4.1,1.3,-5.9,5.1,-7c21,-6.6,42,-13.4,63,-20.2c2.3,-0.8,4.4,-1.8,4,-4.9  c0,-59.3,0,-118.7,0,-178c0,-1.3,-0.7,-2,-2,-2c-2.6,-0.4,-5.2,-0.7,-7.8,-1.2c-30.2,-5.3,-60.5,-10.6,-90.7,-16c-31.9,-5.6,-63.7,-11.3,-95.6,-16.9  c-24.9,-4.4,-49.8,-8.7,-74.6,-13.1C117.1,75.6,93.1,71.3,69,67c-0.3,-0.3,-0.7,-0.7,-1,-1c17.4,-5.3,34.8,-10.7,52.3,-15.9  c29.4,-8.7,58.8,-17.2,88.2,-25.8c24.3,-7.1,48.6,-14.2,72.9,-21.4C283.1,2.4,285.6,2.7,286,0z"
+        android:fillColor="#EFEFEE"/>
+    <path
+        android:pathData="M412,307c0.4,3,-1.7,4.1,-4,4.9c-21,6.8,-42,13.6,-63,20.2c-3.8,1.2,-5.1,3,-5.1,7C340,403.1,340,467,340,531  c-11.8,-1.2,-23.3,-4.5,-34.9,-6.5c-10,-1.7,-19.9,-4.6,-30.1,-5.5c-0.7,-0.3,-1.4,-0.9,-2.2,-1c-19.8,-4,-39.5,-8,-59.3,-12c-12.2,-2.4,-24.3,-4.7,-36.5,-7  c-0.9,-0.3,-1.8,-0.8,-2.8,-1c-24.5,-4.9,-48.9,-9.9,-73.5,-14.6C89.3,481.3,78,477.1,66,478c-0.7,-1.6,-2.1,-1.8,-3.6,-2.1  c-11.1,-2.2,-22.2,-4.7,-33.3,-6.7c-9.7,-1.7,-19.1,-4.9,-29.1,-5.3c0,-64.3,0,-128.7,0,-193c0.8,-0.2,1.6,-0.4,2.4,-0.7c19,-7.8,37.9,-15.9,57.1,-23.4  c5.4,-2.1,6.7,-4.8,6.6,-10.2c-0.2,-55.1,-0.1,-110.2,-0.1,-165.4c0,-1.9,-1.4,-4.6,1.9,-5.4c0.3,0.3,0.7,0.7,1,1c-1.3,4.9,-1,9.9,-1,14.9  c0,51.1,0,102.3,0,153.4c0,1.2,0,2.3,0,3.5c0.1,3.5,1.2,5.9,5.3,6.5c7,1.1,14,2.6,21,3.9c22.1,4.3,44.1,8.6,66.2,12.8  c27.3,5.2,54.6,10.1,81.9,15.3c21.8,4.1,43.5,8.5,65.2,12.6c28.1,5.4,56.2,10.8,84.3,15.8C398.4,306.8,405.1,310.5,412,307z   M105,329c0,3.3,0,6.7,-0.1,10c-0.1,2.5,0.4,3.6,3.4,4.2c30,5.3,59.9,10.9,89.8,16.5c3.4,0.6,5.1,0.2,4.9,-3.7  c-0.2,-3.3,-0.1,-6.7,-0.1,-10c0.5,-3.6,-0.1,-6.3,-4.7,-6.1c-1.1,0.1,-2.2,-0.6,-3.4,-0.8c-28.3,-5,-56.6,-9.9,-84.9,-14.9  C105.6,323.4,104.5,325.2,105,329z M65.9,280.8c13.7,2.5,27.4,4.9,41.1,7.4c32.6,5.9,65.2,11.8,97.8,17.8  c41.4,7.6,82.8,15.2,124.2,22.8c6.8,1.2,13.3,1.4,20,-1.3c9.3,-3.6,18.9,-6.3,28.4,-9.4c6.4,-2.1,12.8,-4.2,19.2,-6.4  c-4.2,-2,-8.3,-3,-12.4,-3.8c-22.6,-4.2,-45.3,-8,-67.9,-12.6c-14.6,-3,-29.2,-5.6,-43.8,-8.5c-24,-4.6,-48,-9.2,-72,-13.7c-15.9,-3,-31.8,-6.2,-47.8,-9.2  c-19,-3.6,-38,-7.3,-57,-10.6c-9.9,-1.7,-19.6,-4.5,-29.7,-5.2C48,255.6,30.1,263,12.2,270.4c0,0.4,0,0.7,0,1.1  C30.1,274.6,48,277.7,65.9,280.8z"
+        android:fillColor="#EAEAEA"/>
+    <path
+        android:pathData="M672,782c-6,0.9,-11.1,4.3,-16.4,6.9c-30.8,15,-61.5,30.3,-92.3,45.4c-34.8,17.1,-69.5,34.3,-104.5,51.1  c-13,6.3,-26,12.8,-39,19.1c-1.5,0.7,-3.7,1,-3.9,3.4c-3.7,0,-7.3,0,-11,0c-0.4,-3,-3.1,-2.3,-4.7,-2.7c-19.3,-4.8,-38.6,-9.5,-57.9,-14.1  c-27.5,-6.5,-55.2,-12.7,-82.6,-19.4c-30.9,-7.5,-61.8,-15,-92.7,-22.1c-24.8,-5.8,-49.5,-12,-74.3,-18C70.8,826.5,48.9,821.3,27,816  c-1.1,-0.3,-2.3,-0.5,-3.3,-1c-3.2,-1.3,-3.5,-3.3,-0.7,-5.4c0.9,-0.7,2,-1.2,3.1,-1.7c12,-5.3,24,-10.7,36,-16c0.4,-0.2,0.9,-0.2,1.9,-0.3  c0,3.6,0,7,0,10.5c0,1.6,-0.5,3.5,2,3.9c0.7,2.8,3.2,2.5,5.2,3c39.3,9,78.7,18.1,118.1,27c43.9,10,87.7,20,131.6,29.9  c9.7,2.2,19.2,4.9,29.1,6c1.1,1.5,2.6,0.9,4,1l0,0c4.1,2,8.5,2.6,13,3l0,0c7.2,2.4,14.4,4.3,22,5l0,0c6.5,2.5,13.3,3.6,20.1,4.9  c2.1,0.4,4.2,-0.1,6.3,-1.1c23.5,-11,46.9,-21.9,70.4,-32.8c29.2,-13.5,58.5,-26.9,87.8,-40.3c18.3,-8.4,36.6,-16.6,54.8,-25  c1.6,-0.7,3.1,-1.9,4.6,-2.8c2,-2.9,1.1,-6.2,0.9,-9.2c-0.3,-4.7,1.9,-5.5,5.7,-4.7c10.8,2.2,21.6,4.6,32.5,6.9C672,778.7,672,780.3,672,782z  "
+        android:fillColor="#E6E4E4"/>
+    <path
+        android:pathData="M350,872c-9.9,-1.1,-19.4,-3.9,-29.1,-6C277,856,233.1,846,189.2,836c-39.4,-9,-78.7,-18,-118.1,-27  c-2,-0.4,-4.5,-0.2,-5.2,-3c0,-85.7,0,-171.4,0.1,-257.1c6.5,0.1,12.7,2.3,19,3.6c26.4,5.4,52.8,10.9,79.2,16.5c25.9,5.4,51.8,11,77.7,16.4  c26.2,5.5,52.5,11,78.7,16.5c30.1,6.3,60.2,12.6,90.3,19c0.3,68.9,0.7,137.8,1,206.7c0.1,17.1,0,34.3,0,51.4c0,5.9,0,6,-5.9,4.9  c-5.7,-1.1,-11.2,-3.2,-17.1,-2.9c0,0,0,0,0,0c-7,-3.1,-14.2,-5.4,-22,-5c0,0,0,0,0,0c-3.9,-2.9,-8.4,-2.9,-13,-3c0,0,0,0,0,0  C352.9,871.5,351.4,872.1,350,872z M177,687c0,3.2,0.1,6.3,0,9.5c-0.1,2.7,0.7,4,3.8,4.6c29.7,5.8,59.3,11.7,89,17.7  c2.4,0.5,4.7,0.1,4.9,-2.6c0.4,-3.7,1.2,-7.6,-0.6,-11.2c1,-3,1.2,-5.3,-3,-6c-29.6,-5.4,-59.2,-10.8,-88.7,-16.5C177.7,681.6,176.5,682.8,177,687  z"
+        android:fillColor="#E5E5E5"/>
+    <path
+        android:pathData="M411,621c-30.1,-6.3,-60.2,-12.6,-90.3,-19c-26.2,-5.5,-52.5,-11,-78.7,-16.5c-25.9,-5.5,-51.8,-11,-77.7,-16.4  c-26.4,-5.5,-52.8,-11.1,-79.2,-16.5c-6.3,-1.3,-12.5,-3.5,-19,-3.6c0,-23.6,0,-47.3,0,-70.9c12,-0.9,23.2,3.3,34.7,5.5c24.5,4.6,49,9.7,73.5,14.6  c1,0.2,1.9,0.6,2.8,1c0,3.3,0.7,6.7,0.7,9.9c0,5.6,2.4,7.5,7.5,8.4c15.3,2.7,30.5,5.8,45.8,8.7c12,2.3,24,4.4,36.1,6.6  c1.9,0.3,4.8,1.5,4.7,-1.4c-0.2,-4.6,1.7,-8.2,3.3,-12.1c10.2,0.9,20,3.8,30.1,5.5c11.7,2,23.1,5.3,34.9,6.5  c14.5,-3.2,28.1,-8.9,42.2,-13.2c8.1,-2.5,16.2,-5,24.1,-7.8c4.1,-1.5,4.8,-0.1,4.7,3.7C411,549.4,411,585.2,411,621z"
+        android:fillColor="#D9D9D9"/>
+    <path
+        android:pathData="M412,307c-6.9,3.5,-13.6,-0.2,-20.1,-1.3c-28.2,-5,-56.2,-10.4,-84.3,-15.8c-21.8,-4.1,-43.5,-8.5,-65.2,-12.6  c-27.3,-5.2,-54.6,-10.1,-81.9,-15.3c-22.1,-4.2,-44.1,-8.5,-66.2,-12.8c-7,-1.3,-13.9,-2.9,-21,-3.9c-4.1,-0.6,-5.2,-3,-5.3,-6.5c0,-1.2,0,-2.3,0,-3.5  c0,-51.1,0,-102.3,0,-153.4c0,-5,-0.3,-10,1,-14.9c24.1,4.3,48.1,8.6,72.2,12.8c24.9,4.4,49.8,8.7,74.6,13.1c31.9,5.6,63.7,11.3,95.6,16.9  c30.2,5.3,60.5,10.6,90.7,16c2.6,0.5,5.2,0.8,7.8,1.2c0,1.3,0.7,2,2,2C412,188.3,412,247.7,412,307z M409,217.4c0,-25.5,0,-51,0,-76.5  c0,-10.9,0.1,-11.2,-10.7,-13.2c-23.4,-4.4,-46.8,-8.5,-70.3,-12.6c-24.1,-4.3,-48.2,-8.4,-72.3,-12.6c-17.7,-3.1,-35.5,-6.3,-53.2,-9.4  c-22.1,-3.9,-44.3,-7.6,-66.4,-11.5c-20,-3.5,-40,-7.1,-60.1,-10.5c-6,-1,-6.1,-0.8,-6.1,5.6c0,53,0,105.9,0,158.9c0,1,0,2,0,3  c0.2,2.6,1,4.1,4,4.6c10.1,1.7,20.1,3.9,30.2,5.8c27.3,5.1,54.6,10.1,81.9,15.2c22.1,4.2,44.1,8.6,66.2,12.8  c27.3,5.2,54.6,10.2,81.9,15.3c22.7,4.3,45.5,8.6,68.2,12.8c6.5,1.2,6.5,1.1,6.5,-5.7C409,272,409,244.7,409,217.4z"
+        android:fillColor="#E8E8E8"/>
+    <path
+        android:pathData="M412,129c-1.3,0,-2,-0.7,-2,-2C411.3,127,412,127.7,412,129z"
+        android:fillColor="#EAEAEA"/>
+    <path
+        android:pathData="M65.8,248.3c10.1,0.7,19.8,3.5,29.7,5.2c19,3.3,38,7,57,10.6c15.9,3,31.8,6.2,47.8,9.2  c24,4.6,48,9.1,72,13.7c14.6,2.8,29.3,5.5,43.8,8.5c22.5,4.6,45.3,8.4,67.9,12.6c4.1,0.8,8.2,1.8,12.4,3.8  c-6.4,2.1,-12.8,4.3,-19.2,6.4c-9.5,3.1,-19.1,5.8,-28.4,9.4c-6.7,2.6,-13.3,2.5,-20,1.3c-41.4,-7.6,-82.8,-15.2,-124.2,-22.8  c-32.6,-6,-65.2,-11.9,-97.8,-17.8c-13.7,-2.5,-27.4,-4.9,-41.1,-7.4C65.9,270,65.9,259.1,65.8,248.3z"
+        android:fillColor="#E6A3A3"/>
+    <path
+        android:pathData="M275,519c-1.5,3.9,-3.5,7.5,-3.3,12.1c0.1,2.9,-2.8,1.7,-4.7,1.4c-12,-2.2,-24.1,-4.3,-36.1,-6.6  c-15.3,-2.9,-30.5,-6,-45.8,-8.7c-5.1,-0.9,-7.5,-2.8,-7.5,-8.4c0,-3.2,-0.8,-6.5,-0.7,-9.9c12.2,2.3,24.4,4.6,36.5,7c19.8,3.9,39.5,8,59.3,12  C273.6,518.2,274.3,518.7,275,519z"
+        android:fillColor="#CBCBCA"/>
+    <path
+        android:pathData="M202.9,345.9c0,3.3,-0.1,6.7,0.1,10c0.2,3.9,-1.4,4.3,-4.9,3.7c-29.9,-5.6,-59.8,-11.2,-89.8,-16.5  c-3,-0.5,-3.5,-1.7,-3.4,-4.2c0.1,-3.3,0.1,-6.7,0.1,-10c21.7,3.9,43.4,7.9,65.2,11.6C181.1,342.4,191.8,345.3,202.9,345.9z"
+        android:fillColor="#CFCFCE"/>
+    <path
+        android:pathData="M65.8,248.3c0,10.9,0,21.7,0,32.6c-17.9,-3.1,-35.8,-6.2,-53.7,-9.3c0,-0.4,0,-0.7,0,-1.1  C30.1,263,48,255.6,65.8,248.3z"
+        android:fillColor="#E57474"/>
+    <path
+        android:pathData="M202.9,345.9c-11.1,-0.6,-21.8,-3.5,-32.6,-5.4c-21.8,-3.7,-43.5,-7.7,-65.2,-11.6c-0.6,-3.8,0.6,-5.6,4.8,-4.8  c28.3,5,56.6,9.9,84.9,14.9c1.1,0.2,2.3,0.8,3.4,0.8C202.8,339.6,203.4,342.3,202.9,345.9z"
+        android:fillColor="#BDBDBD"/>
+    <path
+        android:pathData="M367,876c7.8,-0.4,15,1.9,22,5C381.4,880.3,374.2,878.4,367,876z"
+        android:fillColor="#EFEFEE"/>
+    <path
+        android:pathData="M354,873c4.5,0.1,9.1,0.1,13,3C362.5,875.6,358.1,875,354,873z"
+        android:fillColor="#EFEFEE"/>
+    <path
+        android:pathData="M350,872c1.4,0.1,3,-0.5,4,1C352.6,872.9,351,873.5,350,872z"
+        android:fillColor="#EFEFEE"/>
+    <path
+        android:pathData="M274.1,705c1.9,3.6,1,7.5,0.6,11.2c-0.3,2.8,-2.5,3.1,-4.9,2.6c-29.7,-5.9,-59.3,-11.9,-89,-17.7  c-3.1,-0.6,-3.9,-1.9,-3.8,-4.6c0.1,-3.2,0,-6.3,0,-9.5c1.2,0,2.4,-0.1,3.5,0.1c19.2,3.8,38.4,7.7,57.6,11.4  C250.1,700.8,261.9,703.8,274.1,705z"
+        android:fillColor="#D6D6D5"/>
+    <path
+        android:pathData="M274.1,705c-12.1,-1.2,-24,-4.2,-35.9,-6.5c-19.2,-3.7,-38.4,-7.6,-57.6,-11.4c-1.1,-0.2,-2.3,-0.1,-3.5,-0.1  c-0.5,-4.2,0.7,-5.4,5.3,-4.5c29.5,5.7,59.1,11.1,88.7,16.5C275.3,699.7,275.1,702,274.1,705z"
+        android:fillColor="#C9C9C8"/>
+    <path
+        android:pathData="M409,217.4c0,27.3,0,54.6,0,82c0,6.8,0,6.9,-6.5,5.7c-22.7,-4.2,-45.5,-8.6,-68.2,-12.8  c-27.3,-5.1,-54.6,-10.1,-81.9,-15.3c-22.1,-4.2,-44.1,-8.6,-66.2,-12.8c-27.3,-5.2,-54.6,-10.1,-81.9,-15.2c-10.1,-1.9,-20.1,-4.1,-30.2,-5.8  c-3,-0.5,-3.9,-2.1,-4,-4.6c-0.1,-1,0,-2,0,-3c0,-53,0,-105.9,0,-158.9c0,-6.4,0,-6.6,6.1,-5.6c20,3.4,40,7,60.1,10.5c22.1,3.9,44.3,7.6,66.4,11.5  c17.7,3.1,35.5,6.3,53.2,9.4c24.1,4.2,48.2,8.4,72.3,12.6c23.4,4.1,46.9,8.2,70.3,12.6c10.8,2,10.7,2.3,10.7,13.2  C409,166.4,409,191.9,409,217.4z M283.9,146.9c0.4,-3.2,-0.2,-5.3,-4,-6c-29.7,-5,-59.4,-9.9,-89,-15.3c-4.8,-0.9,-5.2,0.7,-4.8,4.4  c0,3.5,-0.1,7,0,10.5c0,1.3,-0.4,3.2,1.4,3.3c2.9,0.1,5.3,1.8,8.1,2.3c13.8,2.4,27.6,4.9,41.4,7.4c13.3,2.4,26.5,5.1,39.8,7.4  c6.6,1.2,7.3,0.4,7.3,-6.5C284,151.9,283.9,149.4,283.9,146.9z"
+        android:fillColor="#E8E7E7"/>
+    <path
+        android:pathData="M283.9,146.9c0,2.5,0.1,5,0.1,7.5c0,6.9,-0.7,7.7,-7.3,6.5c-13.3,-2.4,-26.5,-5,-39.8,-7.4  c-13.8,-2.5,-27.6,-5.1,-41.4,-7.4c-2.8,-0.5,-5.2,-2.2,-8.1,-2.3c-1.8,-0.1,-1.4,-2,-1.4,-3.3c0,-3.5,0,-7,0,-10.5c1.9,0.3,3.9,0.7,5.8,1  c21.6,4,43.1,8.1,64.7,11.8C265.6,144.4,274.5,147.1,283.9,146.9z"
+        android:fillColor="#CFCFCE"/>
+    <path
+        android:pathData="M283.9,146.9c-9.3,0.2,-18.3,-2.5,-27.3,-4.1c-21.6,-3.7,-43.1,-7.8,-64.7,-11.8c-1.9,-0.4,-3.9,-0.7,-5.8,-1  c-0.4,-3.6,-0.1,-5.2,4.8,-4.4c29.6,5.4,59.3,10.4,89,15.3C283.7,141.6,284.3,143.7,283.9,146.9z"
+        android:fillColor="#BDBDBD"/>
+</vector>
diff --git a/packages/DocumentsUI/res/drawable/hourglass.xml b/packages/DocumentsUI/res/drawable/hourglass.xml
new file mode 100644
index 0000000..9b8d0e2
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/hourglass.xml
@@ -0,0 +1,168 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT 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="421dp"
+        android:height="909dp"
+        android:viewportWidth="421.0"
+        android:viewportHeight="909.0">
+    <path
+        android:pathData="M36,122.9c-2.8,-2.6,-5.7,-5.1,-8.3,-7.8c-5.6,-6,-9.2,-12.9,-8.8,-21.5c0.3,-7.5,0.6,-15,-0.1,-22.5   c-1.2,-14.1,5.5,-23.9,16,-31.9c16.7,-12.8,36.1,-19.6,56.1,-25.1c23.8,-6.5,48,-10.2,72.5,-12.3C168.6,1.3,174,2.2,179,0   c19.3,0,38.7,0,58,0c6,2.1,12.4,1.3,18.6,1.8c30.2,2.7,59.9,7.6,88.5,17.5c16.5,5.7,32.6,12.6,45.2,25.4c6.5,6.6,10.3,14,9.8,23.6   c-0.4,7.8,-0.5,15.7,0,23.4c0.6,10.3,-3.4,18.4,-10.6,25.2c-2.2,2,-4.4,4,-6.6,6c-3,2,-6.1,4,-9.1,5.9c-9.2,4.5,-18.5,9,-28.2,12.3   c-42.4,14.5,-86.3,18.8,-130.8,19.6c-10.9,0.2,-21.9,-0.4,-32.9,-0.7c-4.6,-0.4,-9.2,-0.8,-13.9,-1.1c-18.9,-1.1,-37.5,-3.9,-56,-7.6   c-15.3,-3.1,-30.2,-7.6,-44.9,-12.6c-7.6,-3.7,-15.3,-7.4,-22.9,-11.1C41.1,125.8,38.6,124.3,36,122.9z M41,72c2.9,6.9,7.1,12.6,13.1,17.2   c13,10,27.9,15.8,43.4,20.6c28.2,8.8,57.2,12.8,86.5,14c31.8,1.2,63.7,0.8,95.3,-4.6c25.3,-4.4,50.1,-10,72.9,-22.2   c10.8,-5.8,20,-13.1,24.7,-24.9c2.3,-11,-2.3,-19.5,-10.2,-26.4c-10.5,-9.2,-23.1,-14.9,-36.2,-19.6C295.2,13.4,258.4,9.7,221.2,8.1   c-11.1,-0.5,-22.2,0,-33.4,0.6c-21.4,1,-42.6,3.1,-63.6,7.3c-22.2,4.5,-44.1,10.3,-63.4,22.6C48.9,46.3,38.4,55.4,41,72z"
+        android:fillColor="#9F9F9F"/>
+    <path
+        android:pathData="M0,829c3.7,-2.8,4.7,-7.6,7.8,-10.9c2.6,-2.8,4.9,-5.7,9.2,-7.6c0,3.4,-0.1,6.5,0,9.5c0,1.5,-0.7,3.5,1.7,4   c0.4,3.3,1.4,6.4,2.9,9.4c3.8,7.7,10,13,16.8,17.9c9.2,6.7,19.7,10.8,29.8,15.5c-0.7,2.4,1.3,0.7,1.8,1.1l0,0c1.5,2.1,3.7,2.2,6,2   l0,0c0.8,0.6,1.5,1.4,2.4,1.7c9.5,2.7,18.9,5.8,28.7,7.4c3.6,0.6,7,3.5,10.9,1.1c2.4,0.4,4.8,0.8,7.1,1.2c0.2,1.5,1.3,1.6,2.5,1.8   c6.6,0.9,13.3,2.4,19.9,2.8c5.1,0.3,10.3,2.9,15.4,0.3c0.4,0,0.8,0.1,1.1,0.1c0.3,2.2,2.1,1.8,3.5,1.8c3.8,0,7.6,0,11.5,0   c1.1,1.4,2.7,1,4.1,1c17.2,0,34.5,0,51.7,0c1.4,0,3,0.4,4.1,-1c3.8,0,7.6,0,11.5,0c1.4,0,3.2,0.4,3.5,-1.8c9.4,-1,18.7,-2.1,28.1,-3.1   c6,1.3,11.6,0.4,16.9,-2.8c21.2,-4.2,42.1,-9.3,61.8,-18.4c15.8,-7.3,30.8,-15.8,38,-33.1c2.4,-2,1.9,-4.8,2.2,-7.4c0.3,-3,0,-6,0.1,-9   c0,-1,-0.3,-2.1,0.7,-2.7c1.1,-0.7,1.7,0.5,2.5,1c7.2,5,12.1,11.7,14.8,20c0.4,1.2,0.6,2.2,2.1,2.3c0,3.3,0,6.7,0,10   c-1.5,0,-1.8,1.1,-2.2,2.2c-3.8,10.2,-11.2,17.5,-20.1,23.3c-20.8,13.6,-44.1,21.2,-68.1,26.7c-29.2,6.7,-58.7,11,-88.7,11.7   c-1.6,0,-3.5,-0.5,-3.9,2c-18.7,0,-37.3,0,-56,0c-0.3,-2.5,-2.3,-1.9,-3.9,-2c-5.6,-0.1,-11.2,-0.5,-16.9,-0.8c-18.5,-1.2,-36.8,-3.8,-55,-7.3   C79.9,893.9,54,887,30.2,874C19,867.9,8.5,860.9,2.5,849C2,848,1.4,847,0,847C0,841,0,835,0,829z"
+        android:fillColor="#E6E4E4"/>
+    <path
+        android:pathData="M372.9,128.9c3,-2,6.1,-4,9.1,-5.9c-0.2,2.7,0.2,5.4,1,8c-1.5,1.6,-0.3,1.8,1,2c0.3,1,0.7,2,1,3   c-1.5,1.6,-0.3,1.8,1,2c0.7,2,1.3,4,2,6c-1.5,1.6,-0.3,1.8,1,2c0.3,1.7,0.7,3.3,1,5c-1,2.3,-0.6,4.1,2,5c4.9,23.8,9,47.6,8,72   c-3.5,1.5,-2.1,3.8,-1,6c-1,6,-2,12,-3,18c-1.3,1,-1.3,2,0,3c0,0.7,0,1.3,0,2c-2.1,0.4,-2.6,1.3,-1,3c0,0.3,0,0.7,0,1   c-1.3,0.2,-2.5,0.4,-1,2c0.4,2.1,-0.7,4,-1,6c-1.3,0.2,-2.5,0.4,-1,2c-3.7,9.3,-7.3,18.7,-11,28c-2.7,1.2,-4.2,2.9,-3,6   c-3.4,6.9,-7.8,13.3,-12.2,19.5c-6.1,8.6,-12.4,17.3,-19.4,25.2c-7.3,8.3,-15.5,15.8,-23.9,23c-11.9,10.3,-24.9,19.3,-38.1,27.7   c-12.2,7.8,-25.4,14.1,-38.4,20.5c-12.1,6,-18.5,15.8,-21,28.6c-1.5,7.8,-0.5,15.4,2,22.8c1.2,3.5,3.7,6.1,5.6,9.2   c5.4,8.6,14.8,10.5,22.6,15c15.3,9,30.8,17.7,45.3,28.1c14.4,10.4,28.2,21.5,40.5,34.1c10.1,10.4,18.5,22.2,26.8,34.3   c6.5,9.5,11.3,19.6,16.1,29.8c-1.5,1.6,-0.3,1.8,1,2c0.7,2,1.3,4,2,6c-1,2.3,-0.6,4.1,2,5c0.7,1.2,1.2,2.5,1,4c-1,2.3,-0.6,4.1,2,5   c1.2,12.3,4.6,24.1,5.7,36.5c0.8,8.4,1.4,16.8,1,25.1c-0.3,5.9,-1.1,12,-1.9,18c-1.2,8.7,-2.3,17.4,-4.2,25.9   c-1.5,6.6,-3.7,13.1,-5.6,19.6c-1.8,3.1,-2.9,6.5,-3.9,9.9c-3.4,6.4,-5.6,13.6,-11.9,18.2c-0.1,-3.8,1.6,-7.1,3,-10.4   c8.7,-20.9,13,-42.8,14.7,-65.1c1,-12.9,0.2,-25.8,-1.7,-38.7c-2.7,-18.5,-7.8,-36.2,-15.8,-53.1c-7.3,-15.4,-16.8,-29.3,-27.7,-42.4   c-2.7,-3.2,-6.3,-5.7,-9.6,-8.6c0.4,0.8,0.7,1.4,1,1.9c0.7,1.1,1.5,2.2,2.3,3.3c16.5,21.5,28.5,45.2,34.2,71.7c0.7,3.3,3.1,6.9,0.3,10.4   c-1,-1.9,-2.1,-3.7,-3.1,-5.6c-3.3,-6.3,-6.1,-12.9,-11.7,-17.6c-0.4,-0.9,-0.8,-1.8,-1.3,-2.6c-4,-6.3,-10.4,-10.4,-14.8,-16.2c0,-5.4,-2.7,-9.9,-4.8,-14.5   c-8.4,-18.6,-20.4,-34.9,-32.9,-50.8c-8.4,-10.8,-15.5,-22.8,-28.7,-28.8c-5.3,-2.4,-10,-6,-15.1,-8.6c-5.1,-2.6,-9.9,-6.4,-16.3,-5.2   c-5.2,1,-10.4,2.1,-15.3,4.1c-29.3,11.9,-48.4,34.1,-61.8,61.9c-0.3,0.3,-0.7,0.6,-1,1c-7.1,0.8,-13.9,2.9,-20.7,5.1   c-32.6,10.6,-61,27.4,-82.3,54.9c-9.2,11.6,-15.4,24.7,-18.9,39c-1.5,-1.1,-1.1,-2.7,-1.1,-4.1c-0.1,-9.6,0.3,-19.2,1.8,-28.7   c3.7,-22.6,11.8,-43.5,24,-62.8c12.6,-20,28.6,-36.9,47,-51.7c21.3,-17.3,44.6,-31.3,69.3,-42.9c14.5,-6.8,20,-18.8,21.8,-33.1   c1.8,-13.3,-4.9,-24.1,-12.2,-34.4c-3.6,-5,-7.4,-9.8,-13.2,-12.5c-5.8,-2.8,-11.6,-5.7,-17.4,-8.7c-22,-11.6,-42.6,-25.1,-61.1,-41.7   c-20.7,-18.6,-37.9,-40,-48.8,-65.9c-6.7,-15.7,-10.9,-32.1,-12,-49c-1.8,-27.1,2.1,-53.6,11.7,-79.1c3.8,-10.1,7.1,-20.4,13.3,-29.4   c14.7,5,29.6,9.5,44.9,12.6c18.5,3.7,37.2,6.5,56,7.6c4.6,0.3,9.3,0.7,13.9,1.1c0.2,3.6,-1.5,6.8,-2.6,10   c-11.9,33.6,-17.8,68.2,-17.2,103.8c0.2,9.7,1.3,19.4,2.7,29.1c3.8,24.6,11.4,47.7,26,68.1c12.2,17.1,28.4,28.6,49,33.4   c4.7,1.1,9.5,2.2,14.5,-0.5c18.7,-10.2,36.8,-21.2,53.7,-34.2c15.4,-11.9,29.4,-25.3,41.5,-40.5c12.9,-16.2,23.4,-33.8,30.4,-53.4   c6.4,-17.6,10.3,-35.6,10.9,-54.3c0.5,-15.9,0.2,-31.9,-3,-47.6C383.8,158.7,380.1,143.3,372.9,128.9z"
+        android:fillColor="#EDECEC"/>
+    <path
+        android:pathData="M383,780c1.1,-3.4,2.1,-6.8,3.9,-9.9c7.8,7.1,12.8,15.2,12.2,26.4c-0.6,10.7,-0.3,21.5,-0.5,32.3   c-7.2,17.3,-22.2,25.8,-38,33.1c-19.7,9.1,-40.6,14.1,-61.8,18.4c-5.6,0.9,-11.3,1.9,-16.9,2.8c-9.4,1,-18.7,2.1,-28.1,3.1   c-5,0.3,-9.9,0.7,-14.9,1c-20,1.2,-40,0.9,-60,0c-5,-0.3,-9.9,-0.7,-14.9,-1c-0.4,0,-0.8,-0.1,-1.1,-0.1c-12.6,-1.6,-25.2,-3.2,-37.9,-4.8   c-2.4,-0.4,-4.8,-0.8,-7.1,-1.2c-2.6,-0.6,-5.1,-1.3,-7.7,-1.8c-11.6,-2,-22.6,-6.3,-34.2,-8.4c0,0,0,0,0,0c-1.7,-1.6,-3.7,-2.2,-6,-2c0,0,0,0,0,0   c-0.2,-1,-1.1,-0.9,-1.8,-1.1c-10.2,-4.7,-20.6,-8.8,-29.8,-15.5c-6.8,-4.9,-13,-10.2,-16.8,-17.9c-1.5,-3,-2.4,-6.1,-2.9,-9.4   c0.1,-10.3,0,-20.6,0.2,-30.9c0.1,-8.3,3.5,-15,10,-20.2c2,3.5,3.4,7.1,4.1,11c-1.1,0.8,-1,2,-1.1,3.1c-0.6,8.2,2.9,14.9,8.3,20.6   c8.9,9.6,20.4,15.4,32.3,20.2c17.9,7.2,36.5,11.9,55.4,15.4c20.1,3.7,40.3,5.7,60.6,6.5c21.4,0.8,42.8,0.4,64.2,-1.6   c19.8,-1.9,39.4,-4.6,58.7,-9.3c19.9,-4.8,39.3,-11.2,56.4,-22.9c7.8,-5.3,15.2,-11.3,17.4,-21C386.4,790.1,388.3,784.3,383,780z"
+        android:fillColor="#9F9F9F"/>
+    <path
+        android:pathData="M378,305c-1.2,-3.1,0.3,-4.8,3,-6C380.6,301.3,379.7,303.3,378,305z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M399,234c-1.1,-2.2,-2.5,-4.5,1,-6C399.7,230,400.8,232.2,399,234z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M392,156c-2.6,-0.9,-3,-2.7,-2,-5C391.4,152.4,391.6,154.2,392,156z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M389,636c-2.6,-0.9,-3,-2.7,-2,-5C388.4,632.4,388.6,634.2,389,636z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M392,645c-2.6,-0.9,-3,-2.7,-2,-5C391.4,641.4,391.6,643.2,392,645z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M396,255c-1.3,-1,-1.3,-2,0,-3C397.3,253,397.3,254,396,255z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M395,260c-1.6,-1.7,-1.1,-2.6,1,-3C395.7,258,395.3,259,395,260z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M384,133c-1.3,-0.2,-2.5,-0.4,-1,-2C383.8,131.4,384,132.2,384,133z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M385,625c-1.3,-0.2,-2.5,-0.4,-1,-2C384.8,623.4,385,624.2,385,625z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M392,271c-1.5,-1.6,-0.3,-1.8,1,-2C393,269.8,392.8,270.6,392,271z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M394,263c-1.5,-1.6,-0.3,-1.8,1,-2C395,261.8,394.8,262.6,394,263z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M386,138c-1.3,-0.2,-2.5,-0.4,-1,-2C385.8,136.4,386,137.2,386,138z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M389,146c-1.3,-0.2,-2.5,-0.4,-1,-2C388.8,144.4,389,145.2,389,146z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M33.1,783.9c-0.8,-3.9,-2.2,-7.6,-4.1,-11c-3.7,-11.7,-7.2,-23.5,-9.2,-35.5c-1.3,-7.6,-1.9,-15.4,-2.7,-23.2   c-0.6,-6.2,-0.9,-12.4,-1,-18.5c-0.2,-7.9,1.9,-15.7,2.3,-23.4c0.5,-10.1,2.9,-19.5,5.5,-29c6.3,-23.1,17.3,-43.9,31.5,-62.8   c23.4,-31.1,53.3,-54.7,86.9,-74.1c10.1,-5.8,20.3,-11.6,30.9,-16.2c11.7,-5.2,16.3,-14.9,18.8,-26.3c3.2,-14.9,-2.8,-26.6,-12.7,-37.1   c-1.8,-1.9,-3.9,-3.1,-6.2,-4.2c-23.7,-11.4,-46.4,-24.4,-67.2,-40.7c-16.2,-12.6,-31.3,-26.5,-44.2,-42.6c-16.2,-20.3,-28.8,-42.5,-36.2,-67.5   c-3.1,-10.6,-5.4,-21.3,-6.2,-32.4c-0.7,-9.6,-3.2,-19.3,-2,-28.8c0.8,-6.6,1.5,-13.4,1.9,-20c1,-15.2,4.9,-29.6,9.2,-44c1.7,-5.7,4,-11.3,6.4,-16.8   c0.9,-2.2,1.3,-4.4,1.3,-6.8c2.6,1.4,5.1,2.9,7.2,4.9c-0.6,0.8,-1.4,1.4,-1.8,2.3c-11.2,26.2,-16.2,53.8,-17.4,82.2   c-0.4,8.8,1,17.5,1.9,26.2c2,19.7,7.4,38.4,15.6,56.3c17.9,39.2,46.6,69.1,81.3,93.6c18.5,13.1,38.1,24.3,58.5,34.1   c3.3,1.6,6,3.7,8.1,6.5c8,10.6,12.6,22.1,9.6,35.7c-2.1,9.4,-6.5,17.9,-14.8,22.7c-8.2,4.7,-16.9,8.5,-25.3,12.9   c-22.5,12,-43.8,25.8,-62.6,43c-21.9,19.9,-40.8,42.1,-53.7,69.2C26.3,646.5,20.6,682,24.1,719c1.8,18.7,7,36.7,12.7,54.6   c5.9,18.7,18.2,30.9,35.3,38.9c15.4,7.2,31.5,12.2,48.1,15.8c1.6,0.4,4.3,-0.3,4.8,2.6c-18,-2.8,-35.4,-7.5,-52.3,-14.5   c-12.2,-5.1,-23.4,-11.4,-32.4,-21.4C37.2,791.7,36.5,787,33.1,783.9z"
+        android:fillColor="#EDECEC"/>
+    <path
+        android:pathData="M372.9,128.9c7.2,14.3,10.9,29.8,14.1,45.4c3.2,15.7,3.5,31.6,3,47.6c-0.6,18.7,-4.6,36.7,-10.9,54.3   c-7.1,19.6,-17.6,37.2,-30.4,53.4c-12.1,15.2,-26.1,28.6,-41.5,40.5c-16.9,13,-35,24,-53.7,34.2c-5,2.7,-9.8,1.6,-14.5,0.5   c-20.6,-4.8,-36.8,-16.3,-49,-33.4c-14.6,-20.4,-22.3,-43.5,-26,-68.1c-1.5,-9.7,-2.6,-19.4,-2.7,-29.1c-0.6,-35.6,5.4,-70.2,17.2,-103.8   c1.2,-3.3,2.8,-6.4,2.6,-10c11,0.2,21.9,0.9,32.9,0.7c44.4,-0.8,88.4,-5.2,130.8,-19.6C354.4,137.9,363.7,133.5,372.9,128.9z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M377,72c-4.6,11.9,-13.9,19.1,-24.7,24.9c-22.9,12.2,-47.6,17.9,-72.9,22.2c-31.6,5.4,-63.5,5.9,-95.3,4.6   c-29.3,-1.1,-58.3,-5.1,-86.5,-14C82.1,105,67.2,99.1,54.2,89.2C48.2,84.6,43.9,78.8,41,72c3.9,-1.8,4.6,-6.2,7.3,-9   c10.3,-10.5,22.9,-16.9,36.5,-21.8c19.7,-7.1,40,-11.5,60.7,-14.5c19.4,-2.8,38.9,-3.9,58.4,-4.5c17.9,-0.6,35.8,0.8,53.6,2.8   c15,1.6,29.9,3.5,44.5,7.1c20,4.9,39.7,10.7,57.2,22.1C366.5,58.8,371.5,65.5,377,72z"
+        android:fillColor="#8D8E8E"/>
+    <path
+        android:pathData="M125,831c-0.4,-2.9,-3.2,-2.3,-4.8,-2.6c-16.6,-3.7,-32.7,-8.7,-48.1,-15.8c-17.1,-8,-29.4,-20.2,-35.3,-38.9   c-5.7,-17.9,-10.9,-35.9,-12.7,-54.6c-3.6,-37.1,2.1,-72.5,18.4,-106.4c13,-27.1,31.9,-49.3,53.7,-69.2c18.8,-17.1,40.2,-30.9,62.6,-43   c8.4,-4.5,17.1,-8.2,25.3,-12.9c8.4,-4.8,12.7,-13.3,14.8,-22.7c3.1,-13.6,-1.6,-25.1,-9.6,-35.7c-2.1,-2.8,-4.8,-4.9,-8.1,-6.5   c-20.4,-9.9,-40,-21.1,-58.5,-34.1c-34.7,-24.6,-63.4,-54.5,-81.3,-93.6c-8.2,-17.9,-13.6,-36.6,-15.6,-56.3c-0.9,-8.7,-2.3,-17.5,-1.9,-26.2   c1.2,-28.3,6.2,-55.9,17.4,-82.2c0.4,-0.9,1.2,-1.5,1.8,-2.3c7.6,3.7,15.3,7.4,22.9,11.1c-6.2,9,-9.5,19.3,-13.3,29.4   c-9.6,25.5,-13.5,52,-11.7,79.1c1.1,16.9,5.4,33.3,12,49c11,25.9,28.1,47.4,48.8,65.9c18.5,16.6,39.1,30.2,61.1,41.7   c5.7,3,11.5,5.9,17.4,8.7c5.8,2.8,9.7,7.6,13.2,12.5c7.3,10.3,14,21.1,12.2,34.4c-1.9,14.3,-7.4,26.3,-21.8,33.1   c-24.7,11.6,-48,25.7,-69.3,42.9c-18.3,14.9,-34.3,31.7,-47,51.7c-12.2,19.3,-20.3,40.2,-24,62.8c-1.6,9.6,-2,19.1,-1.8,28.7   c0,1.4,-0.4,3.1,1.1,4.1c-0.6,14.9,0.1,29.8,3,44.5c4.2,21.4,9.1,42.6,26,58.4c-0.2,2.3,0.9,4.1,2.2,5.9c8.8,12.3,22,18.6,35.3,24.1   c26.4,10.9,54.2,16.1,82.4,19.1c1.7,0.2,3,0.4,3,2.4c-4.5,0.7,-9,0.9,-13.4,0.5c-13.2,-1,-26.5,-1.9,-39.6,-4.1c-0.6,-2.4,-1.7,-2.3,-3.1,-0.6   c-1.3,-0.1,-2.6,-0.3,-3.9,-0.4c-0.6,-2.3,-1.6,-2.4,-3.1,-0.7c-0.6,-0.1,-1.3,-0.2,-1.9,-0.3c-0.6,-2.4,-1.7,-2.4,-3.1,-0.6   C126.2,831.2,125.6,831.1,125,831z"
+        android:fillColor="#E8E8E7"/>
+    <path
+        android:pathData="M377,72c-5.4,-6.4,-10.5,-13.2,-17.7,-17.9C341.7,42.7,322.1,36.9,302,32c-14.6,-3.6,-29.5,-5.5,-44.5,-7.1   c-17.8,-1.9,-35.7,-3.3,-53.6,-2.8c-19.5,0.6,-39,1.7,-58.4,4.5c-20.7,3,-41,7.4,-60.7,14.5C71.3,46.1,58.7,52.4,48.4,63   c-2.7,2.8,-3.5,7.2,-7.3,9c-2.6,-16.6,7.9,-25.6,19.8,-33.3c19.3,-12.3,41.2,-18.2,63.4,-22.6c21,-4.2,42.2,-6.3,63.6,-7.3   c11.1,-0.5,22.3,-1,33.4,-0.6c37.2,1.5,74,5.3,109.4,17.9c13.1,4.6,25.6,10.4,36.2,19.6C374.7,52.5,379.3,61,377,72z"
+        android:fillColor="#808080"/>
+    <path
+        android:pathData="M179,887.2c20,0.9,40,1.2,60,0c0,0.3,0,0.5,0,0.8c-1.1,1.4,-2.7,1,-4.1,1c-17.2,0,-34.5,0,-51.7,0   c-1.4,0,-3,0.4,-4.1,-1C179,887.7,179,887.5,179,887.2z"
+        android:fillColor="#F4F3F2"/>
+    <path
+        android:pathData="M76,869.9c11.6,2.2,22.6,6.5,34.2,8.4c2.6,0.4,5.2,1.2,7.7,1.8c-3.9,2.3,-7.3,-0.6,-10.9,-1.1   c-9.8,-1.6,-19.2,-4.7,-28.7,-7.4C77.5,871.3,76.8,870.5,76,869.9z"
+        android:fillColor="#F4F3F2"/>
+    <path
+        android:pathData="M125.1,881.3c12.6,1.6,25.2,3.2,37.9,4.8c-5.2,2.6,-10.3,0,-15.4,-0.3c-6.7,-0.4,-13.3,-1.9,-19.9,-2.8   C126.3,882.9,125.2,882.8,125.1,881.3z"
+        android:fillColor="#F4F3F2"/>
+    <path
+        android:pathData="M282,883.1c5.6,-0.9,11.3,-1.9,16.9,-2.8C293.7,883.4,288.1,884.4,282,883.1z"
+        android:fillColor="#F4F3F2"/>
+    <path
+        android:pathData="M179,887.2c0,0.3,0,0.5,0,0.8c-3.8,0,-7.6,0,-11.5,0c-1.4,0,-3.2,0.4,-3.5,-1.8C169,886.5,174,886.9,179,887.2z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M239,888c0,-0.3,0,-0.5,0,-0.8c5,-0.3,9.9,-0.7,14.9,-1c-0.3,2.2,-2.1,1.8,-3.5,1.8C246.6,888,242.8,888,239,888z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M70,867.9c2.3,-0.2,4.3,0.4,6,2C73.8,870.1,71.6,870,70,867.9z"
+        android:fillColor="#F4F3F2"/>
+    <path
+        android:pathData="M68.2,866.8c0.7,0.2,1.6,0.2,1.8,1.1C69.5,867.4,67.6,869.2,68.2,866.8z"
+        android:fillColor="#F4F3F2"/>
+    <path
+        android:pathData="M165,584c0.3,-0.3,0.7,-0.6,1,-1c10.5,-1.3,21,-3.3,31.5,-3.8c20.8,-1.1,41.4,0.7,61.7,5.4   c30.5,7,57.8,20.3,81.8,40.5c4.4,5.9,10.8,10,14.8,16.2c0.5,0.8,0.9,1.7,1.3,2.6c-2.4,4.1,-4.7,8.1,-7.1,12.2c-4,3.7,-6.3,8.9,-11,12   c-1.6,-0.1,-2.8,0.5,-4.1,1.5c-12.6,9.3,-26.7,15.6,-41.5,20.1c-31,9.4,-62.6,13.3,-95.1,11.6c-12.3,-0.6,-24.5,-1.5,-36.5,-3.4   c-4.5,-0.7,-5.3,0.5,-4.8,4.2c-0.5,0,-1,0.1,-1.5,0c-17.8,-3.9,-34.7,-10.3,-50.9,-18.7c-1,-0.5,-1.6,-1.1,-1.6,-2.3c2.3,-0.3,4.1,1.1,6.1,2   c14.2,6.2,28.9,10.6,44.1,13.3c2.5,0.4,3,0.2,2.4,-2.3c-2.5,-9.3,-3.7,-18.7,-4.8,-28.3c-1.5,-13.7,-0.3,-27.1,1.7,-40.5   C154.6,610.8,159.7,597.4,165,584z"
+        android:fillColor="#E57474"/>
+    <path
+        android:pathData="M103,681c0.1,1.1,0.7,1.8,1.6,2.3c16.2,8.4,33.1,14.8,50.9,18.7c0.5,0.1,1,0,1.5,0c0.6,0.4,1.3,0.7,1.9,1.1   c-0.1,2.7,1,5.2,1.9,7.6c6.5,17.8,16.5,33.6,27.5,48.8c12.5,17.1,27.1,32.1,45.1,43.6c6.6,4.2,13.7,7.3,20.5,11   c-15.6,2.8,-31.4,2.5,-47.1,2.4c-9.9,0,-19.9,-0.2,-29.8,-1.1c-18.2,-1.6,-36.2,-3.9,-54,-8.3c-18.1,-4.4,-35.9,-9.5,-51,-21.1   c-16.9,-15.8,-21.8,-37,-26,-58.4c-2.9,-14.7,-3.6,-29.6,-3,-44.5c3.5,-14.4,9.7,-27.4,18.9,-39c3.4,4.8,6.2,10.1,10.3,14.2   c6,6.1,11.6,13,19.7,16.8c0.5,0.8,1.2,1,2.1,1c0,0,0,0,0,0c0.3,0.3,0.7,0.7,1,1c0,0,0,0,0,0c0.3,0.3,0.7,0.7,1,1l0,0   c1,1.3,2.4,1.8,4,2l0,0C100.7,681.2,101.9,681,103,681L103,681z"
+        android:fillColor="#E6A3A3"/>
+    <path
+        android:pathData="M341,625c-24,-20.1,-51.3,-33.5,-81.8,-40.5c-20.3,-4.7,-41,-6.5,-61.7,-5.4c-10.5,0.6,-21,2.5,-31.5,3.8   c13.4,-27.8,32.5,-49.9,61.8,-61.9c4.9,-2,10.1,-3.1,15.3,-4.1c6.3,-1.2,11.2,2.6,16.3,5.2c5.2,2.6,9.9,6.2,15.1,8.6   c13.3,6,20.3,18,28.7,28.8c12.5,16,24.6,32.2,32.9,50.8C338.3,615.2,341,619.7,341,625z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M91.9,675c-8,-3.8,-13.6,-10.7,-19.7,-16.8c-4.1,-4.1,-6.9,-9.4,-10.3,-14.2c21.3,-27.5,49.8,-44.3,82.3,-54.9   c6.8,-2.2,13.6,-4.3,20.7,-5.1c-5.3,13.4,-10.4,26.9,-12.5,41.2c-2,13.4,-3.2,26.8,-1.7,40.5c1.1,9.6,2.3,19,4.8,28.3   c0.7,2.5,0.1,2.7,-2.4,2.3c-15.2,-2.6,-29.9,-7.1,-44.1,-13.3c-2,-0.9,-3.7,-2.3,-6.1,-2c0,0,0,0,0,0c-0.7,-1.2,-1.9,-1,-3,-1c0,0,0,0,0,0   c-0.3,-2.7,-2.4,-1.8,-4,-2c0,0,0,0,0,0c-0.3,-0.3,-0.7,-0.7,-1,-1c0,0,0,0,0,0c-0.3,-0.3,-0.7,-0.7,-1,-1c0,0,0,0,0,0   C93.6,675.2,92.8,675,91.9,675z"
+        android:fillColor="#D86868"/>
+    <path
+        android:pathData="M135,832.8c1.3,0.1,2.6,0.3,3.9,0.4c0.9,0.8,2,0.7,3.1,0.6c13.1,2.2,26.4,3,39.6,4.1   c4.5,0.3,9,0.2,13.4,-0.5c3.1,0.3,6.3,0.7,9.4,0.8c22.6,0.4,45.2,-0.9,67.6,-4.1c23.9,-3.3,47.4,-8.2,69.8,-17.6   c10.7,-4.5,21.4,-9.3,29.3,-18.3l0,0.1c6.2,-4.6,8.5,-11.8,11.9,-18.2c5.2,4.3,3.3,10.1,2.2,15c-2.2,9.7,-9.6,15.7,-17.4,21   c-17.1,11.7,-36.5,18.1,-56.4,22.9c-19.3,4.7,-38.9,7.4,-58.7,9.3c-21.4,2,-42.8,2.5,-64.2,1.6c-20.3,-0.8,-40.5,-2.8,-60.6,-6.5   c-19,-3.5,-37.6,-8.2,-55.4,-15.4c-11.9,-4.8,-23.4,-10.6,-32.3,-20.2c-5.3,-5.8,-8.9,-12.4,-8.3,-20.6c0.1,-1.2,0,-2.4,1.1,-3.1   c3.3,3.1,4.1,7.8,7.2,11.1c9,9.9,20.2,16.3,32.4,21.4c16.8,7,34.3,11.7,52.3,14.5c0.6,0.1,1.2,0.2,1.9,0.3c0.9,0.8,2,0.7,3.1,0.6   c0.6,0.1,1.3,0.2,1.9,0.3C132.8,833,133.9,833,135,832.8z"
+        android:fillColor="#999899"/>
+    <path
+        android:pathData="M371.9,667c2.8,-3.5,0.4,-7.1,-0.3,-10.4c-5.7,-26.6,-17.7,-50.3,-34.2,-71.7c-0.8,-1,-1.5,-2.2,-2.3,-3.3   c-0.3,-0.5,-0.6,-1.1,-1,-1.9c3.4,3,6.9,5.4,9.6,8.6c10.8,13.1,20.4,27,27.7,42.4c8,16.9,13.1,34.6,15.8,53.1   c1.9,12.9,2.6,25.8,1.7,38.7c-1.7,22.4,-6,44.3,-14.7,65.1c-1.4,3.3,-3.1,6.6,-3,10.4c0,0,0,-0.1,0,-0.1c-1.8,-0.3,-3.3,0.4,-4.7,1.2   c-6.3,3.7,-12.6,7.3,-19.4,10.2c-24,10.3,-48.8,14.5,-74.7,9.2c-4.2,-0.9,-9.4,-0.2,-12.4,-4.8c13.8,-2,27.6,-4.4,41.1,-8   c10,-2.7,20,-5.4,29,-10.8c1.5,-0.5,3.2,-0.9,4.6,-1.6c10.6,-5.1,19.5,-12.1,25.3,-22.6c4.7,-3.1,8.2,-10.7,6.9,-15c0.3,-1.4,0.6,-2.9,1,-4.3   c5.4,-16.2,7.5,-33.1,9,-50C378,689.7,375.5,678.3,371.9,667z"
+        android:fillColor="#F1F0F0"/>
+    <path
+        android:pathData="M371.9,667c3.6,11.3,6.1,22.7,5.1,34.6c-1.5,16.9,-3.6,33.8,-9,50c-0.5,1.4,-0.7,2.9,-1,4.3   c-2.3,5,-4.6,10,-6.9,15c-5.8,10.5,-14.7,17.5,-25.3,22.6c-1.5,0.7,-3.1,1.1,-4.6,1.6c-0.3,-2.1,0.3,-3.9,1.1,-5.7   c3.4,-7.4,6.4,-14.9,8.9,-22.6c6,-18.1,10,-36.5,12,-55.6c1.2,-11.6,0.9,-23.2,0.6,-34.8c-0.2,-6.8,-0.7,-13.8,-2.8,-20.5   c2.4,-4.1,4.7,-8.1,7.1,-12.2c5.6,4.7,8.4,11.3,11.7,17.6C369.8,663.3,370.8,665.2,371.9,667z"
+        android:fillColor="#E6A3A3"/>
+    <path
+        android:pathData="M260,814c2.9,4.6,8.1,3.9,12.4,4.8c25.9,5.3,50.7,1.1,74.7,-9.2c6.7,-2.9,13.1,-6.4,19.4,-10.2   c1.4,-0.9,2.9,-1.6,4.7,-1.2c-7.9,9.1,-18.6,13.8,-29.3,18.3c-22.3,9.4,-45.9,14.3,-69.8,17.6c-22.4,3.1,-45,4.4,-67.6,4.1   c-3.1,-0.1,-6.3,-0.5,-9.4,-0.8c-0.1,-2,-1.4,-2.2,-3,-2.4c-28.3,-3,-56,-8.2,-82.4,-19.1c-13.4,-5.5,-26.5,-11.8,-35.3,-24.1c-1.3,-1.8,-2.4,-3.6,-2.2,-5.9   c15.1,11.6,32.9,16.7,51,21.1c17.7,4.4,35.8,6.6,54,8.3c10,0.9,20,1.1,29.8,1.1c15.7,0.1,31.5,0.4,47.1,-2.4   C256,814,258,814,260,814z"
+        android:fillColor="#EDECEC"/>
+    <path
+        android:pathData="M130,831.9c-1.1,0.1,-2.2,0.2,-3.1,-0.6C128.3,829.5,129.4,829.5,130,831.9z"
+        android:fillColor="#EDECEC"/>
+    <path
+        android:pathData="M135,832.8c-1.1,0.1,-2.2,0.2,-3.1,-0.7C133.4,830.5,134.4,830.6,135,832.8z"
+        android:fillColor="#EDECEC"/>
+    <path
+        android:pathData="M142,833.8c-1.1,0.1,-2.2,0.2,-3.1,-0.6C140.3,831.5,141.4,831.5,142,833.8z"
+        android:fillColor="#EDECEC"/>
+    <path
+        android:pathData="M260,814c-2,0,-4,0,-6,0c-6.8,-3.7,-13.9,-6.8,-20.5,-11c-18,-11.5,-32.7,-26.4,-45.1,-43.6c-11,-15.2,-21,-31,-27.5,-48.8   c-0.9,-2.5,-2,-4.9,-1.9,-7.7c0.7,0,1.4,-0.1,2,0.1c16.2,4.6,33.1,5.3,49.6,5.3c10,0,20.1,-0.2,30.2,-1.3c19.5,-2,38.7,-5.3,57,-12.4   c15.6,-6,30.1,-13.9,41.3,-26.9c4.7,-3.1,7,-8.3,11,-12c2.1,6.7,2.6,13.7,2.8,20.5c0.3,11.6,0.6,23.1,-0.6,34.8c-2,19,-6,37.5,-12,55.6   c-2.6,7.7,-5.5,15.3,-8.9,22.6c-0.9,1.9,-1.5,3.7,-1.1,5.7c-9,5.4,-19,8.1,-29,10.8C287.6,809.6,273.8,811.9,260,814z"
+        android:fillColor="#E6A3A3"/>
+    <path
+        android:pathData="M339,668c-11.1,13,-25.7,20.8,-41.3,26.9c-18.3,7.1,-37.5,10.4,-57,12.4c-10.1,1,-20.3,1.3,-30.2,1.3   c-16.6,0,-33.4,-0.7,-49.6,-5.3c-0.6,-0.2,-1.3,-0.1,-2,-0.1c-0.6,-0.4,-1.3,-0.7,-1.9,-1.1c-0.4,-3.8,0.3,-5,4.8,-4.2c12.1,2,24.3,2.8,36.5,3.4   c32.4,1.7,64.1,-2.3,95.1,-11.6c14.8,-4.5,29,-10.8,41.5,-20.1C336.3,668.5,337.5,667.9,339,668z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M96,678c1.6,0.2,3.7,-0.7,4,2C98.4,679.8,97,679.3,96,678z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M100,680c1.1,0,2.3,-0.2,3,1C101.9,681,100.7,681.2,100,680z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M91.9,675c0.8,0,1.6,0.2,2.1,1C93.2,676,92.4,675.8,91.9,675z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M94,676c0.3,0.3,0.7,0.7,1,1C94.7,676.7,94.3,676.3,94,676z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M95,677c0.3,0.3,0.7,0.7,1,1C95.7,677.7,95.3,677.3,95,677z"
+        android:fillColor="#C5C5C5"/>
+    <path
+        android:pathData="M360,771c2.3,-5,4.6,-10,6.9,-15C368.2,760.3,364.7,767.8,360,771z"
+        android:fillColor="#EDECEC"/>
+</vector>
diff --git a/packages/DocumentsUI/res/drawable/ic_sd_storage.xml b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
new file mode 100644
index 0000000..b0f3cc3
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2015 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2,-.9 2,-2V4c0,-1.1,-.9,-2,-2,-2zm-6 6h-2V4h2v4zm3 0h-2V4h2v4zm3 0h-2V4h2v4z"/>
+</vector>
diff --git a/packages/DocumentsUI/res/layout/directory_cluster.xml b/packages/DocumentsUI/res/layout/directory_cluster.xml
index 8245e53..2fa09d3 100644
--- a/packages/DocumentsUI/res/layout/directory_cluster.xml
+++ b/packages/DocumentsUI/res/layout/directory_cluster.xml
@@ -25,7 +25,7 @@
         android:elevation="8dp"
         android:background="@color/material_grey_50"/>
 
-    <com.android.documentsui.DirectoryContainerView
+    <FrameLayout
         android:id="@+id/container_directory"
         android:layout_width="match_parent"
         android:layout_height="0dp"
diff --git a/packages/DocumentsUI/res/layout/drawer_layout.xml b/packages/DocumentsUI/res/layout/drawer_layout.xml
index 0146f14..e3def05 100644
--- a/packages/DocumentsUI/res/layout/drawer_layout.xml
+++ b/packages/DocumentsUI/res/layout/drawer_layout.xml
@@ -32,7 +32,7 @@
             android:layout_height="match_parent"
             android:orientation="vertical">
 
-            <com.android.documentsui.DocumentsToolBar
+            <com.android.documentsui.DocumentsToolbar
                 android:id="@+id/toolbar"
                 android:layout_width="match_parent"
                 android:layout_height="?android:attr/actionBarSize"
@@ -48,7 +48,7 @@
                     android:layout_marginStart="4dp"
                     android:overlapAnchor="true" />
 
-            </com.android.documentsui.DocumentsToolBar>
+            </com.android.documentsui.DocumentsToolbar>
 
             <include layout="@layout/directory_cluster"/>
 
diff --git a/packages/DocumentsUI/res/layout/fixed_layout.xml b/packages/DocumentsUI/res/layout/fixed_layout.xml
index 3135977..8414feb 100644
--- a/packages/DocumentsUI/res/layout/fixed_layout.xml
+++ b/packages/DocumentsUI/res/layout/fixed_layout.xml
@@ -22,12 +22,12 @@
     android:layout_height="match_parent"
     android:id="@+id/coordinator_layout">
 
-    <LinearLayout 
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical">
 
-        <com.android.documentsui.DocumentsToolBar
+        <com.android.documentsui.DocumentsToolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="?android:attr/actionBarSize"
@@ -43,7 +43,7 @@
                 android:layout_marginStart="4dp"
                 android:overlapAnchor="true" />
 
-        </com.android.documentsui.DocumentsToolBar>
+        </com.android.documentsui.DocumentsToolbar>
 
         <LinearLayout
             android:layout_width="match_parent"
@@ -59,7 +59,6 @@
 
             <include layout="@layout/directory_cluster"
                 android:layout_width="0dp"
-                android:layout_weight="1"
                 android:elevation="8dp" />
 
         </LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/single_pane_layout.xml b/packages/DocumentsUI/res/layout/single_pane_layout.xml
index c5a5745..f53d698 100644
--- a/packages/DocumentsUI/res/layout/single_pane_layout.xml
+++ b/packages/DocumentsUI/res/layout/single_pane_layout.xml
@@ -27,7 +27,7 @@
         android:layout_height="match_parent"
         android:orientation="vertical">
 
-        <com.android.documentsui.DocumentsToolBar
+        <com.android.documentsui.DocumentsToolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="?android:attr/actionBarSize"
@@ -43,7 +43,7 @@
                 android:layout_marginStart="4dp"
                 android:overlapAnchor="true" />
 
-        </com.android.documentsui.DocumentsToolBar>
+        </com.android.documentsui.DocumentsToolbar>
 
         <include layout="@layout/directory_cluster"/>
 
diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml
index a3cfde8..73571af 100644
--- a/packages/DocumentsUI/res/menu/activity.xml
+++ b/packages/DocumentsUI/res/menu/activity.xml
@@ -29,12 +29,44 @@
         android:icon="@drawable/ic_menu_search"
         android:showAsAction="always"
         android:actionViewClass="android.widget.SearchView"
-        android:imeOptions="actionSearch" />
+        android:imeOptions="actionSearch"
+        android:visible="false" />
+    <item
+        android:id="@+id/menu_grid"
+        android:title="@string/menu_grid"
+        android:icon="@drawable/ic_menu_view_grid"
+        android:showAsAction="always" />
+    <item
+        android:id="@+id/menu_list"
+        android:title="@string/menu_list"
+        android:icon="@drawable/ic_menu_view_list"
+        android:showAsAction="always" />
+
+    <item
+        android:id="@+id/menu_new_window"
+        android:title="@string/menu_new_window"
+        android:alphabeticShortcut="n"
+        android:showAsAction="never"
+        android:visible="false" />
+    <item
+        android:id="@+id/menu_create_dir"
+        android:title="@string/menu_create_dir"
+        android:icon="@drawable/ic_menu_new_folder"
+        android:alphabeticShortcut="e"
+        android:showAsAction="never"
+        android:visible="false" />
+    <item
+        android:id="@+id/menu_paste_from_clipboard"
+        android:title="@string/menu_paste_from_clipboard"
+        android:alphabeticShortcut="v"
+        android:showAsAction="never"
+        android:visible="false" />
+    <!-- Copy action is defined in mode_directory.xml -->
     <item
         android:id="@+id/menu_sort"
         android:title="@string/menu_sort"
         android:icon="@drawable/ic_menu_sortby"
-        android:showAsAction="always">
+        android:showAsAction="never">
         <menu>
             <item
                 android:id="@+id/menu_sort_name"
@@ -48,36 +80,6 @@
         </menu>
     </item>
     <item
-        android:id="@+id/menu_grid"
-        android:title="@string/menu_grid"
-        android:icon="@drawable/ic_menu_view_grid"
-        android:showAsAction="never" />
-    <item
-        android:id="@+id/menu_list"
-        android:title="@string/menu_list"
-        android:icon="@drawable/ic_menu_view_list"
-        android:showAsAction="never" />
-    <item
-        android:id="@+id/menu_new_window"
-        android:title="@string/menu_new_window"
-        android:alphabeticShortcut="n"
-        android:showAsAction="never"
-        android:visible="false" />
-    <item
-        android:id="@+id/menu_create_dir"
-        android:title="@string/menu_create_dir"
-        android:icon="@drawable/ic_menu_new_folder"
-        android:alphabeticShortcut="e"
-        android:showAsAction="always"
-        android:visible="false" />
-    <item
-        android:id="@+id/menu_paste_from_clipboard"
-        android:title="@string/menu_paste_from_clipboard"
-        android:alphabeticShortcut="v"
-        android:showAsAction="never"
-        android:visible="false" />
-    <!-- Copy action is defined in mode_directory.xml -->
-    <item
         android:id="@+id/menu_file_size"
         android:showAsAction="never"
         android:visible="false" />
@@ -88,5 +90,6 @@
     <item
         android:id="@+id/menu_settings"
         android:title="@string/menu_settings"
-        android:showAsAction="never" />
+        android:showAsAction="never"
+        android:visible="false" />
 </menu>
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index f0c48ec..458c309 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Lysaansig"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sorteer volgens"</string>
     <string name="menu_search" msgid="3816712084502856974">"Soek"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Instellings"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Maak oop"</string>
     <string name="menu_save" msgid="2394743337684426338">"Stoor"</string>
     <string name="menu_share" msgid="3075149983979628146">"Deel"</string>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index aa11af1..6e08df4 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"የዝርዝር እይታ"</string>
     <string name="menu_sort" msgid="7677740407158414452">"ደርድር በ"</string>
     <string name="menu_search" msgid="3816712084502856974">"ፈልግ"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"ቅንብሮች"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"ክፈት"</string>
     <string name="menu_save" msgid="2394743337684426338">"አስቀምጥ"</string>
     <string name="menu_share" msgid="3075149983979628146">"አጋራ"</string>
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index 966fb17..4b7b4a8 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"عرض القائمة"</string>
     <string name="menu_sort" msgid="7677740407158414452">"ترتيب بحسب"</string>
     <string name="menu_search" msgid="3816712084502856974">"بحث"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"الإعدادات"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"فتح"</string>
     <string name="menu_save" msgid="2394743337684426338">"حفظ"</string>
     <string name="menu_share" msgid="3075149983979628146">"مشاركة"</string>
diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
index 8864a27..9162b95 100644
--- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml
+++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"Siyahı görünüşü"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Bunlardan biri üzrə sırala"</string>
     <string name="menu_search" msgid="3816712084502856974">"Axtarış"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Ayarlar"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"Yaddaş parametrləri"</string>
     <string name="menu_open" msgid="432922957274920903">"Açın"</string>
     <string name="menu_save" msgid="2394743337684426338">"Yadda saxlayın"</string>
     <string name="menu_share" msgid="3075149983979628146">"Paylaşın"</string>
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index 9e9dfb1..3252a43 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Prikaz liste"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sortiraj prema"</string>
     <string name="menu_search" msgid="3816712084502856974">"Pretraži"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Podešavanja"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Otvori"</string>
     <string name="menu_save" msgid="2394743337684426338">"Sačuvaj"</string>
     <string name="menu_share" msgid="3075149983979628146">"Deli"</string>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 6544c57..0d901cf 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Списъчен изглед"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Сортиране по"</string>
     <string name="menu_search" msgid="3816712084502856974">"Търсене"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Настройки"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Отваряне"</string>
     <string name="menu_save" msgid="2394743337684426338">"Запазване"</string>
     <string name="menu_share" msgid="3075149983979628146">"Споделяне"</string>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index 84328a8..a990282 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"তালিকা দৃশ্য"</string>
     <string name="menu_sort" msgid="7677740407158414452">"এই অনুসারে বাছুন"</string>
     <string name="menu_search" msgid="3816712084502856974">"অনুসন্ধান করুন"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"সেটিংস"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"খুলুন"</string>
     <string name="menu_save" msgid="2394743337684426338">"সংরক্ষণ করুন"</string>
     <string name="menu_share" msgid="3075149983979628146">"ভাগ করুন"</string>
diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
index d8797a3..9d75ddc 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml
+++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
@@ -36,7 +36,7 @@
     <skip />
     <!-- no translation found for menu_search (3816712084502856974) -->
     <skip />
-    <!-- no translation found for menu_settings (6008033148948428823) -->
+    <!-- no translation found for menu_settings (8239065133341597825) -->
     <skip />
     <!-- no translation found for menu_open (432922957274920903) -->
     <skip />
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 3cf069b..25029e9 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Visualització de llista"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Ordena per"</string>
     <string name="menu_search" msgid="3816712084502856974">"Cerca"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Configuració"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Obre"</string>
     <string name="menu_save" msgid="2394743337684426338">"Desa"</string>
     <string name="menu_share" msgid="3075149983979628146">"Comparteix"</string>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index b6b9a88..bcb1748 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Zobrazení seznamu"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Řadit podle"</string>
     <string name="menu_search" msgid="3816712084502856974">"Hledat"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Nastavení"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Otevřít"</string>
     <string name="menu_save" msgid="2394743337684426338">"Uložit"</string>
     <string name="menu_share" msgid="3075149983979628146">"Sdílet"</string>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index 2c45d3b..03f4881 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Listevisning"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sortér efter"</string>
     <string name="menu_search" msgid="3816712084502856974">"Søg"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Indstillinger"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Åbn"</string>
     <string name="menu_save" msgid="2394743337684426338">"Gem"</string>
     <string name="menu_share" msgid="3075149983979628146">"Del"</string>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index 37ed4df..0abdd57 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Listenansicht"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sortieren nach"</string>
     <string name="menu_search" msgid="3816712084502856974">"Suchen"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Einstellungen"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Öffnen"</string>
     <string name="menu_save" msgid="2394743337684426338">"Speichern"</string>
     <string name="menu_share" msgid="3075149983979628146">"Teilen"</string>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index 396fa12..819cb5b 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Προβολή λίστας"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Ταξινόμηση κατά"</string>
     <string name="menu_search" msgid="3816712084502856974">"Αναζήτηση"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Ρυθμίσεις"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Άνοιγμα"</string>
     <string name="menu_save" msgid="2394743337684426338">"Αποθήκευση"</string>
     <string name="menu_share" msgid="3075149983979628146">"Κοινή χρήση"</string>
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index e96fef9..f4cd479 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"List view"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sort by"</string>
     <string name="menu_search" msgid="3816712084502856974">"Search"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Settings"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Open"</string>
     <string name="menu_save" msgid="2394743337684426338">"Save"</string>
     <string name="menu_share" msgid="3075149983979628146">"Share"</string>
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index e96fef9..f4cd479 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"List view"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sort by"</string>
     <string name="menu_search" msgid="3816712084502856974">"Search"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Settings"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Open"</string>
     <string name="menu_save" msgid="2394743337684426338">"Save"</string>
     <string name="menu_share" msgid="3075149983979628146">"Share"</string>
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index e96fef9..f4cd479 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"List view"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sort by"</string>
     <string name="menu_search" msgid="3816712084502856974">"Search"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Settings"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Open"</string>
     <string name="menu_save" msgid="2394743337684426338">"Save"</string>
     <string name="menu_share" msgid="3075149983979628146">"Share"</string>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 9f77732..92eb697 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Vista de lista"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Ordenar por"</string>
     <string name="menu_search" msgid="3816712084502856974">"Buscar"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Configuración"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Abrir"</string>
     <string name="menu_save" msgid="2394743337684426338">"Guardar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Compartir"</string>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 2010f8c..5368145 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"Vista de lista"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Ordenar por"</string>
     <string name="menu_search" msgid="3816712084502856974">"Buscar"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Ajustes"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"Ajustes de almacenamiento"</string>
     <string name="menu_open" msgid="432922957274920903">"Abrir"</string>
     <string name="menu_save" msgid="2394743337684426338">"Guardar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Compartir"</string>
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index 97577e68..982a949 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Loendikuva"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sortimisalus:"</string>
     <string name="menu_search" msgid="3816712084502856974">"Otsing"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Seaded"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Ava"</string>
     <string name="menu_save" msgid="2394743337684426338">"Salvesta"</string>
     <string name="menu_share" msgid="3075149983979628146">"Jaga"</string>
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index 036c361..8c13368 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Zerrenda-ikuspegia"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Ordenatzeko irizpidea"</string>
     <string name="menu_search" msgid="3816712084502856974">"Bilatu"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Ezarpenak"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Ireki"</string>
     <string name="menu_save" msgid="2394743337684426338">"Gorde"</string>
     <string name="menu_share" msgid="3075149983979628146">"Partekatu"</string>
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index 7367e25..b7d09f8 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"نمای فهرستی"</string>
     <string name="menu_sort" msgid="7677740407158414452">"مرتب‌سازی براساس"</string>
     <string name="menu_search" msgid="3816712084502856974">"جستجو"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"تنظیمات"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"باز کردن"</string>
     <string name="menu_save" msgid="2394743337684426338">"ذخیره"</string>
     <string name="menu_share" msgid="3075149983979628146">"اشتراک‌گذاری"</string>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 2d65899..c9517f9 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Luettelonäkymä"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Lajitteluperuste"</string>
     <string name="menu_search" msgid="3816712084502856974">"Haku"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Asetukset"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Avaa"</string>
     <string name="menu_save" msgid="2394743337684426338">"Tallenna"</string>
     <string name="menu_share" msgid="3075149983979628146">"Jaa"</string>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index baa963a..ace072b 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Liste"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Trier par"</string>
     <string name="menu_search" msgid="3816712084502856974">"Rechercher"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Paramètres"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Ouvrir"</string>
     <string name="menu_save" msgid="2394743337684426338">"Enregistrer"</string>
     <string name="menu_share" msgid="3075149983979628146">"Partager"</string>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index d30a130..b1e4827 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Liste"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Trier par"</string>
     <string name="menu_search" msgid="3816712084502856974">"Rechercher"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Paramètres"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Ouvrir"</string>
     <string name="menu_save" msgid="2394743337684426338">"Enregistrer"</string>
     <string name="menu_share" msgid="3075149983979628146">"Partager"</string>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index 7c69698..9275557 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Vista de lista"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Ordenar por"</string>
     <string name="menu_search" msgid="3816712084502856974">"Buscar"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Configuración"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Abrir"</string>
     <string name="menu_save" msgid="2394743337684426338">"Gardar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Compartir"</string>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index c650d93..5dceac2d7 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"સૂચિ દૃશ્ય"</string>
     <string name="menu_sort" msgid="7677740407158414452">"આ પ્રમાણે સૉર્ટ કરો"</string>
     <string name="menu_search" msgid="3816712084502856974">"શોધો"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"સેટિંગ્સ"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"ખોલો"</string>
     <string name="menu_save" msgid="2394743337684426338">"સાચવો"</string>
     <string name="menu_share" msgid="3075149983979628146">"શેર કરો"</string>
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index 4ab246d..a6eeb9f 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"सूची दृश्य"</string>
     <string name="menu_sort" msgid="7677740407158414452">"इससे क्रमित करें"</string>
     <string name="menu_search" msgid="3816712084502856974">"खोजें"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"सेटिंग"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"मेमोरी सेटिंग"</string>
     <string name="menu_open" msgid="432922957274920903">"खोलें"</string>
     <string name="menu_save" msgid="2394743337684426338">"जोड़ें"</string>
     <string name="menu_share" msgid="3075149983979628146">"साझा करें"</string>
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index e5d04f7..888cf32 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Prikaz popisa"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Poredano po"</string>
     <string name="menu_search" msgid="3816712084502856974">"Pretraživanje"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Postavke"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Otvaranje"</string>
     <string name="menu_save" msgid="2394743337684426338">"Spremi"</string>
     <string name="menu_share" msgid="3075149983979628146">"Dijeli"</string>
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index 7a68a19..910eb0c 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Lista"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Rendezés"</string>
     <string name="menu_search" msgid="3816712084502856974">"Keresés"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Beállítások"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Megnyitás"</string>
     <string name="menu_save" msgid="2394743337684426338">"Mentés"</string>
     <string name="menu_share" msgid="3075149983979628146">"Megosztás"</string>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index e28c711..1471a6a 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -26,10 +26,11 @@
     <string name="menu_list" msgid="7279285939892417279">"Ցուցակի տեսք"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Դասավորել ըստ"</string>
     <string name="menu_search" msgid="3816712084502856974">"Որոնել"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Կարգավորումներ"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Բացել"</string>
     <string name="menu_save" msgid="2394743337684426338">"Պահել"</string>
-    <string name="menu_share" msgid="3075149983979628146">"Համօգտագործել"</string>
+    <string name="menu_share" msgid="3075149983979628146">"Կիսվել"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ջնջել"</string>
     <string name="menu_select_all" msgid="8323579667348729928">"Ընտրել բոլորը"</string>
     <string name="menu_copy" msgid="3612326052677229148">"Պատճենել…"</string>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index a89d99d..29f118e 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"Tampilan daftar"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Urutkan menurut"</string>
     <string name="menu_search" msgid="3816712084502856974">"Telusuri"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Setelan"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"Setelan penyimpanan"</string>
     <string name="menu_open" msgid="432922957274920903">"Buka"</string>
     <string name="menu_save" msgid="2394743337684426338">"Simpan"</string>
     <string name="menu_share" msgid="3075149983979628146">"Bagikan"</string>
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index 9c69741..c95189d 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Listayfirlit"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Raða eftir"</string>
     <string name="menu_search" msgid="3816712084502856974">"Leita"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Stillingar"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Opna"</string>
     <string name="menu_save" msgid="2394743337684426338">"Vista"</string>
     <string name="menu_share" msgid="3075149983979628146">"Deila"</string>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index d06f732..276c937 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Visualizzazione elenco"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Ordina per"</string>
     <string name="menu_search" msgid="3816712084502856974">"Cerca"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Impostazioni"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Apri"</string>
     <string name="menu_save" msgid="2394743337684426338">"Salva"</string>
     <string name="menu_share" msgid="3075149983979628146">"Condividi"</string>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 25d9b12..4fc5617 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"תצוגת רשימה"</string>
     <string name="menu_sort" msgid="7677740407158414452">"מיין לפי"</string>
     <string name="menu_search" msgid="3816712084502856974">"חפש"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"הגדרות"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"פתח"</string>
     <string name="menu_save" msgid="2394743337684426338">"שמור"</string>
     <string name="menu_share" msgid="3075149983979628146">"שתף"</string>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index d1156ff..36a35f9 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"リスト表示"</string>
     <string name="menu_sort" msgid="7677740407158414452">"並べ替え"</string>
     <string name="menu_search" msgid="3816712084502856974">"検索"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"設定"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"開く"</string>
     <string name="menu_save" msgid="2394743337684426338">"保存"</string>
     <string name="menu_share" msgid="3075149983979628146">"共有"</string>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index e1a5be4..eea4828 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"სიის ხედი"</string>
     <string name="menu_sort" msgid="7677740407158414452">"სორტირება:"</string>
     <string name="menu_search" msgid="3816712084502856974">"ძიება"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"პარამეტრები"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"გახსნა"</string>
     <string name="menu_save" msgid="2394743337684426338">"შენახვა"</string>
     <string name="menu_share" msgid="3075149983979628146">"გაზიარება"</string>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index 3aed2a0..715db08 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Тізім көрінісі"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Белгіге қарай сұрыптау"</string>
     <string name="menu_search" msgid="3816712084502856974">"Іздеу"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Параметрлер"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Ашу"</string>
     <string name="menu_save" msgid="2394743337684426338">"Сақтау"</string>
     <string name="menu_share" msgid="3075149983979628146">"Бөлісу"</string>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index 7e5851f..efa7e88 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"ទិដ្ឋភាព​បញ្ជី"</string>
     <string name="menu_sort" msgid="7677740407158414452">"តម្រៀប​តាម"</string>
     <string name="menu_search" msgid="3816712084502856974">"ស្វែងរក"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"ការ​កំណត់"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"បើក"</string>
     <string name="menu_save" msgid="2394743337684426338">"រក្សាទុក"</string>
     <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក​"</string>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index 41cdbc3..dc644a8 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"ಪಟ್ಟಿ ವೀಕ್ಷಣೆ"</string>
     <string name="menu_sort" msgid="7677740407158414452">"ಈ ಪ್ರಕಾರ ವಿಂಗಡಿಸು"</string>
     <string name="menu_search" msgid="3816712084502856974">"ಹುಡುಕು"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"ತೆರೆ"</string>
     <string name="menu_save" msgid="2394743337684426338">"ಉಳಿಸು"</string>
     <string name="menu_share" msgid="3075149983979628146">"ಹಂಚು"</string>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index 58edec4..f807eef 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"목록 보기"</string>
     <string name="menu_sort" msgid="7677740407158414452">"정렬 기준"</string>
     <string name="menu_search" msgid="3816712084502856974">"검색"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"설정"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"열기"</string>
     <string name="menu_save" msgid="2394743337684426338">"저장"</string>
     <string name="menu_share" msgid="3075149983979628146">"공유"</string>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index fc56478..bc1ea7c 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Тизмек көрүнүшү"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Ылгоо"</string>
     <string name="menu_search" msgid="3816712084502856974">"Издөө"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Тууралоолор"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Ачуу"</string>
     <string name="menu_save" msgid="2394743337684426338">"Сактоо"</string>
     <string name="menu_share" msgid="3075149983979628146">"Бөлүшүү"</string>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index fba9244..aa1c3df 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"ມຸມມອງແບບລາຍຊື່"</string>
     <string name="menu_sort" msgid="7677740407158414452">"ຮຽງລຳດັບຕາມ"</string>
     <string name="menu_search" msgid="3816712084502856974">"ຊອກຫາ"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"ການຕັ້ງຄ່າ"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"ເປີດ"</string>
     <string name="menu_save" msgid="2394743337684426338">"ບັນທຶກ"</string>
     <string name="menu_share" msgid="3075149983979628146">"ແບ່ງປັນ"</string>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 992d4da..48339b9 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Sąrašo rodinys"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Rūšiuoti pagal"</string>
     <string name="menu_search" msgid="3816712084502856974">"Ieškoti"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Nustatymai"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Atidaryti"</string>
     <string name="menu_save" msgid="2394743337684426338">"Išsaugoti"</string>
     <string name="menu_share" msgid="3075149983979628146">"Bendrinti"</string>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 58e507d..524feba 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Saraksts"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Kārtot pēc"</string>
     <string name="menu_search" msgid="3816712084502856974">"Meklēt"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Iestatījumi"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Atvērt"</string>
     <string name="menu_save" msgid="2394743337684426338">"Saglabāt"</string>
     <string name="menu_share" msgid="3075149983979628146">"Kopīgot"</string>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index b1ea307..15017e1 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Приказ на список"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Подреди по"</string>
     <string name="menu_search" msgid="3816712084502856974">"Пребарај"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Поставки"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Отвори"</string>
     <string name="menu_save" msgid="2394743337684426338">"Зачувај"</string>
     <string name="menu_share" msgid="3075149983979628146">"Сподели"</string>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index 9d1f353..9a79b72 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"ലിസ്റ്റ് കാഴ്‌ച"</string>
     <string name="menu_sort" msgid="7677740407158414452">"ഇപ്രകാരം അടുക്കുക"</string>
     <string name="menu_search" msgid="3816712084502856974">"തിരയൽ"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"ക്രമീകരണങ്ങൾ"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"തുറക്കുക"</string>
     <string name="menu_save" msgid="2394743337684426338">"സംരക്ഷിക്കുക"</string>
     <string name="menu_share" msgid="3075149983979628146">"പങ്കിടുക"</string>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index 3cbdc55..67b88ef 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Жагсааж харах"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Эрэмбэлэх"</string>
     <string name="menu_search" msgid="3816712084502856974">"Хайх"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Тохиргоо"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Нээх"</string>
     <string name="menu_save" msgid="2394743337684426338">"Хадгалах"</string>
     <string name="menu_share" msgid="3075149983979628146">"Хуваалцах"</string>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index ae7a48a..53ca858 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"सूची"</string>
     <string name="menu_sort" msgid="7677740407158414452">"नुसार क्रमवारी लावा"</string>
     <string name="menu_search" msgid="3816712084502856974">"शोध"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"सेटिंग्ज"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"संचयन सेटिंग्ज"</string>
     <string name="menu_open" msgid="432922957274920903">"उघडा"</string>
     <string name="menu_save" msgid="2394743337684426338">"जतन करा"</string>
     <string name="menu_share" msgid="3075149983979628146">"सामायिक करा"</string>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 7346dd5..24fe49c 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Paparan senarai"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Isih mengikut"</string>
     <string name="menu_search" msgid="3816712084502856974">"Cari"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Tetapan"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Buka"</string>
     <string name="menu_save" msgid="2394743337684426338">"Simpan"</string>
     <string name="menu_share" msgid="3075149983979628146">"Kongsi"</string>
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 2e71299..4c36bd3 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"အစဉ်လိုက်မြင်ကွင်း"</string>
     <string name="menu_sort" msgid="7677740407158414452">"အစဉ်အလိုက် စီခြင်း"</string>
     <string name="menu_search" msgid="3816712084502856974">"ရှာဖွေရန်"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"ဆက်တင်များ"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"ဖွင့်ရန်"</string>
     <string name="menu_save" msgid="2394743337684426338">"သိမ်းပါ"</string>
     <string name="menu_share" msgid="3075149983979628146">"မျှဝေခြင်း"</string>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index 57a5a76..4ff395e 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Listevisning"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sortér etter"</string>
     <string name="menu_search" msgid="3816712084502856974">"Søk"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Innstillinger"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Åpne"</string>
     <string name="menu_save" msgid="2394743337684426338">"Lagre"</string>
     <string name="menu_share" msgid="3075149983979628146">"Del"</string>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index 1f2f29c..45934ad 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"सूची दृश्य"</string>
     <string name="menu_sort" msgid="7677740407158414452">"यसद्वारा क्रमवद्घ गर्नुहोस्"</string>
     <string name="menu_search" msgid="3816712084502856974">"खोज्नुहोस्"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"सेटिङहरू"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"खोल्नुहोस्"</string>
     <string name="menu_save" msgid="2394743337684426338">"सुरक्षित गर्नुहोस्"</string>
     <string name="menu_share" msgid="3075149983979628146">"साझेदारी गर्नुहोस्"</string>
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index 348c9cf..b613da3 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"Lijstweergave"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sorteren op"</string>
     <string name="menu_search" msgid="3816712084502856974">"Zoeken"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Instellingen"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"Instellingen voor opslag"</string>
     <string name="menu_open" msgid="432922957274920903">"Openen"</string>
     <string name="menu_save" msgid="2394743337684426338">"Opslaan"</string>
     <string name="menu_share" msgid="3075149983979628146">"Delen"</string>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index add268f..d5eeb66 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"ਸੂਚੀ ਦ੍ਰਿਸ਼"</string>
     <string name="menu_sort" msgid="7677740407158414452">"ਇਸ ਅਨੁਸਾਰ ਛਾਂਟੋ"</string>
     <string name="menu_search" msgid="3816712084502856974">"ਖੋਜੋ"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"ਸਟੋਰੇਜ ਸੈਟਿੰਗਾਂ"</string>
     <string name="menu_open" msgid="432922957274920903">"ਖੋਲ੍ਹੋ"</string>
     <string name="menu_save" msgid="2394743337684426338">"ਸੁਰੱਖਿਅਤ ਕਰੋ"</string>
     <string name="menu_share" msgid="3075149983979628146">"ਸ਼ੇਅਰ ਕਰੋ"</string>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index d30ed84..90f2bdf 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Widok listy"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sortuj według"</string>
     <string name="menu_search" msgid="3816712084502856974">"Szukaj"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Ustawienia"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Otwórz"</string>
     <string name="menu_save" msgid="2394743337684426338">"Zapisz"</string>
     <string name="menu_share" msgid="3075149983979628146">"Udostępnij"</string>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index 068a4e6..f72f43c 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Visualização em lista"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Classificar por"</string>
     <string name="menu_search" msgid="3816712084502856974">"Pesquisar"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Configurações"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Abrir"</string>
     <string name="menu_save" msgid="2394743337684426338">"Salvar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Compartilhar"</string>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index 0897901..596474fd 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"Vista de lista"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Ordenar por"</string>
     <string name="menu_search" msgid="3816712084502856974">"Pesquisar"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Definições"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"Defin. de armazenamento"</string>
     <string name="menu_open" msgid="432922957274920903">"Abrir"</string>
     <string name="menu_save" msgid="2394743337684426338">"Guardar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Partilhar"</string>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 068a4e6..f72f43c 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Visualização em lista"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Classificar por"</string>
     <string name="menu_search" msgid="3816712084502856974">"Pesquisar"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Configurações"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Abrir"</string>
     <string name="menu_save" msgid="2394743337684426338">"Salvar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Compartilhar"</string>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index c8c0c09..07f25f6 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Afișare tip listă"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sortați după"</string>
     <string name="menu_search" msgid="3816712084502856974">"Căutați"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Setări"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Deschideți"</string>
     <string name="menu_save" msgid="2394743337684426338">"Salvați"</string>
     <string name="menu_share" msgid="3075149983979628146">"Distribuiți"</string>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index 3f5e53c..97bd4dd8 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Список"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Сортировать"</string>
     <string name="menu_search" msgid="3816712084502856974">"Поиск"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Настройки"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Открыть"</string>
     <string name="menu_save" msgid="2394743337684426338">"Сохранить"</string>
     <string name="menu_share" msgid="3075149983979628146">"Поделиться"</string>
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index 1237f14..19d8e89 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"ලැයිස්තු පෙනුම"</string>
     <string name="menu_sort" msgid="7677740407158414452">"අනුපිළිවෙලට සකසා ඇත්තේ"</string>
     <string name="menu_search" msgid="3816712084502856974">"සෙවීම"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"සැකසීම්"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"විවෘත කරන්න"</string>
     <string name="menu_save" msgid="2394743337684426338">"සුරකින්න"</string>
     <string name="menu_share" msgid="3075149983979628146">"බෙදාගන්න"</string>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index db2ec54..cf74acf 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Zobrazenie zoznamu"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Zoradiť podľa"</string>
     <string name="menu_search" msgid="3816712084502856974">"Hľadať"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Nastavenia"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Otvoriť"</string>
     <string name="menu_save" msgid="2394743337684426338">"Uložiť"</string>
     <string name="menu_share" msgid="3075149983979628146">"Zdieľať"</string>
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index f000f05..7da4628 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Pogled seznama"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Razvrsti glede na"</string>
     <string name="menu_search" msgid="3816712084502856974">"Iskanje"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Nastavitve"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Odpri"</string>
     <string name="menu_save" msgid="2394743337684426338">"Shrani"</string>
     <string name="menu_share" msgid="3075149983979628146">"Skupna raba"</string>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index fa53157..fec090c 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Pamje liste"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Rendit sipas"</string>
     <string name="menu_search" msgid="3816712084502856974">"Kërko"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Cilësimet"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Hap"</string>
     <string name="menu_save" msgid="2394743337684426338">"Ruaj"</string>
     <string name="menu_share" msgid="3075149983979628146">"Shpërnda"</string>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index 7b9f659..b43a8d3 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Приказ листе"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Сортирај према"</string>
     <string name="menu_search" msgid="3816712084502856974">"Претражи"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Подешавања"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Отвори"</string>
     <string name="menu_save" msgid="2394743337684426338">"Сачувај"</string>
     <string name="menu_share" msgid="3075149983979628146">"Дели"</string>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index 3590fe7..2d1d924 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Listvy"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sortera efter"</string>
     <string name="menu_search" msgid="3816712084502856974">"Sök"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Inställningar"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Öppna"</string>
     <string name="menu_save" msgid="2394743337684426338">"Spara"</string>
     <string name="menu_share" msgid="3075149983979628146">"Dela"</string>
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index f15db63..e28365d 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Mwonekano orodha"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Panga kwa"</string>
     <string name="menu_search" msgid="3816712084502856974">"Utafutaji"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Mipangilio"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Fungua"</string>
     <string name="menu_save" msgid="2394743337684426338">"Hifadhi"</string>
     <string name="menu_share" msgid="3075149983979628146">"Shiriki"</string>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 3b71514..fed470d 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"பட்டியல்"</string>
     <string name="menu_sort" msgid="7677740407158414452">"இதன்படி வரிசைப்படுத்து"</string>
     <string name="menu_search" msgid="3816712084502856974">"தேடு"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"அமைப்பு"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"திற"</string>
     <string name="menu_save" msgid="2394743337684426338">"சேமி"</string>
     <string name="menu_share" msgid="3075149983979628146">"பகிர்"</string>
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index 900fe41..0d90627 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"జాబితా వీక్షణ"</string>
     <string name="menu_sort" msgid="7677740407158414452">"ఇలా క్రమబద్ధీకరించు"</string>
     <string name="menu_search" msgid="3816712084502856974">"శోధించు"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"సెట్టింగ్‌లు"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"నిల్వ సెట్టింగ్‌లు"</string>
     <string name="menu_open" msgid="432922957274920903">"తెరువు"</string>
     <string name="menu_save" msgid="2394743337684426338">"సేవ్ చేయి"</string>
     <string name="menu_share" msgid="3075149983979628146">"భాగస్వామ్యం చేయి"</string>
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 4d93f43..25ab564 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"มุมมองรายการ"</string>
     <string name="menu_sort" msgid="7677740407158414452">"จัดเรียงตาม"</string>
     <string name="menu_search" msgid="3816712084502856974">"ค้นหา"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"การตั้งค่า"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"เปิด"</string>
     <string name="menu_save" msgid="2394743337684426338">"บันทึก"</string>
     <string name="menu_share" msgid="3075149983979628146">"แชร์"</string>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index d28eb69..1baa5db 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"View na listahan"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Uriin ayon sa"</string>
     <string name="menu_search" msgid="3816712084502856974">"Maghanap"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Mga Setting"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Buksan"</string>
     <string name="menu_save" msgid="2394743337684426338">"I-save"</string>
     <string name="menu_share" msgid="3075149983979628146">"Ibahagi"</string>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index 5223919..500c37f 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Liste görünümü"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sıralama ölçütü"</string>
     <string name="menu_search" msgid="3816712084502856974">"Ara"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Ayarlar"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Aç"</string>
     <string name="menu_save" msgid="2394743337684426338">"Kaydet"</string>
     <string name="menu_share" msgid="3075149983979628146">"Paylaş"</string>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index 1987ee2..c57ca6a 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Режим списку"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Параметри сортування"</string>
     <string name="menu_search" msgid="3816712084502856974">"Пошук"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Налаштування"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Відкрити"</string>
     <string name="menu_save" msgid="2394743337684426338">"Зберегти"</string>
     <string name="menu_share" msgid="3075149983979628146">"Поділитися"</string>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index 3871496..90bce27 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"فہرست منظر"</string>
     <string name="menu_sort" msgid="7677740407158414452">"ترتیب دیں بلحاظ"</string>
     <string name="menu_search" msgid="3816712084502856974">"تلاش کریں"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"ترتیبات"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"کھولیں"</string>
     <string name="menu_save" msgid="2394743337684426338">"محفوظ کریں"</string>
     <string name="menu_share" msgid="3075149983979628146">"اشتراک کریں"</string>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index a915afd..4a0aba2 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Ro‘yxat ko‘rinishida"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Saralash"</string>
     <string name="menu_search" msgid="3816712084502856974">"Qidirish"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Sozlamalar"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Ochish"</string>
     <string name="menu_save" msgid="2394743337684426338">"Saqlash"</string>
     <string name="menu_share" msgid="3075149983979628146">"Ulashish"</string>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index 536c7a5..48290d1 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"Chế độ xem danh sách"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Sắp xếp theo"</string>
     <string name="menu_search" msgid="3816712084502856974">"Tìm kiếm"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Cài đặt"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"Mở"</string>
     <string name="menu_save" msgid="2394743337684426338">"Lưu"</string>
     <string name="menu_share" msgid="3075149983979628146">"Chia sẻ"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index df2cf04..f3d4e6c 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"列表视图"</string>
     <string name="menu_sort" msgid="7677740407158414452">"排序依据"</string>
     <string name="menu_search" msgid="3816712084502856974">"搜索"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"设置"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"打开"</string>
     <string name="menu_save" msgid="2394743337684426338">"保存"</string>
     <string name="menu_share" msgid="3075149983979628146">"分享"</string>
@@ -100,8 +101,7 @@
     <string name="close" msgid="3043722427445528732">"关闭"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"以下文件无法复制:<xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"以下文件无法移动:<xliff:g id="LIST">%1$s</xliff:g>"</string>
-    <!-- no translation found for copy_converted_warning_content (5753861488218674361) -->
-    <skip />
+    <string name="copy_converted_warning_content" msgid="5753861488218674361">"下列文件已转换成其他格式:<xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
       <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>
@@ -109,8 +109,7 @@
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"无法将所选文件粘贴到此位置。"</string>
     <string name="menu_rename" msgid="7678802479104285353">"重命名"</string>
     <string name="rename_error" msgid="4203041674883412606">"无法重命名文档"</string>
-    <!-- no translation found for notification_copy_files_converted_title (3153573223054275181) -->
-    <skip />
+    <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分文件已转换成其他格式"</string>
     <string name="allow" msgid="7225948811296386551">"允许"</string>
     <string name="deny" msgid="2081879885755434506">"拒绝"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index fa66c7f..3c55cd8 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"清單檢視"</string>
     <string name="menu_sort" msgid="7677740407158414452">"排序方式"</string>
     <string name="menu_search" msgid="3816712084502856974">"搜尋"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"設定"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"開啟"</string>
     <string name="menu_save" msgid="2394743337684426338">"儲存"</string>
     <string name="menu_share" msgid="3075149983979628146">"分享"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index 0288bd3..f09899c 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -26,7 +26,8 @@
     <string name="menu_list" msgid="7279285939892417279">"清單檢視"</string>
     <string name="menu_sort" msgid="7677740407158414452">"排序依據"</string>
     <string name="menu_search" msgid="3816712084502856974">"搜尋"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"設定"</string>
+    <!-- no translation found for menu_settings (8239065133341597825) -->
+    <skip />
     <string name="menu_open" msgid="432922957274920903">"開啟"</string>
     <string name="menu_save" msgid="2394743337684426338">"儲存"</string>
     <string name="menu_share" msgid="3075149983979628146">"共用"</string>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index 9bff355..dffe241 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -26,7 +26,7 @@
     <string name="menu_list" msgid="7279285939892417279">"Ukubuka uhlu"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Hlunga nge-"</string>
     <string name="menu_search" msgid="3816712084502856974">"Sesha"</string>
-    <string name="menu_settings" msgid="6008033148948428823">"Izilungiselelo"</string>
+    <string name="menu_settings" msgid="8239065133341597825">"Izilungiselelo zesitoreji"</string>
     <string name="menu_open" msgid="432922957274920903">"Vula"</string>
     <string name="menu_save" msgid="2394743337684426338">"Londoloza"</string>
     <string name="menu_share" msgid="3075149983979628146">"Yabelana"</string>
diff --git a/packages/DocumentsUI/res/values/layouts.xml b/packages/DocumentsUI/res/values/layouts.xml
index 8ac1ac2..c9308a1 100644
--- a/packages/DocumentsUI/res/values/layouts.xml
+++ b/packages/DocumentsUI/res/values/layouts.xml
@@ -15,7 +15,7 @@
 -->
 
 <resources>
-    <item name="docs_activity" type="layout">@layout/drawer_layout</item>
+    <item name="documents_activity" type="layout">@layout/drawer_layout</item>
     <item name="files_activity" type="layout">@layout/drawer_layout</item>
-    <item name="manage_roots_activity" type="layout">@layout/single_pane_layout</item>
+    <item name="downloads_activity" type="layout">@layout/single_pane_layout</item>
 </resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index afe9336..b97918e 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -39,8 +39,8 @@
     <string name="menu_sort">Sort by</string>
     <!-- Menu item that enters a mode to search for documents [CHAR LIMIT=24] -->
     <string name="menu_search">Search</string>
-    <!-- Menu item that enters activity to change settings [CHAR LIMIT=24] -->
-    <string name="menu_settings">Settings</string>
+    <!-- Menu item that enters activity to change settings for current root [CHAR LIMIT=24] -->
+    <string name="menu_settings">Storage settings</string>
 
     <!-- Menu item title that opens the selected documents [CHAR LIMIT=24] -->
     <string name="menu_open">Open</string>
@@ -101,7 +101,7 @@
     <!-- Toast shown when creating a folder failed with an error [CHAR LIMIT=48] -->
     <string name="create_error">Failed to create folder</string>
     <!-- Error message shown when querying for a list of documents failed [CHAR LIMIT=48] -->
-    <string name="query_error">Failed to query documents</string>
+    <string name="query_error">Can\u2019t load content at the moment</string>
 
     <!-- Title of storage root location that contains recently modified or used documents [CHAR LIMIT=24] -->
     <string name="root_recent">Recent</string>
@@ -123,7 +123,7 @@
     <string name="no_results">No matches in %1$s</string>
 
     <!-- Toast shown when no app can be found to open the selected document [CHAR LIMIT=48] -->
-    <string name="toast_no_application">Can\'t open file</string>
+    <string name="toast_no_application">Can\u2019t open file</string>
     <!-- Toast shown when some of the selected documents failed to be deleted [CHAR LIMIT=48] -->
     <string name="toast_failed_delete">Unable to delete some documents</string>
 
@@ -160,27 +160,27 @@
     <string name="delete_preparing">Preparing for delete\u2026</string>
     <!-- Title of the copy error notification [CHAR LIMIT=48] -->
     <plurals name="copy_error_notification_title">
-        <item quantity="one">Couldn\'t copy <xliff:g id="count" example="1">%1$d</xliff:g> file</item>
-        <item quantity="other">Couldn\'t copy <xliff:g id="count" example="2">%1$d</xliff:g> files</item>
+        <item quantity="one">Couldn\u2019t copy <xliff:g id="count" example="1">%1$d</xliff:g> file</item>
+        <item quantity="other">Couldn\u2019t copy <xliff:g id="count" example="2">%1$d</xliff:g> files</item>
     </plurals>
     <!-- Title of the move error notification [CHAR LIMIT=48] -->
     <plurals name="move_error_notification_title">
-        <item quantity="one">Couldn\'t move <xliff:g id="count" example="1">%1$d</xliff:g> file</item>
-        <item quantity="other">Couldn\'t move <xliff:g id="count" example="2">%1$d</xliff:g> files</item>
+        <item quantity="one">Couldn\u2019t move <xliff:g id="count" example="1">%1$d</xliff:g> file</item>
+        <item quantity="other">Couldn\u2019t move <xliff:g id="count" example="2">%1$d</xliff:g> files</item>
     </plurals>
     <!-- Title of the delete error notification [CHAR LIMIT=48] -->
     <plurals name="delete_error_notification_title">
-        <item quantity="one">Couldn\'t delete <xliff:g id="count" example="1">%1$d</xliff:g> file</item>
-        <item quantity="other">Couldn\'t delete <xliff:g id="count" example="2">%1$d</xliff:g> files</item>
+        <item quantity="one">Couldn\u2019t delete <xliff:g id="count" example="1">%1$d</xliff:g> file</item>
+        <item quantity="other">Couldn\u2019t delete <xliff:g id="count" example="2">%1$d</xliff:g> files</item>
     </plurals>
     <!-- Second line for notifications saying that more information will be shown after touching [CHAR LIMIT=48] -->
     <string name="notification_touch_for_details">Tap to view details</string>
     <!-- Label of the close dialog button.[CHAR LIMIT=24] -->
     <string name="close">Close</string>
     <!-- Contents of the copying failure alert dialog. [CHAR LIMIT=48] -->
-    <string name="copy_failure_alert_content">These files weren\'t copied: <xliff:g id="list">%1$s</xliff:g></string>
+    <string name="copy_failure_alert_content">These files weren\u2019t copied: <xliff:g id="list">%1$s</xliff:g></string>
     <!-- Contents of the moving failure alert dialog. [CHAR LIMIT=48] -->
-    <string name="move_failure_alert_content">These files weren\'t moved: <xliff:g id="list">%1$s</xliff:g></string>
+    <string name="move_failure_alert_content">These files weren\u2019t moved: <xliff:g id="list">%1$s</xliff:g></string>
     <!-- Contents of the copying warning dialog due to converted files. [CHAR LIMIT=64] -->
     <string name="copy_converted_warning_content">These files were converted to another format: <xliff:g id="list" example="Document.pdf, Photo.jpg, Song.ogg">%1$s</xliff:g></string>
     <!-- Toast shown when a user copies files to clipboard. -->
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 1474aa6..3c21a21 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -18,10 +18,10 @@
 
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.State.MODE_GRID;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_DOWN;
+import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_ENTER;
+import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_LEAVE;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_SIDE;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_UP;
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkState;
 
@@ -38,91 +38,97 @@
 import android.os.Bundle;
 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.util.Log;
-import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.TextView;
+import android.widget.Spinner;
 
-import com.android.documentsui.RecentsProvider.ResumeColumns;
 import com.android.documentsui.SearchManager.SearchManagerListener;
 import com.android.documentsui.State.ViewMode;
 import com.android.documentsui.dirlist.DirectoryFragment;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.DocumentStack;
-import com.android.documentsui.model.DurableUtils;
 import com.android.documentsui.model.RootInfo;
 import com.android.internal.util.Preconditions;
 
-import libcore.io.IoUtils;
-
 import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Executor;
 
-public abstract class BaseActivity extends Activity implements SearchManagerListener {
+public abstract class BaseActivity extends Activity
+        implements SearchManagerListener, NavigationView.Environment {
 
     static final String EXTRA_STATE = "state";
 
+    // See comments where this const is referenced for details.
+    private static final int DRAWER_NO_FIDDLE_DELAY = 1500;
+
     State mState;
     RootsCache mRoots;
     SearchManager mSearchManager;
     DrawerController mDrawer;
-    boolean mProductivityDevice;
+    NavigationView mNavigator;
 
     private final String mTag;
+
     @LayoutRes
     private int mLayoutId;
-    private DirectoryContainerView mDirectoryContainer;
+
+    // Track the time we opened the drawer in response to back being pressed.
+    // We use the time gap to figure out whether to close app or reopen the drawer.
+    private long mDrawerLastFiddled;
 
     public abstract void onDocumentPicked(DocumentInfo doc, @Nullable SiblingProvider siblings);
     public abstract void onDocumentsPicked(List<DocumentInfo> docs);
 
     abstract void onTaskFinished(Uri... uris);
     abstract void refreshDirectory(int anim);
-    abstract void updateActionBar();
-    abstract void saveStackBlocking();
-    abstract State buildState();
+    /** Allows sub-classes to include information in a newly created State instance. */
+    abstract void includeState(State initialState);
 
     public BaseActivity(@LayoutRes int layoutId, String tag) {
         mLayoutId = layoutId;
         mTag = tag;
     }
 
+    @CallSuper
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        mState = (icicle != null)
-                ? icicle.<State>getParcelable(EXTRA_STATE)
-                        : buildState();
-
-        Metrics.logActivityLaunch(this, mState, getIntent());
-
         setContentView(mLayoutId);
 
+        mDrawer = DrawerController.create(this);
+        mState = getState(icicle);
+        Metrics.logActivityLaunch(this, mState, getIntent());
+
         mRoots = DocumentsApplication.getRootsCache(this);
+
         mRoots.setOnCacheUpdateListener(
                 new RootsCache.OnCacheUpdateListener() {
                     @Override
                     public void onCacheUpdate() {
-                        new HandleRootsChangedTask().execute(getCurrentRoot());
+                        new HandleRootsChangedTask(BaseActivity.this)
+                                .execute(getCurrentRoot());
                     }
                 });
-        mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
+
         mSearchManager = new SearchManager(this);
 
+        DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar);
+        setActionBar(toolbar);
+        mNavigator = new NavigationView(
+                mDrawer,
+                toolbar,
+                (Spinner) findViewById(R.id.stack),
+                mState,
+                this);
+
         // Base classes must update result in their onCreate.
         setResult(Activity.RESULT_CANCELED);
     }
@@ -132,16 +138,18 @@
         boolean showMenu = super.onCreateOptionsMenu(menu);
 
         getMenuInflater().inflate(R.menu.activity, menu);
-        mSearchManager.install((DocumentsToolBar) findViewById(R.id.toolbar));
+        mSearchManager.install((DocumentsToolbar) findViewById(R.id.toolbar));
 
         return showMenu;
     }
 
     @Override
+    @CallSuper
     public boolean onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
 
-        final RootInfo root = getCurrentRoot();
+        mSearchManager.showMenu(canSearchRoot());
+
         final boolean inRecents = getCurrentDirectory() == null;
 
         final MenuItem sort = menu.findItem(R.id.menu_sort);
@@ -150,26 +158,17 @@
         final MenuItem list = menu.findItem(R.id.menu_list);
         final MenuItem advanced = menu.findItem(R.id.menu_advanced);
         final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
-        final MenuItem settings = menu.findItem(R.id.menu_settings);
-        final MenuItem search = menu.findItem(R.id.menu_search);
 
-        // I'm thinkin' this isn't necesary here. If it is...'cuz of a bug....
-        // then uncomment the linke and let's get a proper bug reference here.
-        // mSearchManager.update(root);
-
-        // Search uses backend ranking; no sorting
+        // Search uses backend ranking; no sorting, recents doesn't support sort.
         sort.setVisible(!inRecents && !mSearchManager.isSearching());
+        sortSize.setVisible(mState.showSize); // Only sort by size when file sizes are visible
+        fileSize.setVisible(!mState.forceSize);
 
         // grid/list is effectively a toggle.
         grid.setVisible(mState.derivedMode != State.MODE_GRID);
         list.setVisible(mState.derivedMode != State.MODE_LIST);
 
-        sortSize.setVisible(mState.showSize); // Only sort by size when visible
-        fileSize.setVisible(!mState.forceSize);
         advanced.setVisible(!mState.forceAdvanced);
-        settings.setVisible((root.flags & Root.FLAG_HAS_SETTINGS) != 0);
-        search.setVisible(canSearchRoot());
-
         advanced.setTitle(LocalPreferences.getDisplayAdvancedDevices(this)
                 ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
         fileSize.setTitle(LocalPreferences.getDisplayFileSize(this)
@@ -184,7 +183,20 @@
         super.onDestroy();
     }
 
-    State buildDefaultState() {
+    private State getState(@Nullable Bundle icicle) {
+        if (icicle != null) {
+            State state = icicle.<State>getParcelable(EXTRA_STATE);
+            if (DEBUG) Log.d(mTag, "Recovered existing state object: " + state);
+            return state;
+        }
+
+        State state = createSharedState();
+        includeState(state);
+        if (DEBUG) Log.d(mTag, "Created new state object: " + state);
+        return state;
+    }
+
+    private State createSharedState() {
         State state = new State();
 
         final Intent intent = getIntent();
@@ -207,6 +219,11 @@
     void onStackRestored(boolean restored, boolean external) {}
 
     void onRootPicked(RootInfo root) {
+        // Skip refreshing if root didn't change
+        if(root.equals(getCurrentRoot())) {
+            return;
+        }
+
         mState.derivedMode = LocalPreferences.getViewMode(this, root, MODE_GRID);
 
         // Clear entire backstack and start in new root
@@ -217,24 +234,9 @@
         // Otherwise we delegate loading data from disk to a task
         // to ensure a responsive ui.
         if (mRoots.isRecentsRoot(root)) {
-            refreshCurrentRootAndDirectory(ANIM_SIDE);
+            refreshCurrentRootAndDirectory(ANIM_NONE);
         } else {
-            new PickRootTask(root, true).executeOnExecutor(getExecutorForCurrentDirectory());
-        }
-    }
-
-    void expandMenus(Menu menu) {
-        for (int i = 0; i < menu.size(); i++) {
-            final MenuItem item = menu.getItem(i);
-            switch (item.getItemId()) {
-                case R.id.menu_advanced:
-                case R.id.menu_file_size:
-                case R.id.menu_new_window:
-                case R.id.menu_search:
-                    break;
-                default:
-                    item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
-            }
+            new PickRootTask(this, root).executeOnExecutor(getExecutorForCurrentDirectory());
         }
     }
 
@@ -273,8 +275,10 @@
                 return true;
 
             case R.id.menu_paste_from_clipboard:
-                DirectoryFragment.get(getFragmentManager())
-                    .pasteFromClipboard();
+                DirectoryFragment dir = getDirectoryFragment();
+                if (dir != null) {
+                    dir.pasteFromClipboard();
+                }
               return true;
 
             case R.id.menu_advanced:
@@ -297,6 +301,10 @@
         }
     }
 
+    final @Nullable DirectoryFragment getDirectoryFragment() {
+        return DirectoryFragment.get(getFragmentManager());
+    }
+
     void showCreateDirectoryDialog() {
         CreateDirectoryFragment.show(getFragmentManager());
     }
@@ -323,7 +331,12 @@
     void openContainerDocument(DocumentInfo doc) {
         checkArgument(doc.isContainer());
         mState.pushDocument(doc);
-        refreshCurrentRootAndDirectory(ANIM_DOWN);
+        // Show an opening animation only if pressing "back" would get us back to the
+        // previous directory. Especially after opening a root document, pressing
+        // back, wouldn't go to the previous root, but close the activity.
+        final int anim = (mState.hasLocationChanged() && mState.stack.size() > 1)
+                ? ANIM_ENTER : ANIM_NONE;
+        refreshCurrentRootAndDirectory(anim);
     }
 
     /**
@@ -331,10 +344,10 @@
      * The current directory name and selection will get updated.
      * @param anim
      */
-    final void refreshCurrentRootAndDirectory(int anim) {
+    @Override
+    public final void refreshCurrentRootAndDirectory(int anim) {
         mSearchManager.cancelSearch();
 
-        mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
         refreshDirectory(anim);
 
         final RootsFragment roots = RootsFragment.get(getFragmentManager());
@@ -342,8 +355,7 @@
             roots.onCurrentRootChanged();
         }
 
-        updateActionBar();
-
+        mNavigator.update();
         invalidateOptionsMenu();
     }
 
@@ -354,7 +366,6 @@
      */
     @Override
     public void onSearchChanged() {
-        mDirectoryContainer.setDrawDisappearingFirst(false);
         refreshDirectory(ANIM_NONE);
     }
 
@@ -425,7 +436,10 @@
     void setDisplayFileSize(boolean display) {
         LocalPreferences.setDisplayFileSize(this, display);
         mState.showSize = display;
-        DirectoryFragment.get(getFragmentManager()).onDisplayStateChanged();
+        DirectoryFragment dir = getDirectoryFragment();
+        if (dir != null) {
+            dir.onDisplayStateChanged();
+        }
         invalidateOptionsMenu();
     }
 
@@ -434,7 +448,10 @@
      */
     void setUserSortOrder(int sortOrder) {
         mState.userSortOrder = sortOrder;
-        DirectoryFragment.get(getFragmentManager()).onSortOrderChanged();
+        DirectoryFragment dir = getDirectoryFragment();
+        if (dir != null) {
+            dir.onSortOrderChanged();
+        };
     }
 
     /**
@@ -449,7 +466,10 @@
         // in onOptionsItemSelected, and not do the full invalidation
         // But! That's a larger refactoring we'll save for another day.
         invalidateOptionsMenu();
-        DirectoryFragment.get(getFragmentManager()).onViewModeChanged();
+        DirectoryFragment dir = getDirectoryFragment();
+        if (dir != null) {
+            dir.onViewModeChanged();
+        };
     }
 
     public void setPending(boolean pending) {
@@ -470,6 +490,12 @@
         super.onRestoreInstanceState(state);
     }
 
+    @Override
+    public boolean isSearchExpanded() {
+        return mSearchManager.isExpanded();
+    }
+
+    @Override
     public RootInfo getCurrentRoot() {
         if (mState.stack.root != null) {
             return mState.stack.root;
@@ -498,7 +524,8 @@
             return;
         }
 
-        if (DirectoryFragment.get(getFragmentManager()).onBackPressed()) {
+        DirectoryFragment dir = getDirectoryFragment();
+        if (dir != null && dir.onBackPressed()) {
             return;
         }
 
@@ -507,16 +534,35 @@
             return;
         }
 
-        final int size = mState.stack.size();
+        int size = mState.stack.size();
 
-        if (mDrawer.isOpen()) {
-            mDrawer.setOpen(false);
-        } else if (size > 1) {
-            mState.stack.pop();
-            refreshCurrentRootAndDirectory(ANIM_UP);
-        } else {
-            super.onBackPressed();
+        // Do some "do what a I want" drawer fiddling, but don't
+        // do it if user already hit back recently and we recently
+        // did some fiddling.
+        if ((System.currentTimeMillis() - mDrawerLastFiddled) > DRAWER_NO_FIDDLE_DELAY) {
+            // Close drawer if it is open.
+            if (mDrawer.isOpen()) {
+                mDrawer.setOpen(false);
+                mDrawerLastFiddled = System.currentTimeMillis();
+                return;
+            }
+
+            // Open the Close drawer if it is closed and we're at the top of a root.
+            if (size == 1) {
+                mDrawer.setOpen(true);
+                // Remember so we don't just close it again if back is pressed again.
+                mDrawerLastFiddled = System.currentTimeMillis();
+                return;
+            }
         }
+
+        if (size > 1) {
+            mState.stack.pop();
+            refreshCurrentRootAndDirectory(ANIM_LEAVE);
+            return;
+        }
+
+        super.onBackPressed();
     }
 
     public void onStackPicked(DocumentStack stack) {
@@ -531,7 +577,7 @@
         }
     }
 
-    private DocumentInfo getRootDocumentBlocking(RootInfo root) {
+    DocumentInfo getRootDocumentBlocking(RootInfo root) {
         try {
             final Uri uri = DocumentsContract.buildDocumentUri(
                     root.authority, root.documentId);
@@ -542,117 +588,40 @@
         }
     }
 
-    final class PickRootTask extends AsyncTask<Void, Void, DocumentInfo> {
+    private static final class PickRootTask extends PairedTask<BaseActivity, Void, DocumentInfo> {
         private RootInfo mRoot;
-        private boolean mTouched;
 
-        public PickRootTask(RootInfo root, boolean touched) {
+        public PickRootTask(BaseActivity activity, RootInfo root) {
+            super(activity);
             mRoot = root;
-            mTouched = touched;
         }
 
         @Override
-        protected DocumentInfo doInBackground(Void... params) {
-            return getRootDocumentBlocking(mRoot);
+        protected DocumentInfo run(Void... params) {
+            return mOwner.getRootDocumentBlocking(mRoot);
         }
 
         @Override
-        protected void onPostExecute(DocumentInfo result) {
-            if (result != null && !isDestroyed()) {
-                openContainerDocument(result);
+        protected void finish(DocumentInfo result) {
+            if (result != null) {
+                mOwner.openContainerDocument(result);
             }
         }
     }
 
-    final class RestoreStackTask extends AsyncTask<Void, Void, Void> {
-        private volatile boolean mRestoredStack;
-        private volatile boolean mExternal;
-
-        @Override
-        protected Void doInBackground(Void... params) {
-            if (DEBUG && !mState.stack.isEmpty()) {
-                Log.w(mTag, "Overwriting existing stack.");
-            }
-            RootsCache roots = DocumentsApplication.getRootsCache(BaseActivity.this);
-
-            // Restore last stack for calling package
-            final String packageName = getCallingPackageMaybeExtra();
-            final Cursor cursor = getContentResolver()
-                    .query(RecentsProvider.buildResume(packageName), null, null, null, null);
-            try {
-                if (cursor.moveToFirst()) {
-                    mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0;
-                    final byte[] rawStack = cursor.getBlob(
-                            cursor.getColumnIndex(ResumeColumns.STACK));
-                    DurableUtils.readFromArray(rawStack, mState.stack);
-                    mRestoredStack = true;
-                }
-            } catch (IOException e) {
-                Log.w(mTag, "Failed to resume: " + e);
-            } finally {
-                IoUtils.closeQuietly(cursor);
-            }
-
-            if (mRestoredStack) {
-                // Update the restored stack to ensure we have freshest data
-                final Collection<RootInfo> matchingRoots = roots.getMatchingRootsBlocking(mState);
-                try {
-                    mState.stack.updateRoot(matchingRoots);
-                    mState.stack.updateDocuments(getContentResolver());
-                } catch (FileNotFoundException e) {
-                    Log.w(mTag, "Failed to restore stack: " + e);
-                    mState.stack.reset();
-                    mRestoredStack = false;
-                }
-            }
-
-            return null;
-        }
-
-        @Override
-        protected void onPostExecute(Void result) {
-            if (isDestroyed()) return;
-            mState.restored = true;
-            refreshCurrentRootAndDirectory(ANIM_NONE);
-            onStackRestored(mRestoredStack, mExternal);
-        }
-    }
-
-    final class RestoreRootTask extends AsyncTask<Void, Void, RootInfo> {
-        private Uri mRootUri;
-
-        public RestoreRootTask(Uri rootUri) {
-            mRootUri = rootUri;
-        }
-
-        @Override
-        protected RootInfo doInBackground(Void... params) {
-            final String rootId = DocumentsContract.getRootId(mRootUri);
-            return mRoots.getRootOneshot(mRootUri.getAuthority(), rootId);
-        }
-
-        @Override
-        protected void onPostExecute(RootInfo root) {
-            if (isDestroyed()) return;
-            mState.restored = true;
-
-            if (root != null) {
-                onRootPicked(root);
-            } else {
-                Log.w(mTag, "Failed to find root: " + mRootUri);
-                finish();
-            }
-        }
-    }
-
-    final class HandleRootsChangedTask extends AsyncTask<RootInfo, Void, RootInfo> {
+    private static final class HandleRootsChangedTask
+            extends PairedTask<BaseActivity, RootInfo, RootInfo> {
         DocumentInfo mHome;
 
+        public HandleRootsChangedTask(BaseActivity activity) {
+            super(activity);
+        }
+
         @Override
-        protected RootInfo doInBackground(RootInfo... roots) {
+        protected RootInfo run(RootInfo... roots) {
             checkArgument(roots.length == 1);
             final RootInfo currentRoot = roots[0];
-            final Collection<RootInfo> cachedRoots = mRoots.getRootsBlocking();
+            final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking();
             RootInfo homeRoot = null;
             for (final RootInfo root : cachedRoots) {
                 if (root.isHome()) {
@@ -664,107 +633,21 @@
                 }
             }
             Preconditions.checkNotNull(homeRoot);
-            mHome = getRootDocumentBlocking(homeRoot);
+            mHome = mOwner.getRootDocumentBlocking(homeRoot);
             return homeRoot;
         }
 
         @Override
-        protected void onPostExecute(RootInfo homeRoot) {
-            if (homeRoot != null && mHome != null && !isDestroyed()) {
+        protected void finish(RootInfo homeRoot) {
+            if (homeRoot != null && mHome != null) {
                 // Clear entire backstack and start in new root
-                mState.onRootChanged(homeRoot);
-                mSearchManager.update(homeRoot);
-                openContainerDocument(mHome);
+                mOwner.mState.onRootChanged(homeRoot);
+                mOwner.mSearchManager.update(homeRoot);
+                mOwner.openContainerDocument(mHome);
             }
         }
     }
 
-    final class ItemSelectedListener implements OnItemSelectedListener {
-
-        boolean mIgnoreNextNavigation;
-
-        @Override
-        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            if (mIgnoreNextNavigation) {
-                mIgnoreNextNavigation = false;
-                return;
-            }
-
-            while (mState.stack.size() > position + 1) {
-                mState.popDocument();
-            }
-            refreshCurrentRootAndDirectory(ANIM_UP);
-        }
-
-        @Override
-        public void onNothingSelected(AdapterView<?> parent) {
-            // Ignored
-        }
-    }
-
-    /**
-     * Class providing toolbar with runtime access to useful activity data.
-     */
-    final class StackAdapter extends BaseAdapter {
-        @Override
-        public int getCount() {
-            return mState.stack.size();
-        }
-
-        @Override
-        public DocumentInfo getItem(int position) {
-            return mState.stack.get(mState.stack.size() - position - 1);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            if (convertView == null) {
-                convertView = LayoutInflater.from(parent.getContext())
-                        .inflate(R.layout.item_subdir_title, parent, false);
-            }
-
-            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
-            final DocumentInfo doc = getItem(position);
-
-            if (position == 0) {
-                final RootInfo root = getCurrentRoot();
-                title.setText(root.title);
-            } else {
-                title.setText(doc.displayName);
-            }
-
-            return convertView;
-        }
-
-        @Override
-        public View getDropDownView(int position, View convertView, ViewGroup parent) {
-            if (convertView == null) {
-                convertView = LayoutInflater.from(parent.getContext())
-                        .inflate(R.layout.item_subdir, parent, false);
-            }
-
-            final ImageView subdir = (ImageView) convertView.findViewById(R.id.subdir);
-            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
-            final DocumentInfo doc = getItem(position);
-
-            if (position == 0) {
-                final RootInfo root = getCurrentRoot();
-                title.setText(root.title);
-                subdir.setVisibility(View.GONE);
-            } else {
-                title.setText(doc.displayName);
-                subdir.setVisibility(View.VISIBLE);
-            }
-
-            return convertView;
-        }
-    }
-
     /**
      * Interface providing access to current view of documents
      * even when all documents are not homed to the same parent.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java
deleted file mode 100644
index 71ea8a9..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import java.util.ArrayList;
-
-public class DirectoryContainerView extends FrameLayout {
-    private boolean mDisappearingFirst = false;
-
-    public DirectoryContainerView(Context context) {
-        super(context);
-    }
-
-    public DirectoryContainerView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        final ArrayList<View> disappearing = mDisappearingChildren;
-        if (mDisappearingFirst && disappearing != null) {
-            for (int i = 0; i < disappearing.size(); i++) {
-                super.drawChild(canvas, disappearing.get(i), getDrawingTime());
-            }
-        }
-        super.dispatchDraw(canvas);
-    }
-
-    @Override
-    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
-        if (mDisappearingFirst && mDisappearingChildren != null
-                && mDisappearingChildren.contains(child)) {
-            return false;
-        }
-        return super.drawChild(canvas, child, drawingTime);
-    }
-
-    public void setDrawDisappearingFirst(boolean disappearingFirst) {
-        mDisappearingFirst = disappearingFirst;
-    }
-}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index c3395ae..3485fe4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.Shared.DEBUG;
 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;
@@ -31,11 +32,12 @@
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentValues;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
+import android.database.Cursor;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.provider.DocumentsContract;
@@ -43,10 +45,6 @@
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
-import android.widget.BaseAdapter;
-import android.widget.Spinner;
-import android.widget.Toolbar;
 
 import com.android.documentsui.RecentsProvider.RecentColumns;
 import com.android.documentsui.RecentsProvider.ResumeColumns;
@@ -56,23 +54,20 @@
 import com.android.documentsui.model.RootInfo;
 import com.android.documentsui.services.FileOperationService;
 
+import libcore.io.IoUtils;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 public class DocumentsActivity extends BaseActivity {
     private static final int CODE_FORWARD = 42;
     private static final String TAG = "DocumentsActivity";
 
-    private Toolbar mToolbar;
-    private Spinner mToolbarStack;
-
-    private Toolbar mRootsToolbar;
-
-    private ItemSelectedListener mStackListener;
-    private BaseAdapter mStackAdapter;
-
     public DocumentsActivity() {
-        super(R.layout.docs_activity, TAG);
+        super(R.layout.documents_activity, TAG);
     }
 
     @Override
@@ -81,18 +76,6 @@
 
         final Resources res = getResources();
 
-        mDrawer = DrawerController.create(this);
-        mToolbar = (Toolbar) findViewById(R.id.toolbar);
-
-        mStackAdapter = new StackAdapter();
-        mStackListener = new ItemSelectedListener();
-        mToolbarStack = (Spinner) findViewById(R.id.stack);
-        mToolbarStack.setOnItemSelectedListener(mStackListener);
-
-        mRootsToolbar = (Toolbar) findViewById(R.id.roots_toolbar);
-
-        setActionBar(mToolbar);
-
         if (mState.action == ACTION_CREATE) {
             final String mimeType = getIntent().getType();
             final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE);
@@ -118,16 +101,14 @@
             // In this case, we set the activity title in AsyncTask.onPostExecute().  To prevent
             // talkback from reading aloud the default title, we clear it here.
             setTitle("");
-            new RestoreStackTask().execute();
+            new RestoreStackTask(this).execute();
         } else {
             refreshCurrentRootAndDirectory(ANIM_NONE);
         }
     }
 
     @Override
-    State buildState() {
-        State state = buildDefaultState();
-
+    void includeState(State state) {
         final Intent intent = getIntent();
         final String action = intent.getAction();
         if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
@@ -158,8 +139,6 @@
             state.transferMode = intent.getIntExtra(FileOperationService.EXTRA_OPERATION,
                     FileOperationService.OPERATION_COPY);
         }
-
-        return state;
     }
 
     @Override
@@ -180,7 +159,7 @@
         }
 
         if (showDrawer) {
-            setRootsDrawerOpen(true);
+            mNavigator.revealRootsDrawer(true);
         }
     }
 
@@ -217,74 +196,28 @@
     @Override
     protected void onPostCreate(Bundle savedInstanceState) {
         super.onPostCreate(savedInstanceState);
-        mDrawer.syncState();
-        updateActionBar();
-    }
-
-    public void setRootsDrawerOpen(boolean open) {
-        mDrawer.setOpen(open);
+        mDrawer.update();
+        mNavigator.update();
     }
 
     @Override
-    public void updateActionBar() {
-        if (mRootsToolbar != null) {
-            final String prompt = getIntent().getStringExtra(DocumentsContract.EXTRA_PROMPT);
-            if (prompt != null) {
-                mRootsToolbar.setTitle(prompt);
+    public String getDrawerTitle() {
+        String title = getIntent().getStringExtra(DocumentsContract.EXTRA_PROMPT);
+        if (title == null) {
+            if (mState.action == ACTION_OPEN ||
+                mState.action == ACTION_GET_CONTENT ||
+                mState.action == ACTION_OPEN_TREE) {
+                title = getResources().getString(R.string.title_open);
+            } else if (mState.action == ACTION_CREATE ||
+                       mState.action == ACTION_PICK_COPY_DESTINATION) {
+                title = getResources().getString(R.string.title_save);
             } else {
-                if (mState.action == ACTION_OPEN ||
-                    mState.action == ACTION_GET_CONTENT ||
-                    mState.action == ACTION_OPEN_TREE) {
-                    mRootsToolbar.setTitle(R.string.title_open);
-                } else if (mState.action == ACTION_CREATE ||
-                           mState.action == ACTION_PICK_COPY_DESTINATION) {
-                    mRootsToolbar.setTitle(R.string.title_save);
-                }
+                // If all else fails, just call it "Files".
+                title = getResources().getString(R.string.files_label);
             }
         }
 
-        if (mDrawer.isUnlocked()) {
-            mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
-            mToolbar.setNavigationContentDescription(R.string.drawer_open);
-            mToolbar.setNavigationOnClickListener(
-                    new View.OnClickListener() {
-                        @Override
-                        public void onClick(View v) {
-                            setRootsDrawerOpen(true);
-                        }
-                    });
-        } else {
-            mToolbar.setNavigationIcon(null);
-            mToolbar.setNavigationContentDescription(R.string.drawer_open);
-            mToolbar.setNavigationOnClickListener(null);
-        }
-
-        if (mSearchManager.isExpanded()) {
-            mToolbar.setTitle(null);
-            mToolbarStack.setVisibility(View.GONE);
-            mToolbarStack.setAdapter(null);
-        } else {
-            if (mState.stack.size() <= 1) {
-                mToolbar.setTitle(getCurrentRoot().title);
-                mToolbarStack.setVisibility(View.GONE);
-                mToolbarStack.setAdapter(null);
-            } else {
-                mToolbar.setTitle(null);
-                mToolbarStack.setVisibility(View.VISIBLE);
-                mToolbarStack.setAdapter(mStackAdapter);
-
-                mStackListener.mIgnoreNextNavigation = true;
-                mToolbarStack.setSelection(mStackAdapter.getCount() - 1);
-            }
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        boolean showMenu = super.onCreateOptionsMenu(menu);
-
-        expandMenus(menu);
-        return showMenu;
+        return title;
     }
 
     @Override
@@ -293,19 +226,24 @@
 
         final DocumentInfo cwd = getCurrentDirectory();
 
-        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
-        final MenuItem grid = menu.findItem(R.id.menu_grid);
-        final MenuItem list = menu.findItem(R.id.menu_list);
-        final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
-        final MenuItem settings = menu.findItem(R.id.menu_settings);
-
-        boolean recents = cwd == null;
         boolean picking = mState.action == ACTION_CREATE
                 || mState.action == ACTION_OPEN_TREE
                 || mState.action == ACTION_PICK_COPY_DESTINATION;
 
+        if (picking) {
+            // May already be hidden because the root
+            // doesn't support search.
+            mSearchManager.showMenu(false);
+        }
+
+        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
+        final MenuItem grid = menu.findItem(R.id.menu_grid);
+        final MenuItem list = menu.findItem(R.id.menu_list);
+        final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
+
+        boolean recents = cwd == null;
+
         createDir.setVisible(picking && !recents && cwd.isCreateSupported());
-        mSearchManager.showMenu(!picking);
 
         // No display options in recent directories
         if (picking && recents) {
@@ -314,7 +252,6 @@
         }
 
         fileSize.setVisible(fileSize.isVisible() && !picking);
-        settings.setVisible(false);
 
         if (mState.action == ACTION_CREATE) {
             final FragmentManager fm = getFragmentManager();
@@ -327,11 +264,6 @@
     }
 
     @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        return mDrawer.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
-    }
-
-    @Override
     void refreshDirectory(int anim) {
         final FragmentManager fm = getFragmentManager();
         final RootInfo root = getCurrentRoot();
@@ -382,17 +314,23 @@
     }
 
     void onSaveRequested(DocumentInfo replaceTarget) {
-        new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getExecutorForCurrentDirectory());
+        new ExistingFinishTask(this, replaceTarget.derivedUri)
+                .executeOnExecutor(getExecutorForCurrentDirectory());
     }
 
     void onSaveRequested(String mimeType, String displayName) {
-        new CreateFinishTask(mimeType, displayName).executeOnExecutor(getExecutorForCurrentDirectory());
+        new CreateFinishTask(this, mimeType, displayName)
+                .executeOnExecutor(getExecutorForCurrentDirectory());
     }
 
     @Override
     void onRootPicked(RootInfo root) {
         super.onRootPicked(root);
-        setRootsDrawerOpen(false);
+        mNavigator.revealRootsDrawer(false);
+    }
+
+    public void setRootsDrawerOpen(boolean open) {
+        mNavigator.revealRootsDrawer(open);
     }
 
     @Override
@@ -402,7 +340,8 @@
             openContainerDocument(doc);
         } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
             // Explicit file picked, return
-            new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getExecutorForCurrentDirectory());
+            new ExistingFinishTask(this, doc.derivedUri)
+                    .executeOnExecutor(getExecutorForCurrentDirectory());
         } else if (mState.action == ACTION_CREATE) {
             // Replace selected file
             SaveFragment.get(fm).setReplaceTarget(doc);
@@ -417,7 +356,8 @@
             for (int i = 0; i < size; i++) {
                 uris[i] = docs.get(i).derivedUri;
             }
-            new ExistingFinishTask(uris).executeOnExecutor(getExecutorForCurrentDirectory());
+            new ExistingFinishTask(this, uris)
+                    .executeOnExecutor(getExecutorForCurrentDirectory());
         }
     }
 
@@ -432,11 +372,10 @@
             // Should not be reached.
             throw new IllegalStateException("Invalid mState.action.");
         }
-        new PickFinishTask(result).executeOnExecutor(getExecutorForCurrentDirectory());
+        new PickFinishTask(this, result).executeOnExecutor(getExecutorForCurrentDirectory());
     }
 
-    @Override
-    void saveStackBlocking() {
+    void writeStackToRecentsBlocking() {
         final ContentResolver resolver = getContentResolver();
         final ContentValues values = new ContentValues();
 
@@ -497,69 +436,137 @@
         finish();
     }
 
+
     public static DocumentsActivity get(Fragment fragment) {
         return (DocumentsActivity) fragment.getActivity();
     }
 
-    private final class PickFinishTask extends AsyncTask<Void, Void, Void> {
+    /**
+     * Restores the stack from Recents for the specified package.
+     */
+    private static final class RestoreStackTask
+            extends PairedTask<DocumentsActivity, Void, Void> {
+
+        private volatile boolean mRestoredStack;
+        private volatile boolean mExternal;
+        private State mState;
+
+        public RestoreStackTask(DocumentsActivity activity) {
+            super(activity);
+            mState = activity.mState;
+        }
+
+        @Override
+        protected Void run(Void... params) {
+            if (DEBUG && !mState.stack.isEmpty()) {
+                Log.w(TAG, "Overwriting existing stack.");
+            }
+            RootsCache roots = DocumentsApplication.getRootsCache(mOwner);
+
+            String packageName = mOwner.getCallingPackageMaybeExtra();
+            Uri resumeUri = RecentsProvider.buildResume(packageName);
+            Cursor cursor = mOwner.getContentResolver().query(resumeUri, null, null, null, null);
+            try {
+                if (cursor.moveToFirst()) {
+                    mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0;
+                    final byte[] rawStack = cursor.getBlob(
+                            cursor.getColumnIndex(ResumeColumns.STACK));
+                    DurableUtils.readFromArray(rawStack, mState.stack);
+                    mRestoredStack = true;
+                }
+            } catch (IOException e) {
+                Log.w(TAG, "Failed to resume: " + e);
+            } finally {
+                IoUtils.closeQuietly(cursor);
+            }
+
+            if (mRestoredStack) {
+                // Update the restored stack to ensure we have freshest data
+                final Collection<RootInfo> matchingRoots = roots.getMatchingRootsBlocking(mState);
+                try {
+                    mState.stack.updateRoot(matchingRoots);
+                    mState.stack.updateDocuments(mOwner.getContentResolver());
+                } catch (FileNotFoundException e) {
+                    Log.w(TAG, "Failed to restore stack for package: " + packageName
+                            + " because of error: "+ e);
+                    mState.stack.reset();
+                    mRestoredStack = false;
+                }
+            }
+
+            return null;
+        }
+
+        @Override
+        protected void finish(Void result) {
+            mState.restored = true;
+            mOwner.refreshCurrentRootAndDirectory(ANIM_NONE);
+            mOwner.onStackRestored(mRestoredStack, mExternal);
+        }
+    }
+
+    private static final class PickFinishTask extends PairedTask<DocumentsActivity, Void, Void> {
         private final Uri mUri;
 
-        public PickFinishTask(Uri uri) {
+        public PickFinishTask(DocumentsActivity activity, Uri uri) {
+            super(activity);
             mUri = uri;
         }
 
         @Override
-        protected Void doInBackground(Void... params) {
-            saveStackBlocking();
+        protected Void run(Void... params) {
+            mOwner.writeStackToRecentsBlocking();
             return null;
         }
 
         @Override
-        protected void onPostExecute(Void result) {
-            onTaskFinished(mUri);
+        protected void finish(Void result) {
+            mOwner.onTaskFinished(mUri);
         }
     }
 
-    final class ExistingFinishTask extends AsyncTask<Void, Void, Void> {
+    private static final class ExistingFinishTask extends PairedTask<DocumentsActivity, Void, Void> {
         private final Uri[] mUris;
 
-        public ExistingFinishTask(Uri... uris) {
+        public ExistingFinishTask(DocumentsActivity activity, Uri... uris) {
+            super(activity);
             mUris = uris;
         }
 
         @Override
-        protected Void doInBackground(Void... params) {
-            saveStackBlocking();
+        protected Void run(Void... params) {
+            mOwner.writeStackToRecentsBlocking();
             return null;
         }
 
         @Override
-        protected void onPostExecute(Void result) {
-            onTaskFinished(mUris);
+        protected void finish(Void result) {
+            mOwner.onTaskFinished(mUris);
         }
     }
 
     /**
      * Task that creates a new document in the background.
      */
-    final class CreateFinishTask extends AsyncTask<Void, Void, Uri> {
+    private static final class CreateFinishTask extends PairedTask<DocumentsActivity, Void, Uri> {
         private final String mMimeType;
         private final String mDisplayName;
 
-        public CreateFinishTask(String mimeType, String displayName) {
+        public CreateFinishTask(DocumentsActivity activity, String mimeType, String displayName) {
+            super(activity);
             mMimeType = mimeType;
             mDisplayName = displayName;
         }
 
         @Override
-        protected void onPreExecute() {
-            setPending(true);
+        protected void prepare() {
+            mOwner.setPending(true);
         }
 
         @Override
-        protected Uri doInBackground(Void... params) {
-            final ContentResolver resolver = getContentResolver();
-            final DocumentInfo cwd = getCurrentDirectory();
+        protected Uri run(Void... params) {
+            final ContentResolver resolver = mOwner.getContentResolver();
+            final DocumentInfo cwd = mOwner.getCurrentDirectory();
 
             ContentProviderClient client = null;
             Uri childUri = null;
@@ -575,22 +582,22 @@
             }
 
             if (childUri != null) {
-                saveStackBlocking();
+                mOwner.writeStackToRecentsBlocking();
             }
 
             return childUri;
         }
 
         @Override
-        protected void onPostExecute(Uri result) {
+        protected void finish(Uri result) {
             if (result != null) {
-                onTaskFinished(result);
+                mOwner.onTaskFinished(result);
             } else {
                 Snackbars.makeSnackbar(
-                    DocumentsActivity.this, R.string.save_error, Snackbar.LENGTH_SHORT).show();
+                        mOwner, R.string.save_error, Snackbar.LENGTH_SHORT).show();
             }
 
-            setPending(false);
+            mOwner.setPending(false);
         }
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
index 547e343..9005442 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
@@ -63,6 +63,8 @@
 
     @Override
     public void onCreate() {
+        super.onCreate();
+
         final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
         final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsToolBar.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsToolbar.java
similarity index 86%
rename from packages/DocumentsUI/src/com/android/documentsui/DocumentsToolBar.java
rename to packages/DocumentsUI/src/com/android/documentsui/DocumentsToolbar.java
index 36b7646..7742cbf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsToolBar.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsToolbar.java
@@ -24,28 +24,28 @@
 /**
  * ToolBar of Documents UI.
  */
-public class DocumentsToolBar extends Toolbar {
+public class DocumentsToolbar extends Toolbar {
     interface OnActionViewCollapsedListener {
         void onActionViewCollapsed();
     }
 
     private OnActionViewCollapsedListener mOnActionViewCollapsedListener;
 
-    public DocumentsToolBar(Context context, AttributeSet attrs,
+    public DocumentsToolbar(Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
     }
 
-    public DocumentsToolBar(Context context, AttributeSet attrs,
+    public DocumentsToolbar(Context context, AttributeSet attrs,
             int defStyleAttr) {
         super(context, attrs, defStyleAttr);
     }
 
-    public DocumentsToolBar(Context context, AttributeSet attrs) {
+    public DocumentsToolbar(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
-    public DocumentsToolBar(Context context) {
+    public DocumentsToolbar(Context context) {
         super(context);
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
index 3302da9..d589d5e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
@@ -24,8 +24,6 @@
 import android.app.FragmentManager;
 import android.content.ActivityNotFoundException;
 import android.content.ClipData;
-import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
@@ -35,15 +33,10 @@
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
-import android.widget.BaseAdapter;
-import android.widget.Spinner;
 import android.widget.Toolbar;
 
-import com.android.documentsui.RecentsProvider.ResumeColumns;
 import com.android.documentsui.dirlist.DirectoryFragment;
 import com.android.documentsui.model.DocumentInfo;
-import com.android.documentsui.model.DurableUtils;
 import com.android.documentsui.model.RootInfo;
 import com.android.internal.util.Preconditions;
 
@@ -56,14 +49,8 @@
 public class DownloadsActivity extends BaseActivity {
     private static final String TAG = "DownloadsActivity";
 
-    private Toolbar mToolbar;
-    private Spinner mToolbarStack;
-
-    private ItemSelectedListener mStackListener;
-    private BaseAdapter mStackAdapter;
-
     public DownloadsActivity() {
-        super(R.layout.manage_roots_activity, TAG);
+        super(R.layout.downloads_activity, TAG);
     }
 
     @Override
@@ -72,73 +59,39 @@
 
         final Context context = this;
 
-        mDrawer = DrawerController.createDummy();
-
-        mToolbar = (Toolbar) findViewById(R.id.toolbar);
-        mToolbar.setTitleTextAppearance(context,
+        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+        toolbar.setTitleTextAppearance(context,
                 android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
 
-        mStackAdapter = new StackAdapter();
-        mStackListener = new ItemSelectedListener();
-        mToolbarStack = (Spinner) findViewById(R.id.stack);
-        mToolbarStack.setOnItemSelectedListener(mStackListener);
-
-        setActionBar(mToolbar);
-
         if (!mState.restored) {
             // In this case, we set the activity title in AsyncTask.onPostExecute(). To prevent
             // talkback from reading aloud the default title, we clear it here.
             setTitle("");
             final Uri rootUri = getIntent().getData();
-            new RestoreRootTask(rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
+            new RestoreRootTask(this, rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
         } else {
             refreshCurrentRootAndDirectory(ANIM_NONE);
         }
     }
 
     @Override
-    State buildState() {
-        State state = buildDefaultState();
-
+    void includeState(State state) {
         state.action = ACTION_MANAGE;
         state.acceptMimes = new String[] { "*/*" };
         state.allowMultiple = true;
         state.showSize = true;
         state.excludedAuthorities = getExcludedAuthorities();
-
-        return state;
     }
 
     @Override
     protected void onPostCreate(Bundle savedInstanceState) {
         super.onPostCreate(savedInstanceState);
-        updateActionBar();
+        mNavigator.update();
     }
 
     @Override
-    public void updateActionBar() {
-        // No navigation in manage root mode.
-        mToolbar.setNavigationIcon(null);
-        mToolbar.setNavigationOnClickListener(null);
-
-        if (mSearchManager.isExpanded()) {
-            mToolbar.setTitle(null);
-            mToolbarStack.setVisibility(View.GONE);
-            mToolbarStack.setAdapter(null);
-        } else {
-            if (mState.stack.size() <= 1) {
-                mToolbar.setTitle(getCurrentRoot().title);
-                mToolbarStack.setVisibility(View.GONE);
-                mToolbarStack.setAdapter(null);
-            } else {
-                mToolbar.setTitle(null);
-                mToolbarStack.setVisibility(View.VISIBLE);
-                mToolbarStack.setAdapter(mStackAdapter);
-
-                mStackListener.mIgnoreNextNavigation = true;
-                mToolbarStack.setSelection(mStackAdapter.getCount() - 1);
-            }
-        }
+    public String getDrawerTitle() {
+        return null;  // being and nothingness
     }
 
     @Override
@@ -147,17 +100,13 @@
 
         final MenuItem advanced = menu.findItem(R.id.menu_advanced);
         final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
-        final MenuItem newWindow = menu.findItem(R.id.menu_new_window);
         final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
         final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
-        final MenuItem search = menu.findItem(R.id.menu_search);
 
         advanced.setVisible(false);
         createDir.setVisible(false);
         pasteFromCb.setEnabled(false);
-        newWindow.setEnabled(false);
         fileSize.setVisible(false);
-        search.setVisible(false);
 
         Menus.disableHiddenItems(menu);
         return true;
@@ -184,29 +133,25 @@
 
     @Override
     public void onDocumentPicked(DocumentInfo doc, SiblingProvider siblings) {
-        final FragmentManager fm = getFragmentManager();
-        if (doc.isContainer()) {
-            openContainerDocument(doc);
-        } else {
-            // First try managing the document; we expect manager to filter
-            // based on authority, so we don't grant.
-            final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
-            manage.setData(doc.derivedUri);
+        Preconditions.checkArgument(!doc.isDirectory());
+        // First try managing the document; we expect manager to filter
+        // based on authority, so we don't grant.
+        final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
+        manage.setData(doc.derivedUri);
+
+        try {
+            startActivity(manage);
+        } catch (ActivityNotFoundException ex) {
+            // Fall back to viewing.
+            final Intent view = new Intent(Intent.ACTION_VIEW);
+            view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            view.setData(doc.derivedUri);
 
             try {
-                startActivity(manage);
-            } catch (ActivityNotFoundException ex) {
-                // Fall back to viewing
-                final Intent view = new Intent(Intent.ACTION_VIEW);
-                view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                view.setData(doc.derivedUri);
-
-                try {
-                    startActivity(view);
-                } catch (ActivityNotFoundException ex2) {
-                    Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT)
-                            .show();
-                }
+                startActivity(view);
+            } catch (ActivityNotFoundException ex2) {
+                Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT)
+                        .show();
             }
         }
     }
@@ -215,21 +160,6 @@
     public void onDocumentsPicked(List<DocumentInfo> docs) {}
 
     @Override
-    void saveStackBlocking() {
-        final ContentResolver resolver = getContentResolver();
-        final ContentValues values = new ContentValues();
-
-        final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
-
-        // Remember location for next app launch
-        final String packageName = getCallingPackageMaybeExtra();
-        values.clear();
-        values.put(ResumeColumns.STACK, rawStack);
-        values.put(ResumeColumns.EXTERNAL, 0);
-        resolver.insert(RecentsProvider.buildResume(packageName), values);
-    }
-
-    @Override
     void onTaskFinished(Uri... uris) {
         Log.d(TAG, "onFinished() " + Arrays.toString(uris));
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
index df3ac1b..bcf69c4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -22,8 +22,8 @@
 import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v4.widget.DrawerLayout.DrawerListener;
-import android.view.MenuItem;
 import android.view.View;
+import android.widget.Toolbar;
 
 /**
  * A facade over the various pieces comprising "roots fragment in a Drawer".
@@ -33,13 +33,10 @@
 abstract class DrawerController implements DrawerListener {
 
     abstract void setOpen(boolean open);
-    abstract void lockOpen();
-    abstract void lockClosed();
     abstract boolean isPresent();
     abstract boolean isOpen();
-    abstract boolean isUnlocked();
-    abstract void syncState();
-    abstract boolean onOptionsItemSelected(MenuItem item);
+    abstract void setTitle(String title);
+    abstract void update();
 
     /**
      * Returns a controller suitable for {@code Layout}.
@@ -53,6 +50,8 @@
         }
 
         View drawer = activity.findViewById(R.id.drawer_roots);
+        Toolbar toolbar = (Toolbar) activity.findViewById(R.id.roots_toolbar);
+
         ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                 activity,
                 layout,
@@ -60,7 +59,7 @@
                 R.string.drawer_open,
                 R.string.drawer_close);
 
-        return new RuntimeDrawerController(layout, drawer, toggle);
+        return new RuntimeDrawerController(layout, drawer, toggle, toolbar);
     }
 
     /**
@@ -78,9 +77,12 @@
         private final ActionBarDrawerToggle mToggle;
         private DrawerLayout mLayout;
         private View mDrawer;
+        private Toolbar mToolbar;
 
         public RuntimeDrawerController(
-                DrawerLayout layout, View drawer, ActionBarDrawerToggle toggle) {
+                DrawerLayout layout, View drawer, ActionBarDrawerToggle toggle,
+                Toolbar drawerToolbar) {
+            mToolbar = drawerToolbar;
             checkArgument(layout != null);
 
             mLayout = layout;
@@ -110,31 +112,16 @@
         }
 
         @Override
-        void syncState() {
+        void setTitle(String title) {
+            mToolbar.setTitle(title);
+        }
+
+        @Override
+        void update() {
             mToggle.syncState();
         }
 
         @Override
-        boolean isUnlocked() {
-            return mLayout.getDrawerLockMode(mDrawer) == DrawerLayout.LOCK_MODE_UNLOCKED;
-        }
-
-        @Override
-        void lockOpen() {
-            mLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
-        }
-
-        @Override
-        void lockClosed() {
-            mLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
-        }
-
-        @Override
-        boolean onOptionsItemSelected(MenuItem item) {
-            return false;
-        }
-
-        @Override
         public void onDrawerSlide(View drawerView, float slideOffset) {
             mToggle.onDrawerSlide(drawerView, slideOffset);
         }
@@ -163,14 +150,6 @@
         @Override
         void setOpen(boolean open) {}
 
-        @Override
-        void syncState() {}
-
-        @Override
-        void lockOpen() {}
-
-        @Override
-        void lockClosed() {}
 
         @Override
         boolean isOpen() {
@@ -178,19 +157,15 @@
         }
 
         @Override
-        boolean isUnlocked() {
-            return true;
-        }
-
-        @Override
         boolean isPresent() {
             return false;
         }
 
         @Override
-        boolean onOptionsItemSelected(MenuItem item) {
-            return false;
-        }
+        void setTitle(String title) {}
+
+        @Override
+        void update() {}
 
         @Override
         public void onDrawerSlide(View drawerView, float slideOffset) {}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Events.java b/packages/DocumentsUI/src/com/android/documentsui/Events.java
index 10a78b9..99b425e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Events.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Events.java
@@ -78,6 +78,27 @@
     }
 
     /**
+     * Whether or not the given keyCode represents a navigation keystroke (e.g. up, down, home).
+     *
+     * @param keyCode
+     * @return
+     */
+    public static boolean isNavigationKeyCode(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+            case KeyEvent.KEYCODE_MOVE_HOME:
+            case KeyEvent.KEYCODE_MOVE_END:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+
+    /**
      * Returns true if the "SHIFT" bit is set.
      */
     public static boolean hasShiftBit(int metaState) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 336888a..c81f342 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -39,10 +39,6 @@
 import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
-import android.widget.BaseAdapter;
-import android.widget.Spinner;
-import android.widget.Toolbar;
 
 import com.android.documentsui.OperationDialogFragment.DialogType;
 import com.android.documentsui.RecentsProvider.ResumeColumns;
@@ -53,8 +49,10 @@
 import com.android.documentsui.model.RootInfo;
 import com.android.documentsui.services.FileOperationService;
 
+import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -64,10 +62,6 @@
 
     public static final String TAG = "FilesActivity";
 
-    private Toolbar mToolbar;
-    private Spinner mToolbarStack;
-    private ItemSelectedListener mStackListener;
-    private BaseAdapter mStackAdapter;
     private DocumentClipper mClipper;
 
     public FilesActivity() {
@@ -78,17 +72,7 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        mToolbar = (Toolbar) findViewById(R.id.toolbar);
-
-        mStackAdapter = new StackAdapter();
-        mStackListener = new ItemSelectedListener();
-        mToolbarStack = (Spinner) findViewById(R.id.stack);
-        mToolbarStack.setOnItemSelectedListener(mStackListener);
-
-        setActionBar(mToolbar);
-
         mClipper = new DocumentClipper(this);
-        mDrawer = DrawerController.create(this);
 
         RootsFragment.show(getFragmentManager(), null);
 
@@ -104,22 +88,28 @@
             // loading or restoring the stack.
             //
             // When restoring from a stack, if a URI is present, it should only ever
-            // be a launch URI. Launch URIs support sensible activity management, but
-            // don't specify a real content target.
+            // be a launch URI, or a fake Uri from notifications.
+            // Launch URIs support sensible activity management, but don't specify a real
+            // content target.
             if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
-            checkState(uri == null || LauncherActivity.isLaunchUri(uri));
+            checkState(uri == null || uri.getAuthority() == null ||
+                    LauncherActivity.isLaunchUri(uri));
             refreshCurrentRootAndDirectory(ANIM_NONE);
+        } else if (intent.getAction() == Intent.ACTION_VIEW) {
+            checkArgument(uri != null);
+            new OpenUriForViewTask(this).executeOnExecutor(
+                    ProviderExecutor.forAuthority(uri.getAuthority()), uri);
         } else if (DocumentsContract.isRootUri(this, uri)) {
             if (DEBUG) Log.d(TAG, "Launching with root URI.");
             // If we've got a specific root to display, restore that root using a dedicated
             // authority. That way a misbehaving provider won't result in an ANR.
-            new RestoreRootTask(uri).executeOnExecutor(
+            new RestoreRootTask(this, uri).executeOnExecutor(
                     ProviderExecutor.forAuthority(uri.getAuthority()));
         } else {
             if (DEBUG) Log.d(TAG, "Launching into Home directory.");
             // If all else fails, try to load "Home" directory.
             final Uri homeUri = DocumentsContract.buildHomeUri();
-            new RestoreRootTask(homeUri).executeOnExecutor(
+            new RestoreRootTask(this, homeUri).executeOnExecutor(
                     ProviderExecutor.forAuthority(homeUri.getAuthority()));
         }
 
@@ -143,9 +133,7 @@
     }
 
     @Override
-    State buildState() {
-        State state = buildDefaultState();
-
+    void includeState(State state) {
         final Intent intent = getIntent();
 
         state.action = State.ACTION_BROWSE;
@@ -158,8 +146,6 @@
         if (stack != null) {
             state.stack = stack;
         }
-
-        return state;
     }
 
     @Override
@@ -170,11 +156,11 @@
         // serach. Why? Because this avoid an early (undesired) load of
         // the recents root...which is the default root in other activities.
         // In Files app "Home" is the default, but it is loaded async.
-        // updateActionBar will be called once Home root is loaded.
+        // update will be called once Home root is loaded.
         // Except while searching we need this call to ensure the
         // search bits get layed out correctly.
         if (mSearchManager.isSearching()) {
-            updateActionBar();
+            mNavigator.update();
         }
     }
 
@@ -194,67 +180,26 @@
     }
 
     @Override
-    public void updateActionBar() {
-        final RootInfo root = getCurrentRoot();
-
-        if (mDrawer.isPresent()) {
-            mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
-            mToolbar.setNavigationContentDescription(R.string.drawer_open);
-            mToolbar.setNavigationOnClickListener(
-                    new View.OnClickListener() {
-                        @Override
-                        public void onClick(View v) {
-                            mDrawer.setOpen(true);
-                        }
-                    });
-        } else {
-            mToolbar.setNavigationIcon(
-                    root != null ? root.loadToolbarIcon(mToolbar.getContext()) : null);
-            mToolbar.setNavigationContentDescription(R.string.drawer_open);
-            mToolbar.setNavigationOnClickListener(null);
-        }
-
-        if (mSearchManager.isExpanded()) {
-            mToolbar.setTitle(null);
-            mToolbarStack.setVisibility(View.GONE);
-            mToolbarStack.setAdapter(null);
-        } else {
-            if (mState.stack.size() <= 1) {
-                mToolbar.setTitle(root.title);
-                mToolbarStack.setVisibility(View.GONE);
-                mToolbarStack.setAdapter(null);
-            } else {
-                mToolbar.setTitle(null);
-                mToolbarStack.setVisibility(View.VISIBLE);
-                mToolbarStack.setAdapter(mStackAdapter);
-
-                mStackListener.mIgnoreNextNavigation = true;
-                mToolbarStack.setSelection(mStackAdapter.getCount() - 1);
-            }
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        boolean showMenu = super.onCreateOptionsMenu(menu);
-
-        expandMenus(menu);
-        return showMenu;
+    public String getDrawerTitle() {
+        return getResources().getString(R.string.files_label);
     }
 
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
 
-        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
-        final MenuItem newWindow = menu.findItem(R.id.menu_new_window);
-        final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
+        final RootInfo root = getCurrentRoot();
 
-        createDir.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
+        final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
+        final MenuItem settings = menu.findItem(R.id.menu_settings);
+        final MenuItem newWindow = menu.findItem(R.id.menu_new_window);
+
         createDir.setVisible(true);
         createDir.setEnabled(canCreateDirectory());
-
         pasteFromCb.setEnabled(mClipper.hasItemsToPaste());
+        settings.setVisible(root.hasSettings());
+        newWindow.setVisible(true);
 
         Menus.disableHiddenItems(menu, pasteFromCb);
         return true;
@@ -271,9 +216,10 @@
                 createNewWindow();
                 return true;
             case R.id.menu_paste_from_clipboard:
-                DirectoryFragment dir = DirectoryFragment.get(getFragmentManager());
-                dir = DirectoryFragment.get(getFragmentManager());
-                dir.pasteFromClipboard();
+                DirectoryFragment dir = getDirectoryFragment();
+                if (dir != null) {
+                    dir.pasteFromClipboard();
+                }
                 return true;
         }
 
@@ -288,7 +234,7 @@
         // With new multi-window mode we have to pick how we are launched.
         // By default we'd be launched in-place above the existing app.
         // By setting launch-to-side ActivityManager will open us to side.
-        if (inMultiWindowMode()) {
+        if (inMultiWindow()) {
             intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
         }
 
@@ -376,33 +322,41 @@
     @Override
     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
         DirectoryFragment dir;
+        // TODO: All key events should be statically bound using alphabeticShortcut.
+        // But not working.
         switch (keyCode) {
             case KeyEvent.KEYCODE_A:
-                dir = DirectoryFragment.get(getFragmentManager());
-                dir.selectAllFiles();
+                dir = getDirectoryFragment();
+                if (dir != null) {
+                    dir.selectAllFiles();
+                }
                 return true;
             case KeyEvent.KEYCODE_C:
-                // TODO: Should be statically bound using alphabeticShortcut. See b/21330356.
-                dir = DirectoryFragment.get(getFragmentManager());
-                dir.copySelectedToClipboard();
+                dir = getDirectoryFragment();
+                if (dir != null) {
+                    dir.copySelectedToClipboard();
+                }
                 return true;
             case KeyEvent.KEYCODE_V:
-                // TODO: Should be statically bound using alphabeticShortcut. See b/21330356.
-                dir = DirectoryFragment.get(getFragmentManager());
-                dir.pasteFromClipboard();
+                dir = getDirectoryFragment();
+                if (dir != null) {
+                    dir.pasteFromClipboard();
+                }
                 return true;
             default:
                 return super.onKeyShortcut(keyCode, event);
         }
     }
 
-    @Override
-    void saveStackBlocking() {
+    // Turns out only DocumentsActivity was ever calling saveStackBlocking.
+    // There may be a  case where we want to contribute entries from
+    // Behavior here in FilesActivity, but it isn't yet obvious.
+    // TODO: Contribute to recents, or remove this.
+    void writeStackToRecentsBlocking() {
         final ContentResolver resolver = getContentResolver();
         final ContentValues values = new ContentValues();
 
-        final byte[] rawStack = DurableUtils.writeToArrayOrNull(
-                getDisplayState().stack);
+        final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
 
         // Remember location for next app launch
         final String packageName = getCallingPackageMaybeExtra();
@@ -435,4 +389,48 @@
         setResult(Activity.RESULT_OK, intent);
         finish();
     }
+
+    /**
+     * Builds a stack for the specific Uris. Multi roots are not supported, as it's impossible
+     * to know which root to select. Also, the stack doesn't contain intermediate directories.
+     * It's primarly used for opening ZIP archives from Downloads app.
+     */
+    private static final class OpenUriForViewTask extends PairedTask<FilesActivity, Uri, Void> {
+
+        private final State mState;
+        public OpenUriForViewTask(FilesActivity activity) {
+            super(activity);
+            mState = activity.mState;
+        }
+
+        @Override
+        protected Void run(Uri... params) {
+            final Uri uri = params[0];
+
+            final RootsCache rootsCache = DocumentsApplication.getRootsCache(mOwner);
+            final String authority = uri.getAuthority();
+
+            final Collection<RootInfo> roots =
+                    rootsCache.getRootsForAuthorityBlocking(authority);
+            if (roots.isEmpty()) {
+                Log.e(TAG, "Failed to find root for the requested Uri: " + uri);
+                return null;
+            }
+
+            final RootInfo root = roots.iterator().next();
+            mState.stack.root = root;
+            try {
+                mState.stack.add(DocumentInfo.fromUri(mOwner.getContentResolver(), uri));
+            } catch (FileNotFoundException e) {
+                Log.e(TAG, "Failed to resolve DocumentInfo from Uri: " + uri);
+            }
+            mState.stack.add(mOwner.getRootDocumentBlocking(root));
+            return null;
+        }
+
+        @Override
+        protected void finish(Void result) {
+            mOwner.refreshCurrentRootAndDirectory(ANIM_NONE);
+        }
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ListItem.java b/packages/DocumentsUI/src/com/android/documentsui/ListItem.java
index 5c40f1b..6d6f21e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ListItem.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ListItem.java
@@ -20,7 +20,6 @@
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.TypedValue;
-import android.view.View;
 import android.widget.LinearLayout;
 
 /**
@@ -39,14 +38,11 @@
 
     @Override
     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
-        View indicator = findViewById(R.id.focus_indicator);
-        if (gainFocus) {
-            TypedValue color = new TypedValue();
-            getContext().getTheme().resolveAttribute(android.R.attr.colorAccent, color, true);
-            indicator.setBackgroundColor(color.data);
-        } else {
-            indicator.setBackgroundColor(android.R.color.transparent);
-        }
+        TypedValue color = new TypedValue();
+        int colorId = gainFocus ? android.R.attr.colorAccent : android.R.color.transparent;
+        getContext().getTheme().resolveAttribute(colorId, color, true);
+
+        findViewById(R.id.focus_indicator).setBackgroundColor(color.data);
         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index bae334b..172282a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -354,7 +354,7 @@
      * a single ROOT_OTHER bucket.
      */
     private static @Root int sanitizeRoot(Uri uri) {
-        if (LauncherActivity.isLaunchUri(uri)) {
+        if (uri == null || uri.getAuthority() == null || LauncherActivity.isLaunchUri(uri)) {
             return ROOT_NONE;
         }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
new file mode 100644
index 0000000..ff1940a
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_LEAVE;
+
+import android.annotation.Nullable;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import com.android.documentsui.model.DocumentInfo;
+import com.android.documentsui.model.RootInfo;
+
+/**
+ * A facade over the portions of the app and drawer toolbars.
+ */
+class NavigationView {
+
+    private static final String TAG = "NavigationView";
+
+    private final DrawerController mDrawer;
+    private final DocumentsToolbar mToolbar;
+    private final Spinner mBreadcrumb;
+    private final State mState;
+    private final NavigationView.Environment mEnv;
+    private final BreadcrumbAdapter mBreadcrumbAdapter;
+
+    private boolean mIgnoreNextNavigation;
+
+    public NavigationView(
+            DrawerController drawer,
+            DocumentsToolbar toolbar,
+            Spinner breadcrumb,
+            State state,
+            NavigationView.Environment env) {
+
+        mToolbar = toolbar;
+        mBreadcrumb = breadcrumb;
+        mDrawer = drawer;
+        mState = state;
+        mEnv = env;
+
+        mBreadcrumbAdapter = new BreadcrumbAdapter(mState, mEnv);
+        mToolbar.setNavigationOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        onNavigationIconClicked();
+                    }
+
+                });
+
+        mBreadcrumb.setOnItemSelectedListener(
+                new OnItemSelectedListener() {
+                    @Override
+                    public void onItemSelected(
+                            AdapterView<?> parent, View view, int position, long id) {
+                        onBreadcrumbItemSelected(position);
+                    }
+
+                    @Override
+                    public void onNothingSelected(AdapterView<?> parent) {}
+                });
+
+    }
+
+    private void onNavigationIconClicked() {
+        if (mDrawer.isPresent()) {
+            mDrawer.setOpen(true);
+        }
+    }
+
+    private void onBreadcrumbItemSelected(int position) {
+        if (mIgnoreNextNavigation) {
+            mIgnoreNextNavigation = false;
+            return;
+        }
+
+        while (mState.stack.size() > position + 1) {
+            mState.popDocument();
+        }
+        mEnv.refreshCurrentRootAndDirectory(ANIM_LEAVE);
+    }
+
+    void update() {
+
+        // TODO: Looks to me like this block is never getting hit.
+        if (mEnv.isSearchExpanded()) {
+            mToolbar.setTitle(null);
+            mBreadcrumb.setVisibility(View.GONE);
+            mBreadcrumb.setAdapter(null);
+            return;
+        }
+
+        mDrawer.setTitle(mEnv.getDrawerTitle());
+
+        mToolbar.setNavigationIcon(getActionBarIcon());
+        mToolbar.setNavigationContentDescription(R.string.drawer_open);
+
+        if (mState.stack.size() <= 1) {
+            showBreadcrumb(false);
+            String title = mEnv.getCurrentRoot().title;
+            if (DEBUG) Log.d(TAG, "New toolbar title is: " + title);
+            mToolbar.setTitle(title);
+        } else {
+            showBreadcrumb(true);
+            mToolbar.setTitle(null);
+            mIgnoreNextNavigation = true;
+            mBreadcrumb.setSelection(mBreadcrumbAdapter.getCount() - 1);
+        }
+
+        if (DEBUG) Log.d(TAG, "Final toolbar title is: " + mToolbar.getTitle());
+    }
+
+    private void showBreadcrumb(boolean visibility) {
+        if (visibility) {
+            mBreadcrumb.setVisibility(VISIBLE);
+            mBreadcrumb.setAdapter(mBreadcrumbAdapter);
+        } else {
+            mBreadcrumb.setVisibility(GONE);
+            mBreadcrumb.setAdapter(null);
+        }
+    }
+
+    // Hamburger if drawer is present, else root icon, or sad nullness.
+    private @Nullable Drawable getActionBarIcon() {
+        if (mDrawer.isPresent()) {
+            return mToolbar.getContext().getDrawable(R.drawable.ic_hamburger);
+        } else {
+            RootInfo root = mEnv.getCurrentRoot();
+            if (root != null) {
+                return root.loadToolbarIcon(mToolbar.getContext());
+            }
+        }
+        return null;
+    }
+
+    void revealRootsDrawer(boolean open) {
+        mDrawer.setOpen(open);
+    }
+
+    /**
+     * Class providing toolbar with runtime access to useful activity data.
+     */
+    static final class BreadcrumbAdapter extends BaseAdapter {
+
+        private Environment mEnv;
+        private State mState;
+
+        public BreadcrumbAdapter(State state, Environment env) {
+            mState = state;
+            mEnv = env;
+        }
+
+        @Override
+        public int getCount() {
+            return mState.stack.size();
+        }
+
+        @Override
+        public DocumentInfo getItem(int position) {
+            return mState.stack.get(mState.stack.size() - position - 1);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = LayoutInflater.from(parent.getContext())
+                        .inflate(R.layout.item_subdir_title, parent, false);
+            }
+
+            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+            final DocumentInfo doc = getItem(position);
+
+            if (position == 0) {
+                final RootInfo root = mEnv.getCurrentRoot();
+                title.setText(root.title);
+            } else {
+                title.setText(doc.displayName);
+            }
+
+            return convertView;
+        }
+
+        @Override
+        public View getDropDownView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = LayoutInflater.from(parent.getContext())
+                        .inflate(R.layout.item_subdir, parent, false);
+            }
+
+            final ImageView subdir = (ImageView) convertView.findViewById(R.id.subdir);
+            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+            final DocumentInfo doc = getItem(position);
+
+            if (position == 0) {
+                final RootInfo root = mEnv.getCurrentRoot();
+                title.setText(root.title);
+                subdir.setVisibility(View.GONE);
+            } else {
+                title.setText(doc.displayName);
+                subdir.setVisibility(View.VISIBLE);
+            }
+
+            return convertView;
+        }
+    }
+
+    interface Environment {
+        RootInfo getCurrentRoot();
+        String getDrawerTitle();
+        void refreshCurrentRootAndDirectory(int animation);
+        boolean isSearchExpanded();
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
index 5dc4f57..d601550 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
@@ -19,17 +19,12 @@
 import static android.os.Environment.isStandardDirectory;
 import static com.android.documentsui.Shared.DEBUG;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
-import android.content.ContentProvider;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -48,11 +43,15 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
 /**
  * Activity responsible for handling {@link Intent#ACTION_OPEN_EXTERNAL_DOCUMENT}.
  */
 public class OpenExternalDirectoryActivity extends Activity {
-    private static final String TAG = "OpenExternalDirectoryActivity";
+    private static final String TAG = "OpenExternalDirectory";
     private static final String FM_TAG = "open_external_directory";
     private static final String EXTERNAL_STORAGE_AUTH = "com.android.externalstorage.documents";
     private static final String EXTRA_FILE = "com.android.documentsui.FILE";
@@ -209,7 +208,7 @@
         return intent;
     }
 
-    private static class OpenExternalDirectoryDialogFragment extends DialogFragment {
+    public static class OpenExternalDirectoryDialogFragment extends DialogFragment {
 
         private File mFile;
         private String mVolumeLabel;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PairedTask.java b/packages/DocumentsUI/src/com/android/documentsui/PairedTask.java
new file mode 100644
index 0000000..b74acb8
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/PairedTask.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.app.Activity;
+import android.os.AsyncTask;
+
+/**
+ * An {@link AsyncTask} that guards work with checks that a paired {@link Activity}
+ * is still alive. Instances of this class make no progress.
+ *
+ * <p>Use this type of task for greater safety when executing tasks that might complete
+ * after an Activity is destroyed.
+ *
+ * <p>Also useful as tasks can be static, limiting scope, but still have access to
+ * the owning class (by way the A template and the mActivity field).
+ *
+ * @template Owner Activity type.
+ * @template Input input type
+ * @template Output output type
+ */
+abstract class PairedTask<Owner extends Activity, Input, Output>
+        extends AsyncTask<Input, Void, Output> {
+
+    protected final Owner mOwner;
+
+    public PairedTask(Owner owner) {
+        mOwner = owner;
+    }
+
+    /** Called prior to run being executed. Analogous to {@link AsyncTask#onPreExecute} */
+    void prepare() {}
+
+    /** Analogous to {@link AsyncTask#doInBackground} */
+    abstract Output run(Input... input);
+
+    /** Analogous to {@link AsyncTask#onPostExecute} */
+    abstract void finish(Output output);
+
+    @Override
+    final protected void onPreExecute() {
+        if (mOwner.isDestroyed()) {
+            return;
+        }
+        prepare();
+    }
+
+    @Override
+    final protected Output doInBackground(Input... input) {
+        if (mOwner.isDestroyed()) {
+            return null;
+        }
+        return run(input);
+    }
+
+    @Override
+    final protected void onPostExecute(Output result) {
+        if (mOwner.isDestroyed()) {
+            return;
+        }
+        finish(result);
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java b/packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java
new file mode 100644
index 0000000..9048b9d
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/RestoreRootTask.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.net.Uri;
+import android.provider.DocumentsContract;
+import android.util.Log;
+
+import com.android.documentsui.model.RootInfo;
+
+final class RestoreRootTask extends PairedTask<BaseActivity, Void, RootInfo> {
+    private static final String TAG = "RestoreRootTask";
+
+    private final Uri mRootUri;
+
+    public RestoreRootTask(BaseActivity activity, Uri rootUri) {
+        super(activity);
+        mRootUri = rootUri;
+    }
+
+    @Override
+    protected RootInfo run(Void... params) {
+        String rootId = DocumentsContract.getRootId(mRootUri);
+        return mOwner.mRoots.getRootOneshot(mRootUri.getAuthority(), rootId);
+    }
+
+    @Override
+    protected void finish(RootInfo root) {
+        mOwner.mState.restored = true;
+
+        if (root != null) {
+            mOwner.onRootPicked(root);
+        } else {
+            Log.w(TAG, "Failed to find root: " + mRootUri);
+            mOwner.finish();
+        }
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 21e7566..29a72b8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -48,6 +48,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -159,6 +160,24 @@
         }
     }
 
+    /**
+     * Load roots from a stopped authority. Normal {@link UpdateTask} passes
+     * ignore stopped applications.
+     */
+    private void loadStoppedAuthority(String authority) {
+        final ContentResolver resolver = mContext.getContentResolver();
+        synchronized (mLock) {
+            if (!mStoppedAuthorities.contains(authority)) {
+                return;
+            }
+            if (DEBUG) {
+                Log.d(TAG, "Loading stopped authority " + authority);
+            }
+            mRoots.putAll(authority, loadRootsForAuthority(resolver, authority));
+            mStoppedAuthorities.remove(authority);
+        }
+    }
+
     private class UpdateTask extends AsyncTask<Void, Void, Void> {
         private final String mFilterPackage;
 
@@ -360,6 +379,19 @@
         }
     }
 
+    /**
+     * Returns a list of roots for the specified authority. If not found, then
+     * an empty list is returned.
+     */
+    public Collection<RootInfo> getRootsForAuthorityBlocking(String authority) {
+        waitForFirstLoad();
+        loadStoppedAuthority(authority);
+        synchronized (mLock) {
+            final Collection<RootInfo> roots = mRoots.get(authority);
+            return roots != null ? roots : Collections.<RootInfo>emptyList();
+        }
+    }
+
     public void setOnCacheUpdateListener(OnCacheUpdateListener cacheUpdateListener) {
         mCacheUpdateListener = cacheUpdateListener;
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index c2aeb86..26bda31 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -92,7 +92,6 @@
         mList = (ListView) view.findViewById(android.R.id.list);
         mList.setOnItemClickListener(mItemListener);
         mList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
-
         return view;
     }
 
@@ -161,6 +160,7 @@
                 final RootInfo testRoot = ((RootItem) item).root;
                 if (Objects.equals(testRoot, root)) {
                     mList.setItemChecked(i, true);
+                    mList.setSelection(i);
                     return;
                 }
             }
@@ -180,9 +180,9 @@
             Item item = mAdapter.getItem(position);
             if (item instanceof RootItem) {
                 BaseActivity activity = BaseActivity.get(RootsFragment.this);
-                RootInfo info = ((RootItem) item).root;
-                Metrics.logRootVisited(getActivity(), info);
-                activity.onRootPicked(info);
+                RootInfo newRoot = ((RootItem) item).root;
+                Metrics.logRootVisited(getActivity(), newRoot);
+                activity.onRootPicked(newRoot);
             } else if (item instanceof AppItem) {
                 DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this);
                 ResolveInfo info = ((AppItem) item).info;
@@ -302,8 +302,10 @@
             for (final RootInfo root : roots) {
                 final RootItem item = new RootItem(root);
                 if (root.isLibrary()) {
+                    if (DEBUG) Log.d(TAG, "Adding " + root + " as library.");
                     libraries.add(item);
                 } else {
+                    if (DEBUG) Log.d(TAG, "Adding " + root + " as non-library.");
                     others.add(item);
                 }
             }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SearchManager.java b/packages/DocumentsUI/src/com/android/documentsui/SearchManager.java
index fb585a6..69f54c7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SearchManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SearchManager.java
@@ -47,7 +47,7 @@
     private boolean mSearchExpanded;
     private boolean mIgnoreNextClose;
 
-    private DocumentsToolBar mActionBar;
+    private DocumentsToolbar mActionBar;
     private MenuItem mMenu;
     private SearchView mView;
 
@@ -59,7 +59,7 @@
         mListener = listener;
     }
 
-    public void install(DocumentsToolBar actionBar) {
+    public void install(DocumentsToolbar actionBar) {
         assert (mActionBar == null);
         mActionBar = actionBar;
         mMenu = actionBar.getSearchMenu();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index 28f7432..d141de6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -158,9 +158,14 @@
         out.writeInt(mStackTouched ? 1 : 0);
     }
 
-    public static final Creator<State> CREATOR = new Creator<State>() {
+    public static final ClassLoaderCreator<State> CREATOR = new ClassLoaderCreator<State>() {
         @Override
         public State createFromParcel(Parcel in) {
+            return createFromParcel(in, null);
+        }
+
+        @Override
+        public State createFromParcel(Parcel in, ClassLoader loader) {
             final State state = new State();
             state.action = in.readInt();
             state.acceptMimes = in.readStringArray();
@@ -174,9 +179,9 @@
             state.restored = in.readInt() != 0;
             DurableUtils.readFromParcel(in, state.stack);
             state.currentSearch = in.readString();
-            in.readMap(state.dirState, null);
-            in.readList(state.selectedDocumentsForCopy, null);
-            in.readList(state.excludedAuthorities, null);
+            in.readMap(state.dirState, loader);
+            in.readList(state.selectedDocumentsForCopy, loader);
+            in.readList(state.excludedAuthorities, loader);
             state.openableOnly = in.readInt() != 0;
             state.mStackTouched = in.readInt() != 0;
             return state;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 2aabc99..70bee3c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -66,6 +66,7 @@
 import android.view.ActionMode;
 import android.view.DragEvent;
 import android.view.GestureDetector;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -99,7 +100,6 @@
 import com.android.documentsui.model.RootInfo;
 import com.android.documentsui.services.FileOperationService;
 import com.android.documentsui.services.FileOperations;
-
 import com.google.common.collect.Lists;
 
 import java.util.ArrayList;
@@ -117,8 +117,8 @@
 
     public static final int ANIM_NONE = 1;
     public static final int ANIM_SIDE = 2;
-    public static final int ANIM_DOWN = 3;
-    public static final int ANIM_UP = 4;
+    public static final int ANIM_LEAVE = 3;
+    public static final int ANIM_ENTER = 4;
 
     public static final int REQUEST_COPY_DESTINATION = 1;
 
@@ -151,7 +151,6 @@
     private String mStateKey;
 
     private int mLastSortOrder = SORT_ORDER_UNKNOWN;
-    private boolean mLastShowSize;
     private DocumentsAdapter mAdapter;
     private LoaderCallbacks<DirectoryResult> mCallbacks;
     private FragmentTuner mTuner;
@@ -428,7 +427,6 @@
 
     private void updateDisplayState() {
         State state = getDisplayState();
-        mLastShowSize = state.showSize;
         updateLayout(state.derivedMode);
         mRecView.setAdapter(mAdapter);
     }
@@ -529,6 +527,9 @@
             final Cursor cursor = mModel.getItem(modelId);
             checkNotNull(cursor, "Cursor cannot be null.");
 
+            // TODO: Should this be happening in onSelectionChanged? Technically this callback is
+            // triggered on "silent" selection updates (i.e. we might be reacting to unfinalized
+            // selection changes here)
             final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
             if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) {
                 mNoDeleteCount += selected ? 1 : -1;
@@ -827,7 +828,6 @@
     @Override
     public void initDocumentHolder(DocumentHolder holder) {
         holder.addEventListener(mItemEventListener);
-        holder.addOnKeyListener(mSelectionManager);
     }
 
     @Override
@@ -853,27 +853,28 @@
     }
 
     private void showEmptyDirectory() {
-        showEmptyView(R.string.empty);
+        showEmptyView(R.string.empty, R.drawable.cabinet);
     }
 
     private void showNoResults(RootInfo root) {
         CharSequence msg = getContext().getResources().getText(R.string.no_results);
-        showEmptyView(String.format(String.valueOf(msg), root.title));
+        showEmptyView(String.format(String.valueOf(msg), root.title), R.drawable.cabinet);
     }
 
-    // Shows an error indicating documents couldn't be queried.
     private void showQueryError() {
-        showEmptyView(R.string.query_error);
+        showEmptyView(R.string.query_error, R.drawable.hourglass);
     }
 
-    private void showEmptyView(@StringRes int id) {
-        showEmptyView(getContext().getResources().getText(id));
+    private void showEmptyView(@StringRes int id, int drawable) {
+        showEmptyView(getContext().getResources().getText(id), drawable);
     }
 
-    private void showEmptyView(CharSequence msg) {
+    private void showEmptyView(CharSequence msg, int drawable) {
         View content = mEmptyView.findViewById(R.id.content);
         TextView msgView = (TextView) mEmptyView.findViewById(R.id.message);
+        ImageView imageView = (ImageView) mEmptyView.findViewById(R.id.artwork);
         msgView.setText(msg);
+        imageView.setImageResource(drawable);
 
         content.animate().cancel();  // cancel any ongoing animations
 
@@ -1230,7 +1231,12 @@
     private class ItemEventListener implements DocumentHolder.EventListener {
         @Override
         public boolean onActivate(DocumentHolder doc) {
-            handleViewItem(doc.modelId);
+            // Toggle selection if we're in selection mode, othewise, view item.
+            if (mSelectionManager.hasSelection()) {
+                mSelectionManager.toggleSelection(doc.modelId);
+            } else {
+                handleViewItem(doc.modelId);
+            }
             return true;
         }
 
@@ -1240,6 +1246,128 @@
             mSelectionManager.setSelectionRangeBegin(doc.getAdapterPosition());
             return true;
         }
+
+        @Override
+        public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event) {
+            // Only handle key-down events. This is simpler, consistent with most other UIs, and
+            // enables the handling of repeated key events from holding down a key.
+            if (event.getAction() != KeyEvent.ACTION_DOWN) {
+                return false;
+            }
+
+            boolean handled = false;
+            if (Events.isNavigationKeyCode(keyCode)) {
+                // Find the target item and focus it.
+                int endPos = findTargetPosition(doc.itemView, keyCode);
+
+                if (endPos != RecyclerView.NO_POSITION) {
+                    focusItem(endPos);
+
+                    // Handle any necessary adjustments to selection.
+                    boolean extendSelection = event.isShiftPressed();
+                    if (extendSelection) {
+                        int startPos = doc.getAdapterPosition();
+                        mSelectionManager.selectRange(startPos, endPos);
+                    }
+                    handled = true;
+                }
+            } else {
+                // Handle enter key events
+                if (keyCode == KeyEvent.KEYCODE_ENTER) {
+                    handled = onActivate(doc);
+                }
+            }
+
+            return handled;
+        }
+
+        /**
+         * Finds the destination position where the focus should land for a given navigation event.
+         *
+         * @param view The view that received the event.
+         * @param keyCode The key code for the event.
+         * @return The adapter position of the destination item. Could be RecyclerView.NO_POSITION.
+         */
+        private int findTargetPosition(View view, int keyCode) {
+            if (keyCode == KeyEvent.KEYCODE_MOVE_HOME) {
+                return 0;
+            }
+
+            if (keyCode == KeyEvent.KEYCODE_MOVE_END) {
+                return mAdapter.getItemCount() - 1;
+            }
+
+            // Find a navigation target based on the arrow key that the user pressed.
+            int searchDir = -1;
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_DPAD_UP:
+                    searchDir = View.FOCUS_UP;
+                    break;
+                case KeyEvent.KEYCODE_DPAD_DOWN:
+                    searchDir = View.FOCUS_DOWN;
+                    break;
+                case KeyEvent.KEYCODE_DPAD_LEFT:
+                    searchDir = View.FOCUS_LEFT;
+                    break;
+                case KeyEvent.KEYCODE_DPAD_RIGHT:
+                    searchDir = View.FOCUS_RIGHT;
+                    break;
+            }
+
+            if (searchDir != -1) {
+                View targetView = view.focusSearch(searchDir);
+                // TargetView can be null, for example, if the user pressed <down> at the bottom
+                // of the list.
+                if (targetView != null) {
+                    // Ignore navigation targets that aren't items in the RecyclerView.
+                    if (targetView.getParent() == mRecView) {
+                        return mRecView.getChildAdapterPosition(targetView);
+                    }
+                }
+            }
+
+            return RecyclerView.NO_POSITION;
+        }
+
+        /**
+         * Requests focus for the item in the given adapter position, scrolling the RecyclerView if
+         * necessary.
+         *
+         * @param pos
+         */
+        public void focusItem(final int pos) {
+            // If the item is already in view, focus it; otherwise, scroll to it and focus it.
+            RecyclerView.ViewHolder vh = mRecView.findViewHolderForAdapterPosition(pos);
+            if (vh != null) {
+                vh.itemView.requestFocus();
+            } else {
+                mRecView.smoothScrollToPosition(pos);
+                // Set a one-time listener to request focus when the scroll has completed.
+                mRecView.addOnScrollListener(
+                    new RecyclerView.OnScrollListener() {
+                        @Override
+                        public void onScrollStateChanged (RecyclerView view, int newState) {
+                            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+                                // When scrolling stops, find the item and focus it.
+                                RecyclerView.ViewHolder vh =
+                                        view.findViewHolderForAdapterPosition(pos);
+                                if (vh != null) {
+                                    vh.itemView.requestFocus();
+                                } else {
+                                    // This might happen in weird corner cases, e.g. if the user is
+                                    // scrolling while a delete operation is in progress.  In that
+                                    // case, just don't attempt to focus the missing item.
+                                    Log.w(
+                                        TAG, "Unable to focus position " + pos + " after a scroll");
+                                }
+                                view.removeOnScrollListener(this);
+                            }
+                        }
+                    });
+            }
+        }
+
+
     }
 
     private final class ModelUpdateListener implements Model.UpdateListener {
@@ -1404,12 +1532,12 @@
             case ANIM_SIDE:
                 args.putBoolean(EXTRA_IGNORE_STATE, true);
                 break;
-            case ANIM_DOWN:
+            case ANIM_ENTER:
                 args.putBoolean(EXTRA_IGNORE_STATE, true);
-                ft.setCustomAnimations(R.animator.dir_down, R.animator.dir_frozen);
+                ft.setCustomAnimations(R.animator.dir_enter, R.animator.dir_frozen);
                 break;
-            case ANIM_UP:
-                ft.setCustomAnimations(R.animator.dir_frozen, R.animator.dir_up);
+            case ANIM_LEAVE:
+                ft.setCustomAnimations(R.animator.dir_frozen, R.animator.dir_leave);
                 break;
         }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
index 8acf1af..1bfc6e9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -84,13 +84,7 @@
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         // Event listener should always be set.
         checkNotNull(mEventListener);
-        // Intercept enter key-up events, and treat them as clicks.  Forward other events.
-        if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) {
-            return mEventListener.onActivate(this);
-        } else if (mKeyListener != null) {
-            return mKeyListener.onKey(v, keyCode, event);
-        }
-        return false;
+        return mEventListener.onKey(this,  keyCode,  event);
     }
 
     public void addEventListener(DocumentHolder.EventListener listener) {
@@ -159,15 +153,29 @@
      */
     interface EventListener {
         /**
+         * Handles activation events on the document holder.
+         *
          * @param doc The target DocumentHolder
          * @return Whether the event was handled.
          */
         public boolean onActivate(DocumentHolder doc);
 
         /**
+         * Handles selection events on the document holder.
+         *
          * @param doc The target DocumentHolder
          * @return Whether the event was handled.
          */
         public boolean onSelect(DocumentHolder doc);
+
+        /**
+         * Handles key events on the document holder.
+         *
+         * @param doc The target DocumentHolder.
+         * @param keyCode Key code for the event.
+         * @param event KeyEvent for the event.
+         * @return Whether the event was handled.
+         */
+        public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event);
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
index 880da9c..69a6711 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
@@ -29,7 +29,6 @@
 import android.view.ViewGroup;
 
 import com.android.documentsui.State;
-
 import com.google.common.collect.Sets;
 
 import java.util.ArrayList;
@@ -42,7 +41,7 @@
  */
 final class ModelBackedDocumentsAdapter extends DocumentsAdapter {
 
-    private static final String TAG = "ModelBackedDocumentsAdapter";
+    private static final String TAG = "ModelBackedDocuments";
     public static final int ITEM_TYPE_DOCUMENT = 1;
     public static final int ITEM_TYPE_DIRECTORY = 2;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index 71e87cb..516b25e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -34,7 +34,6 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
-import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 
@@ -57,7 +56,7 @@
  * Additionally it can be configured to restrict selection to a single element, @see
  * #setSelectMode.
  */
-public final class MultiSelectManager implements View.OnKeyListener {
+public final class MultiSelectManager {
 
     /** Selection mode for multiple select. **/
     public static final int MODE_MULTIPLE = 0;
@@ -129,9 +128,11 @@
 
                     @Override
                     public void onChanged() {
-                        // TODO: This is causing b/22765812
-                        mSelection.clear();
                         mModelIds = mAdapter.getModelIds();
+
+                        // Update the selection to remove any disappeared IDs.
+                        mSelection.cancelProvisionalSelection();
+                        mSelection.intersect(mModelIds);
                     }
 
                     @Override
@@ -237,7 +238,8 @@
     }
 
     /**
-     * Clears the selection, without notifying anyone.
+     * Clears the selection, without notifying selection listeners. UI elements still need to be
+     * notified about state changes so that they can update their appearance.
      */
     private void clearSelectionQuietly() {
         mRanger = null;
@@ -246,10 +248,10 @@
             return;
         }
 
-        Selection intermediateSelection = getSelection(new Selection());
+        Selection oldSelection = getSelection(new Selection());
         mSelection.clear();
 
-        for (String id: intermediateSelection.getAll()) {
+        for (String id: oldSelection.getAll()) {
             notifyItemStateChanged(id, false);
         }
     }
@@ -332,21 +334,7 @@
         if (mSelection.contains(modelId)) {
             changed = attemptDeselect(modelId);
         } else {
-            boolean canSelect = notifyBeforeItemStateChange(modelId, true);
-            if (!canSelect) {
-                return;
-            }
-            if (mSingleSelect && hasSelection()) {
-                clearSelectionQuietly();
-            }
-
-            // Here we're already in selection mode. In that case
-            // When a simple click/tap (without SHIFT) creates causes
-            // an item to be selected.
-            // By recreating Ranger at this point, we allow the user to create
-            // multiple separate contiguous ranges with SHIFT+Click & Click.
-            selectAndNotify(modelId);
-            changed = true;
+            changed = attemptSelect(modelId);
         }
 
         if (changed) {
@@ -355,9 +343,46 @@
     }
 
     /**
-     * Sets the magic location at which a selection range begins. This
-     * value is consulted when determining how to extend, and modify
-     * selection ranges.
+     * Handle a range selection event.
+     * <li> If the MSM is currently in single-select mode, only the last item in the range will
+     * actually be selected.
+     * <li>If a range selection is not already active, one will be started, and the given range of
+     * items will be selected.  The given startPos becomes the anchor for the range selection.
+     * <li>If a range selection is already active, the anchor is not changed. The range is extended
+     * from its current anchor to endPos.
+     *
+     * @param startPos
+     * @param endPos
+     */
+    public void selectRange(int startPos, int endPos) {
+        // In single-select mode, just select the last item in the range.
+        if (mSingleSelect) {
+            attemptSelect(mAdapter.getModelId(endPos));
+            return;
+        }
+
+        // In regular (i.e. multi-select) mode
+        if (!isRangeSelectionActive()) {
+            // If a range selection isn't active, start one up
+            attemptSelect(mAdapter.getModelId(startPos));
+            setSelectionRangeBegin(startPos);
+        }
+        // Extend the range selection
+        mRanger.snapSelection(endPos);
+        notifySelectionChanged();
+    }
+
+    /**
+     * @return Whether or not there is a current range selection active.
+     */
+    private boolean isRangeSelectionActive() {
+        return mRanger != null;
+    }
+
+    /**
+     * Sets the magic location at which a selection range begins (the selection anchor). This value
+     * is consulted when determining how to extend, and modify selection ranges. Calling this when a
+     * range selection is active will reset the range selection.
      *
      * @throws IllegalStateException if {@code position} is not already be selected
      * @param position
@@ -432,6 +457,24 @@
         }
     }
 
+    /**
+     * @param id
+     * @return True if the update was applied.
+     */
+    private boolean attemptSelect(String id) {
+        checkArgument(id != null);
+        boolean canSelect = notifyBeforeItemStateChange(id, true);
+        if (!canSelect) {
+            return false;
+        }
+        if (mSingleSelect && hasSelection()) {
+            clearSelectionQuietly();
+        }
+
+        selectAndNotify(id);
+        return true;
+    }
+
     private boolean notifyBeforeItemStateChange(String id, boolean nextState) {
         int lastListener = mCallbacks.size() - 1;
         for (int i = lastListener; i > -1; i--) {
@@ -784,12 +827,10 @@
         Point createAbsolutePoint(Point relativePoint);
         Rect getAbsoluteRectForChildViewAt(int index);
         int getAdapterPositionAt(int index);
-        int getAdapterPositionForChildView(View view);
         int getColumnCount();
         int getRowCount();
         int getChildCount();
         int getVisibleChildCount();
-        void focusItem(int position);
         /**
          * Layout items are excluded from the GridModel.
          */
@@ -810,17 +851,8 @@
         }
 
         @Override
-        public int getAdapterPositionForChildView(View view) {
-            if (view.getParent() == mView) {
-                return mView.getChildAdapterPosition(view);
-            } else {
-                return RecyclerView.NO_POSITION;
-            }
-        }
-
-        @Override
         public int getAdapterPositionAt(int index) {
-            return getAdapterPositionForChildView(mView.getChildAt(index));
+            return mView.getChildAdapterPosition(mView.getChildAt(index));
         }
 
         @Override
@@ -919,39 +951,6 @@
         }
 
         @Override
-        public void focusItem(final int pos) {
-            // If the item is already in view, focus it; otherwise, scroll to it and focus it.
-            RecyclerView.ViewHolder vh = mView.findViewHolderForAdapterPosition(pos);
-            if (vh != null) {
-                vh.itemView.requestFocus();
-            } else {
-                mView.smoothScrollToPosition(pos);
-                // Set a one-time listener to request focus when the scroll has completed.
-                mView.addOnScrollListener(
-                    new RecyclerView.OnScrollListener() {
-                        @Override
-                        public void onScrollStateChanged (RecyclerView view, int newState) {
-                            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
-                                // When scrolling stops, find the item and focus it.
-                                RecyclerView.ViewHolder vh =
-                                        view.findViewHolderForAdapterPosition(pos);
-                                if (vh != null) {
-                                    vh.itemView.requestFocus();
-                                } else {
-                                    // This might happen in weird corner cases, e.g. if the user is
-                                    // scrolling while a delete operation is in progress.  In that
-                                    // case, just don't attempt to focus the missing item.
-                                    Log.w(
-                                        TAG, "Unable to focus position " + pos + " after a scroll");
-                                }
-                                view.removeOnScrollListener(this);
-                            }
-                        }
-                    });
-            }
-        }
-
-        @Override
         public boolean isLayoutItem(int pos) {
             // The band selection model only operates on documents and directories. Exclude other
             // types of adapter items (e.g. whitespace items like dividers).
@@ -1905,99 +1904,4 @@
             return true;
         }
     }
-
-    // TODO: Might have to move this to a more global level.  e.g. What should happen if the
-    // user taps a file and then presses shift-down?  Currently the RecyclerView never even sees
-    // the key event.  Perhaps install a global key handler to catch those events while in
-    // selection mode?
-    @Override
-    public boolean onKey(View view, int keyCode, KeyEvent event) {
-        // Listen for key-down events.  This allows the handler to respond appropriately when
-        // the user holds down the arrow keys for navigation.
-        if (event.getAction() != KeyEvent.ACTION_DOWN) {
-            return false;
-        }
-
-        // Here we unpack information from the event and pass it to an more
-        // easily tested method....basically eliminating the need to synthesize
-        // events and views and so on in our tests.
-        int endPos = findTargetPosition(view, keyCode);
-        if (endPos == RecyclerView.NO_POSITION) {
-            // If there is no valid navigation target, don't handle the keypress.
-            return false;
-        }
-
-        int startPos = mEnvironment.getAdapterPositionForChildView(view);
-
-        return changeFocus(startPos, endPos, event.isShiftPressed());
-    }
-
-    /**
-     * @param startPosition The current focus position.
-     * @param targetPosition The adapter position to focus.
-     * @param extendSelection
-     */
-    @VisibleForTesting
-    boolean changeFocus(int startPosition, int targetPosition, boolean extendSelection) {
-        // Focus the new file.
-        mEnvironment.focusItem(targetPosition);
-
-        if (extendSelection) {
-            if (mSingleSelect) {
-                // We're in single select and have an existing selection.
-                // Our best guess as to what the user would expect is to advance the selection.
-                clearSelection();
-                toggleSelection(targetPosition);
-            } else {
-                if (!hasSelection()) {
-                    // No selection - start a selection when the user presses shift-arrow.
-                    toggleSelection(startPosition);
-                    setSelectionRangeBegin(startPosition);
-                }
-                mRanger.snapSelection(targetPosition);
-                notifySelectionChanged();
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns the adapter position that the key combo is targeted at.
-     */
-    private int findTargetPosition(View view, int keyCode) {
-        int position = RecyclerView.NO_POSITION;
-        if (keyCode == KeyEvent.KEYCODE_MOVE_HOME) {
-            position = 0;
-        } else if (keyCode == KeyEvent.KEYCODE_MOVE_END) {
-            position = mAdapter.getItemCount() - 1;
-        } else {
-            // Find a navigation target based on the arrow key that the user pressed.  Ignore
-            // navigation targets that aren't items in the recycler view.
-            int searchDir = -1;
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_DPAD_UP:
-                    searchDir = View.FOCUS_UP;
-                    break;
-                case KeyEvent.KEYCODE_DPAD_DOWN:
-                    searchDir = View.FOCUS_DOWN;
-                    break;
-                case KeyEvent.KEYCODE_DPAD_LEFT:
-                    searchDir = View.FOCUS_LEFT;
-                    break;
-                case KeyEvent.KEYCODE_DPAD_RIGHT:
-                    searchDir = View.FOCUS_RIGHT;
-                    break;
-            }
-            if (searchDir != -1) {
-                View targetView = view.focusSearch(searchDir);
-                // TargetView can be null, for example, if the user pressed <down> at the bottom of
-                // the list.
-                if (targetView != null) {
-                    position = mEnvironment.getAdapterPositionForChildView(targetView);
-                }
-            }
-        }
-        return position;
-    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
index 71708c1..0bb682e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
@@ -44,13 +44,13 @@
 
 import com.android.documentsui.BaseActivity;
 import com.android.documentsui.DocumentsApplication;
-import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.R;
 import com.android.documentsui.Snackbars;
+import com.android.documentsui.model.DocumentInfo;
 /**
  * Dialog to rename file or directory.
  */
-class RenameDocumentFragment extends DialogFragment {
+public class RenameDocumentFragment extends DialogFragment {
     private static final String TAG_RENAME_DOCUMENT = "rename_document";
     private DocumentInfo mDocument;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 12c0b8f..3f14a55 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -176,6 +176,7 @@
         } else if (isExternalStorage()) {
             derivedIcon = R.drawable.ic_root_smartphone;
             derivedType = TYPE_LOCAL;
+            // TODO: Apply SD card icon to SD devices.
         } else if (isDownloads()) {
             derivedIcon = R.drawable.ic_root_download;
             derivedType = TYPE_DOWNLOADS;
@@ -244,6 +245,10 @@
                 || derivedType == TYPE_RECENTS || derivedType == TYPE_DOWNLOADS;
     }
 
+    public boolean hasSettings() {
+        return (flags & Root.FLAG_HAS_SETTINGS) != 0;
+    }
+
     public Drawable loadIcon(Context context) {
         if (derivedIcon != 0) {
             return context.getDrawable(derivedIcon);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
index 7c08ba7..dad8697 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
@@ -186,7 +186,7 @@
 
     @Override
     Notification getWarningNotification() {
-        final Intent navigateIntent = buildNavigateIntent();
+        final Intent navigateIntent = buildNavigateIntent(INTENT_TAG_WARNING);
         navigateIntent.putExtra(EXTRA_DIALOG_TYPE, DIALOG_TYPE_CONVERTED);
         navigateIntent.putExtra(EXTRA_OPERATION, operationType);
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
index f2c8763..77517ca 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
@@ -35,6 +35,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.net.Uri;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.provider.DocumentsContract;
@@ -60,6 +61,12 @@
  */
 abstract public class Job implements Runnable {
     private static final String TAG = "Job";
+
+    static final String INTENT_TAG_WARNING = "warning";
+    static final String INTENT_TAG_FAILURE = "failure";
+    static final String INTENT_TAG_PROGRESS = "progress";
+    static final String INTENT_TAG_CANCEL = "cancel";
+
     final Context service;
     final Context appContext;
     final Listener listener;
@@ -130,6 +137,10 @@
 
     abstract Notification getWarningNotification();
 
+    Uri getDataUriForIntent(String tag) {
+        return Uri.parse(String.format("data,%s-%s", tag, id));
+    }
+
     ContentProviderClient getClient(DocumentInfo doc) throws RemoteException {
         ContentProviderClient client = mClients.get(doc.authority);
         if (client == null) {
@@ -193,10 +204,9 @@
     }
 
     Notification getFailureNotification(@PluralsRes int titleId, @DrawableRes int icon) {
-        final Intent navigateIntent = buildNavigateIntent();
+        final Intent navigateIntent = buildNavigateIntent(INTENT_TAG_FAILURE);
         navigateIntent.putExtra(EXTRA_DIALOG_TYPE, OperationDialogFragment.DIALOG_TYPE_FAILURE);
         navigateIntent.putExtra(EXTRA_OPERATION, operationType);
-
         navigateIntent.putParcelableArrayListExtra(EXTRA_SRC_LIST, failedFiles);
 
         final Notification.Builder errorBuilder = new Notification.Builder(service)
@@ -219,7 +229,8 @@
         Notification.Builder progressBuilder = new Notification.Builder(service)
                 .setContentTitle(title)
                 .setContentIntent(
-                        PendingIntent.getActivity(appContext, 0, buildNavigateIntent(), 0))
+                        PendingIntent.getActivity(appContext, 0,
+                                buildNavigateIntent(INTENT_TAG_PROGRESS), 0))
                 .setCategory(Notification.CATEGORY_PROGRESS)
                 .setSmallIcon(icon)
                 .setOngoing(true);
@@ -241,15 +252,18 @@
     /**
      * Creates an intent for navigating back to the destination directory.
      */
-    Intent buildNavigateIntent() {
+    Intent buildNavigateIntent(String tag) {
         Intent intent = new Intent(service, FilesActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.setAction(DocumentsContract.ACTION_BROWSE);
+        intent.setData(getDataUriForIntent(tag));
         intent.putExtra(Shared.EXTRA_STACK, (Parcelable) stack);
         return intent;
     }
 
     Intent createCancelIntent() {
         final Intent cancelIntent = new Intent(service, FileOperationService.class);
+        cancelIntent.setData(getDataUriForIntent(INTENT_TAG_CANCEL));
         cancelIntent.putExtra(EXTRA_CANCEL, true);
         cancelIntent.putExtra(EXTRA_JOB_ID, id);
         return cancelIntent;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
index 467d97e..5df4dca 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
@@ -105,6 +105,19 @@
         return createDocument(root.documentId, mimeType, name);
     }
 
+    public Uri createDocumentWithFlags(String documentId, String mimeType, String name, int flags)
+            throws RemoteException {
+        Bundle in = new Bundle();
+        in.putInt(StubProvider.EXTRA_FLAGS, flags);
+        in.putString(StubProvider.EXTRA_PARENT_ID, documentId);
+        in.putString(Document.COLUMN_MIME_TYPE, mimeType);
+        in.putString(Document.COLUMN_DISPLAY_NAME, name);
+
+        Bundle out = mClient.call("createDocumentWithFlags", null, in);
+        Uri uri = out.getParcelable(DocumentsContract.EXTRA_URI);
+        return uri;
+    }
+
     public Uri createFolder(Uri parentUri, String name) {
         return createDocument(parentUri, Document.MIME_TYPE_DIR, name);
     }
@@ -286,4 +299,5 @@
 
         return DocumentsContract.buildDocumentUri(mAuthority, documentId);
     }
+
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
index 737a8b6..243c357 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
@@ -30,7 +30,7 @@
 import android.support.test.uiautomator.Configurator;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.Until;
-import android.test.InstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 import android.view.MotionEvent;
@@ -38,7 +38,7 @@
 import com.android.documentsui.model.RootInfo;
 
 @LargeTest
-public class DownloadsActivityUiTest extends InstrumentationTestCase {
+public class DownloadsActivityUiTest extends ActivityInstrumentationTestCase2<DownloadsActivity> {
 
     private static final int TIMEOUT = 5000;
     private static final String TAG = "DownloadsActivityUiTest";
@@ -53,6 +53,10 @@
     private ContentProviderClient mClient;
     private RootInfo mRoot;
 
+    public DownloadsActivityUiTest() {
+        super(DownloadsActivity.class);
+    }
+
     public void setUp() throws Exception {
         // Initialize UiDevice instance.
         Instrumentation instrumentation = getInstrumentation();
@@ -79,24 +83,25 @@
         intent.setDataAndType(mRoot.getUri(), DocumentsContract.Root.MIME_TYPE_ITEM);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        mContext.startActivity(intent);
+        setActivityIntent(intent);
+        getActivity();  // Start the activity.
 
         // Wait for the app to appear.
         mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), TIMEOUT);
         mDevice.waitForIdle();
 
-        mBot = new UiBot(mDevice, TIMEOUT);
+        mBot = new UiBot(mDevice, mContext, TIMEOUT);
 
         resetStorage();  // Just in case a test failed and tearDown didn't happen.
     }
 
     @Override
     protected void tearDown() throws Exception {
-        // Need to kill off the task we started.
-        super.tearDown();
         Log.d(TAG, "Resetting storage from setUp");
         resetStorage();
         mClient.release();
+
+        super.tearDown();
     }
 
     private void resetStorage() throws RemoteException {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index f0dbfe9..868dbbb 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -30,7 +30,7 @@
 import android.support.test.uiautomator.Configurator;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.Until;
-import android.test.InstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 import android.view.MotionEvent;
@@ -38,7 +38,7 @@
 import com.android.documentsui.model.RootInfo;
 
 @LargeTest
-public class FilesActivityUiTest extends InstrumentationTestCase {
+public class FilesActivityUiTest extends ActivityInstrumentationTestCase2<FilesActivity> {
 
     private static final int TIMEOUT = 5000;
     private static final String TAG = "FilesActivityUiTest";
@@ -54,6 +54,10 @@
     private RootInfo mRoot_0;
     private RootInfo mRoot_1;
 
+    public FilesActivityUiTest() {
+        super(FilesActivity.class);
+    }
+
     public void setUp() throws Exception {
         // Initialize UiDevice instance.
         Instrumentation instrumentation = getInstrumentation();
@@ -71,28 +75,31 @@
         mResolver = mContext.getContentResolver();
 
         mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
+        assertNotNull("Failed to acquire ContentProviderClient.", mClient);
         mDocsHelper = new DocumentsProviderHelper(DEFAULT_AUTHORITY, mClient);
 
         // Launch app.
         Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(TARGET_PKG);
         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        mContext.startActivity(intent);
+        setActivityIntent(intent);
+        getActivity();  // Start the activity.
 
         // Wait for the app to appear.
         mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), TIMEOUT);
         mDevice.waitForIdle();
 
-        mBot = new UiBot(mDevice, TIMEOUT);
+        mBot = new UiBot(mDevice, mContext, TIMEOUT);
 
         resetStorage();  // Just incase a test failed and tearDown didn't happen.
     }
 
     @Override
     protected void tearDown() throws Exception {
-        super.tearDown();
         Log.d(TAG, "Resetting storage from setUp");
         resetStorage();
         mClient.release();
+
+        super.tearDown();
     }
 
     private void resetStorage() throws RemoteException {
@@ -156,6 +163,8 @@
 
         mBot.openRoot(ROOT_0_ID);
         mDocsHelper.createDocument(mRoot_0, "yummers/sandwich", "Ham & Cheese.sandwich");
+
+        mDevice.waitForIdle();
         mBot.assertHasDocuments("file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
     }
 
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
new file mode 100644
index 0000000..5c6254f
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static com.android.documentsui.StubProvider.ROOT_0_ID;
+import static com.android.documentsui.UiTestEnvironment.TIMEOUT;
+
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+@LargeTest
+public class RenameDocumentUiTest extends InstrumentationTestCase {
+
+    private static final String TAG = "RenamDocumentUiTest";
+
+    private final String newName = "kitties.log";
+
+    private UiTestEnvironment mHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mHelper = new UiTestEnvironment(getInstrumentation());
+        mHelper.launch();
+        mHelper.initTestFiles();
+        mHelper.bot().openRoot(ROOT_0_ID);
+    }
+
+    public void testRenameEnabled_SingleSelection() throws Exception {
+        mHelper.bot().selectDocument(UiTestEnvironment.fileName1);
+        mHelper.bot().openOverflowMenu();
+        mHelper.bot().assertMenuEnabled(R.string.menu_rename, true);
+
+        // Dismiss more options window
+        mHelper.device().pressBack();
+    }
+
+    public void testNoRenameSupport_SingleSelection() throws Exception {
+        mHelper.bot().selectDocument(UiTestEnvironment.fileNameNoRename);
+        mHelper.bot().openOverflowMenu();
+        mHelper.bot().assertMenuEnabled(R.string.menu_rename, false);
+
+        // Dismiss more options window
+        mHelper.device().pressBack();
+    }
+
+    public void testOneHasRenameSupport_MultipleSelection() throws Exception {
+        mHelper.bot().selectDocument(UiTestEnvironment.fileName1);
+        mHelper.bot().selectDocument(UiTestEnvironment.fileNameNoRename);
+        mHelper.bot().openOverflowMenu();
+        mHelper.bot().assertMenuEnabled(R.string.menu_rename, false);
+
+        // Dismiss more options window
+        mHelper.device().pressBack();
+    }
+
+    public void testRenameDisabled_MultipleSelection() throws Exception {
+        mHelper.bot().selectDocument(UiTestEnvironment.fileName1);
+        mHelper.bot().selectDocument(UiTestEnvironment.fileName2);
+        mHelper.bot().openOverflowMenu();
+        mHelper.bot().assertMenuEnabled(R.string.menu_rename, false);
+
+        // Dismiss more options window
+        mHelper.device().pressBack();
+    }
+
+    public void testRenameFile_OkButton() throws Exception {
+        mHelper.bot().selectDocument(UiTestEnvironment.fileName1);
+        mHelper.bot().openOverflowMenu();
+        mHelper.bot().openDialog(R.string.menu_rename);
+        mHelper.bot().setDialogText(newName);
+        mHelper.bot().dismissKeyboardIfPresent();
+
+        mHelper.device().waitForIdle(TIMEOUT);
+        mHelper.bot().findRenameDialogOkButton().click();
+        mHelper.device().waitForIdle(TIMEOUT);
+
+        mHelper.bot().assertDocument(UiTestEnvironment.fileName1, false);
+        mHelper.bot().assertDocument(newName, true);
+        mHelper.bot().assertDocumentsCount(mHelper.getDocumentsCountDir0());
+    }
+
+    public void testRenameFile_Enter() throws Exception {
+        mHelper.bot().selectDocument(UiTestEnvironment.fileName1);
+        mHelper.bot().openOverflowMenu();
+        mHelper.bot().openDialog(R.string.menu_rename);
+        mHelper.bot().setDialogText(newName);
+
+        pressEnter();
+
+        mHelper.bot().assertDocument(UiTestEnvironment.fileName1, false);
+        mHelper.bot().assertDocument(newName, true);
+        mHelper.bot().assertDocumentsCount(mHelper.getDocumentsCountDir0());
+    }
+
+    public void testRenameFile_Cancel() throws Exception {
+        mHelper.bot().selectDocument(UiTestEnvironment.fileName1);
+        mHelper.bot().openOverflowMenu();
+        mHelper.bot().openDialog(R.string.menu_rename);
+        mHelper.bot().setDialogText(newName);
+        mHelper.bot().dismissKeyboardIfPresent();
+
+        mHelper.device().waitForIdle(TIMEOUT);
+        mHelper.bot().findRenameDialogCancelButton().click();
+        mHelper.device().waitForIdle(TIMEOUT);
+
+        mHelper.bot().assertDocument(UiTestEnvironment.fileName1, true);
+        mHelper.bot().assertDocument(newName, false);
+        mHelper.bot().assertDocumentsCount(mHelper.getDocumentsCountDir0());
+    }
+
+    public void testRenameDir() throws Exception {
+        String oldName = "Dir1";
+        String newName = "Dir123";
+
+        mHelper.bot().selectDocument(oldName);
+        mHelper.bot().openOverflowMenu();
+        mHelper.bot().openDialog(R.string.menu_rename);
+        mHelper.bot().setDialogText(newName);
+
+        pressEnter();
+
+        mHelper.bot().assertDocument(oldName, false);
+        mHelper.bot().assertDocument(newName, true);
+        mHelper.bot().assertDocumentsCount(mHelper.getDocumentsCountDir0());
+    }
+
+    public void testRename_NameExists() throws Exception {
+        // Check that document with the new name exists
+        mHelper.bot().assertDocument(UiTestEnvironment.fileName2, true);
+        mHelper.bot().selectDocument(UiTestEnvironment.fileName1);
+        mHelper.bot().openOverflowMenu();
+        mHelper.bot().openDialog(R.string.menu_rename);
+        mHelper.bot().setDialogText(UiTestEnvironment.fileName2);
+
+        pressEnter();
+
+        mHelper.bot().assertSnackbar(R.string.rename_error);
+        mHelper.bot().assertDocument(UiTestEnvironment.fileName1, true);
+        mHelper.bot().assertDocument(UiTestEnvironment.fileName2, true);
+        mHelper.bot().assertDocumentsCount(mHelper.getDocumentsCountDir0());
+    }
+
+    private void pressEnter() {
+        mHelper.device().waitForIdle(TIMEOUT);
+        mHelper.device().pressEnter();
+        mHelper.device().waitForIdle(TIMEOUT);
+    }
+
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
index 6c9c5d9..042ec85 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
@@ -16,278 +16,146 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.StubProvider.DEFAULT_AUTHORITY;
 import static com.android.documentsui.StubProvider.ROOT_0_ID;
 import static com.android.documentsui.StubProvider.ROOT_1_ID;
 
-import android.app.Instrumentation;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.RemoteException;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.Configurator;
-import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.Until;
 import android.test.InstrumentationTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.view.MotionEvent;
-
-import com.android.documentsui.model.RootInfo;
 
 @LargeTest
 public class SearchViewUiTest extends InstrumentationTestCase {
 
-    private static final int TIMEOUT = 5000;
     private static final String TAG = "SearchViewUiTest";
-    private static final String TARGET_PKG = "com.android.documentsui";
-    private static final String LAUNCHER_PKG = "com.android.launcher";
 
-    private UiBot mBot;
-    private UiDevice mDevice;
-    private Context mContext;
-    private ContentResolver mResolver;
-    private DocumentsProviderHelper mDocsHelper;
-    private ContentProviderClient mClient;
-    private RootInfo mRoot_0;
-    private RootInfo mRoot_1;
+    private UiTestEnvironment mEnv;
 
-    private UiObject mSearchView;
-    private UiObject mSearchTextField;
-    private UiObject mDocsList;
-    private UiObject mMessageTextView;
-    private UiObject mSearchIcon;
-
+    @Override
     public void setUp() throws Exception {
-        // Initialize UiDevice instance.
-        Instrumentation instrumentation = getInstrumentation();
+        super.setUp();
+        mEnv = new UiTestEnvironment(getInstrumentation());
+        mEnv.launch();
 
-        mDevice = UiDevice.getInstance(instrumentation);
-
-        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
-
-        // Start from the home screen.
-        mDevice.pressHome();
-        mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), TIMEOUT);
-
-        // NOTE: Must be the "target" context, else security checks in content provider will fail.
-        mContext = instrumentation.getTargetContext();
-        mResolver = mContext.getContentResolver();
-
-        mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
-        mDocsHelper = new DocumentsProviderHelper(DEFAULT_AUTHORITY, mClient);
-
-        // Launch app.
-        Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(TARGET_PKG);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        mContext.startActivity(intent);
-        // Wait for the app to appear.
-        mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), TIMEOUT);
-        mDevice.waitForIdle();
-
-        mBot = new UiBot(mDevice, TIMEOUT);
-
-        resetStorage(); // Just incase a test failed and tearDown didn't happen.
-
-        initUiObjects();
     }
 
     @Override
     protected void tearDown() throws Exception {
+        mEnv.device().pressBack();
         super.tearDown();
-        mDevice.pressBack();
-        resetStorage();
-        mClient.release();
     }
 
-    private void resetStorage() throws RemoteException {
-        mClient.call("clear", null, null);
-        // TODO: Would be nice to have an event to wait on here.
-        mDevice.waitForIdle();
+    public void testSearchView_ExpandsOnClick() throws Exception {
+        mEnv.bot().openSearchView();
+        mEnv.bot().assertSearchTextFiledAndIcon(true, false);
     }
 
-    private void initTestFiles() throws RemoteException {
-        mRoot_0 = mDocsHelper.getRoot(ROOT_0_ID);
-        mRoot_1 = mDocsHelper.getRoot(ROOT_1_ID);
+    public void testSearchView_CollapsesOnBack() throws Exception {
+        mEnv.bot().openSearchView();
 
-        mDocsHelper.createDocument(mRoot_0, "text/plain", "file10.log");
-        mDocsHelper.createDocument(mRoot_0, "image/png", "file1.png");
-        mDocsHelper.createDocument(mRoot_0, "text/csv", "file2.csv");
+        mEnv.device().pressBack();
 
-        mDocsHelper.createDocument(mRoot_1, "text/plain", "anotherFile0.log");
-        mDocsHelper.createDocument(mRoot_1, "text/plain", "poodles.text");
+        mEnv.bot().assertSearchTextFiledAndIcon(false, true);
     }
 
-    private void initUiObjects() {
-        mSearchView = mBot.findSearchView();
-        mSearchTextField = mBot.findSearchViewTextField();
-        mDocsList = mBot.findDocumentsList();
-        mMessageTextView = mBot.findMessageTextView();
-        mSearchIcon = mBot.findSearchViewIcon();
-    }
-
-    public void testSearchViewExpandsOnClick() throws Exception {
-        assertTrue(mSearchIcon.exists());
-        assertFalse(mSearchTextField.exists());
-
-        mSearchView.click();
-
-        assertTrue(mSearchTextField.exists());
-        assertTrue(mSearchTextField.isFocused());
-        assertFalse(mSearchIcon.exists());
-    }
-
-    public void testSearchViewCollapsesOnBack() throws Exception {
-        assertTrue(mSearchIcon.exists());
-        assertFalse(mSearchTextField.exists());
-
-        mSearchView.click();
-
-        mDevice.pressBack();
-
-        assertTrue(mSearchIcon.exists());
-        assertFalse(mSearchTextField.exists());
-    }
-
-    public void testSearchViewClearsTextOnBack() throws Exception {
-        assertTrue(mSearchIcon.exists());
-        assertFalse(mSearchTextField.exists());
-
+    public void testSearchView_ClearsTextOnBack() throws Exception {
         String query = "file2";
-        mSearchView.click();
-        mSearchTextField.setText(query);
+        mEnv.bot().openSearchView();
+        mEnv.bot().setSearchQuery(query);
 
-        assertSearchTextField(true, query);
+        mEnv.device().pressBack();
 
-        mDevice.pressBack();
-
-        assertTrue(mSearchIcon.exists());
-        assertFalse(mSearchTextField.exists());
+        mEnv.bot().assertSearchTextFiledAndIcon(false, true);
     }
 
-    public void testSearchFound() throws Exception {
-        initTestFiles();
-
-        mBot.openRoot(ROOT_0_ID);
-
-        assertDefaultTestDir0();
+    public void testSearch_ResultsFound() throws Exception {
+        mEnv.initTestFiles();
+        mEnv.bot().openRoot(ROOT_0_ID);
+        mEnv.assertDefaultContentOfTestDir0();
 
         String query = "file1";
-        mSearchView.click();
-        mSearchTextField.setText(query);
+        mEnv.bot().openSearchView();
+        mEnv.bot().setSearchQuery(query);
+        mEnv.bot().assertSearchTextField(true, query);
 
-        assertTrue(mDocsList.exists());
-        assertSearchTextField(true, query);
+        mEnv.device().pressEnter();
 
-        mDevice.pressEnter();
-
-        assertTrue(mDocsList.exists());
-        assertEquals(2, mDocsList.getChildCount());
-        mBot.assertHasDocuments("file1.png", "file10.log");
-        assertSearchTextField(false, query);
+        mEnv.bot().assertDocumentsCountOnList(true, 2);
+        mEnv.bot().assertHasDocuments(UiTestEnvironment.fileName1, UiTestEnvironment.fileName2);
+        mEnv.bot().assertSearchTextField(false, query);
     }
 
-    public void testSearchFoundClearsOnBack() throws Exception {
-        initTestFiles();
+    public void testSearchResultsFound_ClearsOnBack() throws Exception {
+        mEnv.initTestFiles();
+        mEnv.bot().openRoot(ROOT_0_ID);
+        mEnv.assertDefaultContentOfTestDir0();
 
-        mBot.openRoot(ROOT_0_ID);
+        String query = UiTestEnvironment.fileName1;
+        mEnv.bot().openSearchView();
+        mEnv.bot().setSearchQuery(query);
 
-        assertDefaultTestDir0();
-
-        String query = "file1";
-        mSearchView.click();
-        mSearchTextField.setText(query);
-
-        mDevice.pressEnter();
-        mDevice.pressBack();
-
-        assertDefaultTestDir0();
+        mEnv.device().pressEnter();
+        mEnv.device().pressBack();
+        mEnv.assertDefaultContentOfTestDir0();
     }
 
-    public void testSearchNoResults() throws Exception {
-        initTestFiles();
-
-        mBot.openRoot(ROOT_0_ID);
-
-        assertDefaultTestDir0();
+    public void testSearch_NoResults() throws Exception {
+        mEnv.initTestFiles();
+        mEnv.bot().openRoot(ROOT_0_ID);
+        mEnv.assertDefaultContentOfTestDir0();
 
         String query = "chocolate";
-        mSearchView.click();
-        mSearchTextField.setText(query);
+        mEnv.bot().openSearchView();
+        mEnv.bot().setSearchQuery(query);
 
-        mDevice.pressEnter();
+        mEnv.device().pressEnter();
 
-        assertFalse(mDocsList.exists());
-        assertTrue(mMessageTextView.exists());
-        String msg = String.valueOf(mContext.getString(R.string.no_results));
-        assertEquals(String.format(msg, "TEST_ROOT_0"), mMessageTextView.getText());
-        assertSearchTextField(false, query);
+        mEnv.bot().assertDocumentsCountOnList(false, 0);
+
+        String msg = String.valueOf(mEnv.context().getString(R.string.no_results));
+        mEnv.bot().assertMessageTextView(String.format(msg, "TEST_ROOT_0"));
+        mEnv.bot().assertSearchTextField(false, query);
     }
 
-    public void testSearchNoResultsClearsOnBack() throws Exception {
-        initTestFiles();
-
-        mBot.openRoot(ROOT_0_ID);
-
-        assertDefaultTestDir0();
+    public void testSearchNoResults_ClearsOnBack() throws Exception {
+        mEnv.initTestFiles();
+        mEnv.bot().openRoot(ROOT_0_ID);
+        mEnv.assertDefaultContentOfTestDir0();
 
         String query = "chocolate";
-        mSearchView.click();
-        mSearchTextField.setText(query);
+        mEnv.bot().openSearchView();
+        mEnv.bot().setSearchQuery(query);
 
-        mDevice.pressEnter();
-        mDevice.pressBack();
-
-        assertDefaultTestDir0();
+        mEnv.device().pressEnter();
+        mEnv.device().pressBack();
+        mEnv.assertDefaultContentOfTestDir0();
     }
 
-    public void testSearchFoundClearsDirectoryChange() throws Exception {
-        initTestFiles();
+    public void testSearchResultsFound_ClearsOnDirectoryChange() throws Exception {
+        mEnv.initTestFiles();
+        mEnv.bot().openRoot(ROOT_0_ID);
+        mEnv.assertDefaultContentOfTestDir0();
 
-        mBot.openRoot(ROOT_0_ID);
+        String query = UiTestEnvironment.fileName1;
+        mEnv.bot().openSearchView();
+        mEnv.bot().setSearchQuery(query);
 
-        assertDefaultTestDir0();
+        mEnv.device().pressEnter();
 
-        String query = "file1";
-        mSearchView.click();
-        mSearchTextField.setText(query);
+        mEnv.bot().openRoot(ROOT_1_ID);
+        mEnv.assertDefaultContentOfTestDir1();
 
-        mDevice.pressEnter();
-
-        mBot.openRoot(ROOT_1_ID);
-
-         assertDefaultTestDir1();
-
-         mBot.openRoot(ROOT_0_ID);
-
-         assertDefaultTestDir0();
+        mEnv.bot().openRoot(ROOT_0_ID);
+        mEnv.assertDefaultContentOfTestDir0();
     }
 
-    private void assertDefaultTestDir0() throws UiObjectNotFoundException {
-        assertTrue(mSearchIcon.exists());
-        assertTrue(mDocsList.exists());
-        assertFalse(mSearchTextField.exists());
-        assertEquals(3, mDocsList.getChildCount());
-        mBot.assertHasDocuments("file2.csv", "file1.png", "file10.log");
+    public void testSearchIconVisible_RootWithSearchSupport() throws Exception {
+        mEnv.bot().openRoot(ROOT_0_ID);
+        mEnv.bot().assertSearchTextFiledAndIcon(false, true);
     }
 
-    private void assertDefaultTestDir1() throws UiObjectNotFoundException {
-        assertTrue(mSearchIcon.exists());
-        assertFalse(mSearchTextField.exists());
-        assertTrue(mDocsList.exists());
-        assertEquals(2, mDocsList.getChildCount());
-        mBot.assertHasDocuments("anotherFile0.log", "poodles.text");
+    public void testSearchIconHidden_RootNoSearchSupport() throws Exception {
+        mEnv.bot().openRoot(ROOT_1_ID);
+        mEnv.bot().assertSearchTextFiledAndIcon(false, false);
     }
 
-    private void assertSearchTextField(boolean isFocused, String query)
-            throws UiObjectNotFoundException {
-        assertFalse(mSearchIcon.exists());
-        assertTrue(mSearchTextField.exists());
-        assertEquals(isFocused, mSearchTextField.isFocused());
-        assertEquals(query, mSearchTextField.getText());
-    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index cc48786..2527650 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -34,6 +34,7 @@
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsProvider;
 import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
 import android.util.Log;
 
 import libcore.io.IoUtils;
@@ -66,10 +67,13 @@
             = "com.android.documentsui.stubprovider.STREAM_TYPES";
     public static final String EXTRA_CONTENT = "com.android.documentsui.stubprovider.CONTENT";
 
+    public static final String EXTRA_FLAGS = "com.android.documentsui.stubprovider.FLAGS";
+    public static final String EXTRA_PARENT_ID = "com.android.documentsui.stubprovider.PARENT";
+
     private static final String TAG = "StubProvider";
 
     private static final String STORAGE_SIZE_KEY = "documentsui.stubprovider.size";
-    private static int DEFAULT_ROOT_SIZE = 1024 * 1024 * 100;  // 100 MB.
+    private static int DEFAULT_ROOT_SIZE = 1024 * 1024 * 100; // 100 MB.
 
     private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
             Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID,
@@ -122,6 +126,11 @@
                 Log.i(TAG, "Created new root directory @ " + file.getPath());
             }
             final RootInfo rootInfo = new RootInfo(file, getSize(rootId));
+
+            if(rootId.equals(ROOT_1_ID)) {
+                rootInfo.setSearchEnabled(false);
+            }
+
             mStorage.put(rootInfo.document.documentId, rootInfo.document);
             mRoots.put(rootId, rootInfo);
         }
@@ -144,8 +153,7 @@
             final RootInfo info = entry.getValue();
             final RowBuilder row = result.newRow();
             row.add(Root.COLUMN_ROOT_ID, id);
-            row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD
-                    | Root.FLAG_SUPPORTS_SEARCH);
+            row.add(Root.COLUMN_FLAGS, info.flags);
             row.add(Root.COLUMN_TITLE, id);
             row.add(Root.COLUMN_DOCUMENT_ID, info.document.documentId);
             row.add(Root.COLUMN_AVAILABLE_BYTES, info.getRemainingCapacity());
@@ -176,44 +184,8 @@
     @Override
     public String createDocument(String parentId, String mimeType, String displayName)
             throws FileNotFoundException {
-
-        final StubDocument parent = mStorage.get(parentId);
-        if (parent == null) {
-            throw new IllegalArgumentException(
-                    "Can't create file " + displayName + " in null parent.");
-        }
-        if (!parent.file.isDirectory()) {
-            throw new IllegalArgumentException(
-                    "Can't create file " + displayName + " inside non-directory parent "
-                    + parent.file.getName());
-        }
-
-        final File file = new File(parent.file, displayName);
-        if (file.exists()) {
-            throw new FileNotFoundException(
-                    "Duplicate file names not supported for " + file);
-        }
-
-        if (mimeType.equals(Document.MIME_TYPE_DIR)) {
-            if (!file.mkdirs()) {
-                throw new FileNotFoundException(
-                        "Failed to create directory(s): " + file);
-            }
-            Log.i(TAG, "Created new directory: " + file);
-        } else {
-            boolean created = false;
-            try {
-                created = file.createNewFile();
-            } catch (IOException e) {
-                // We'll throw an FNF exception later :)
-                Log.e(TAG, "createNewFile operation failed for file: " + file, e);
-            }
-            if (!created) {
-                throw new FileNotFoundException(
-                        "createNewFile operation failed for: " + file);
-            }
-            Log.i(TAG, "Created new file: " + file);
-        }
+        StubDocument parent = mStorage.get(parentId);
+        File file = createFile(parent, mimeType, displayName);
 
         final StubDocument document = StubDocument.createRegularDocument(file, mimeType, parent);
         mStorage.put(document.documentId, document);
@@ -303,6 +275,45 @@
     }
 
     @Override
+    public String renameDocument(String documentId, String displayName)
+            throws FileNotFoundException {
+
+        StubDocument oldDoc = mStorage.get(documentId);
+
+        File before = oldDoc.file;
+        File after = new File(before.getParentFile(), displayName);
+
+        if (after.exists()) {
+            throw new IllegalStateException("Already exists " + after);
+        }
+
+        boolean result = before.renameTo(after);
+
+        if (!result) {
+            throw new IllegalStateException("Failed to rename to " + after);
+        }
+
+        StubDocument newDoc = StubDocument.createRegularDocument(after, oldDoc.mimeType,
+                mStorage.get(oldDoc.parentId));
+
+        mStorage.remove(documentId);
+        notifyParentChanged(oldDoc.parentId);
+        getContext().getContentResolver().notifyChange(
+                DocumentsContract.buildDocumentUri(mAuthority, oldDoc.documentId), null, false);
+
+        mStorage.put(newDoc.documentId, newDoc);
+        notifyParentChanged(newDoc.parentId);
+        getContext().getContentResolver().notifyChange(
+                DocumentsContract.buildDocumentUri(mAuthority, newDoc.documentId), null, false);
+
+        if (!TextUtils.equals(documentId, newDoc.documentId)) {
+            return newDoc.documentId;
+        } else {
+            return null;
+        }
+    }
+
+    @Override
     public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
             throws FileNotFoundException {
 
@@ -456,6 +467,14 @@
 
     @Override
     public Bundle call(String method, String arg, Bundle extras) {
+        // We're not supposed to override any of the default DocumentsProvider
+        // methods that are supported by "call", so javadoc asks that we
+        // always call super.call first and return if response is not null.
+        Bundle result = super.call(method, arg, extras);
+        if (result != null) {
+            return result;
+        }
+
         switch (method) {
             case "clear":
                 clearCacheAndBuildRoots();
@@ -468,9 +487,11 @@
             case "simulateReadErrorsForFile":
                 simulateReadErrorsForFile(arg);
                 return null;
-            default:
-                return super.call(method, arg, extras);
+            case "createDocumentWithFlags":
+                return dispatchCreateDocumentWithFlags(extras);
         }
+
+        return null;
     }
 
     private Bundle createVirtualFileFromBundle(Bundle extras) {
@@ -493,6 +514,81 @@
         return null;
     }
 
+    private Bundle dispatchCreateDocumentWithFlags(Bundle extras) {
+        String rootId = extras.getString(EXTRA_PARENT_ID);
+        String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
+        String name = extras.getString(Document.COLUMN_DISPLAY_NAME);
+        int flags = extras.getInt(EXTRA_FLAGS);
+
+        Bundle out = new Bundle();
+        String documentId = null;
+        try {
+            documentId = createDocument(rootId, mimeType, name, flags);
+            Uri uri = DocumentsContract.buildDocumentUri(mAuthority, documentId);
+            out.putParcelable(DocumentsContract.EXTRA_URI, uri);
+        } catch (FileNotFoundException e) {
+            Log.d(TAG, "Cretaing document with flags failed" + name);
+        }
+        return out;
+    }
+
+    public String createDocument(String parentId, String mimeType, String displayName, int flags)
+            throws FileNotFoundException {
+
+        StubDocument parent = mStorage.get(parentId);
+        File file = createFile(parent, mimeType, displayName);
+
+        final StubDocument document = StubDocument.createDocumentWithFlags(file, mimeType, parent,
+                flags);
+        mStorage.put(document.documentId, document);
+        Log.d(TAG, "Created document " + document.documentId);
+        notifyParentChanged(document.parentId);
+        getContext().getContentResolver().notifyChange(
+                DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
+                null, false);
+
+        return document.documentId;
+    }
+
+    private File createFile(StubDocument parent, String mimeType, String displayName)
+            throws FileNotFoundException {
+        if (parent == null) {
+            throw new IllegalArgumentException(
+                    "Can't create file " + displayName + " in null parent.");
+        }
+        if (!parent.file.isDirectory()) {
+            throw new IllegalArgumentException(
+                    "Can't create file " + displayName + " inside non-directory parent "
+                            + parent.file.getName());
+        }
+
+        final File file = new File(parent.file, displayName);
+        if (file.exists()) {
+            throw new FileNotFoundException(
+                    "Duplicate file names not supported for " + file);
+        }
+
+        if (mimeType.equals(Document.MIME_TYPE_DIR)) {
+            if (!file.mkdirs()) {
+                throw new FileNotFoundException("Failed to create directory(s): " + file);
+            }
+            Log.i(TAG, "Created new directory: " + file);
+        } else {
+            boolean created = false;
+            try {
+                created = file.createNewFile();
+            } catch (IOException e) {
+                // We'll throw an FNF exception later :)
+                Log.e(TAG, "createNewFile operation failed for file: " + file, e);
+            }
+            if (!created) {
+                throw new FileNotFoundException("createNewFile operation failed for: " + file);
+            }
+            Log.i(TAG, "Created new file: " + file);
+        }
+        return file;
+    }
+
     private void configure(String arg, Bundle extras) {
         Log.d(TAG, "Configure " + arg);
         String rootName = extras.getString(EXTRA_ROOT, ROOT_0_ID);
@@ -557,7 +653,7 @@
         }
         final StubDocument document = StubDocument.createRegularDocument(file, mimeType, parent);
         mStorage.put(document.documentId, document);
-        return DocumentsContract.buildDocumentUri(mAuthority,  document.documentId);
+        return DocumentsContract.buildDocumentUri(mAuthority, document.documentId);
     }
 
     @VisibleForTesting
@@ -573,7 +669,7 @@
         final StubDocument document = StubDocument.createVirtualDocument(
                 file, mimeType, streamTypes, parent);
         mStorage.put(document.documentId, document);
-        return DocumentsContract.buildDocumentUri(mAuthority,  document.documentId);
+        return DocumentsContract.buildDocumentUri(mAuthority, document.documentId);
     }
 
     @VisibleForTesting
@@ -616,22 +712,33 @@
     }
 
     final static class RootInfo {
+        private static final int DEFAULT_ROOTS_FLAGS = Root.FLAG_SUPPORTS_SEARCH
+                | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD;
+
         public final String name;
         public final StubDocument document;
         public long capacity;
         public long size;
+        public int flags;
 
         RootInfo(File file, long capacity) {
             this.name = file.getName();
             this.capacity = 1024 * 1024;
-            this.document = StubDocument.createRootDocument(file, this);
+            this.flags = DEFAULT_ROOTS_FLAGS;
             this.capacity = capacity;
             this.size = 0;
+            this.document = StubDocument.createRootDocument(file, this);
         }
 
         public long getRemainingCapacity() {
             return capacity - size;
         }
+
+        public void setSearchEnabled(boolean enabled) {
+            flags = enabled ? (flags | Root.FLAG_SUPPORTS_SEARCH)
+                    : (flags & ~Root.FLAG_SUPPORTS_SEARCH);
+        }
+
     }
 
     final static class StubDocument {
@@ -643,9 +750,8 @@
         public final String parentId;
         public final RootInfo rootInfo;
 
-        private StubDocument(
-                 File file, String mimeType, List<String> streamTypes, int flags,
-                 StubDocument parent) {
+        private StubDocument(File file, String mimeType, List<String> streamTypes, int flags,
+                StubDocument parent) {
             this.file = file;
             this.documentId = getDocumentIdForFile(file);
             this.mimeType = mimeType;
@@ -671,7 +777,7 @@
 
         public static StubDocument createRegularDocument(
                 File file, String mimeType, StubDocument parent) {
-            int flags = Document.FLAG_SUPPORTS_DELETE;
+            int flags = Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_RENAME;
             if (file.isDirectory()) {
                 flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
             } else {
@@ -680,6 +786,11 @@
             return new StubDocument(file, mimeType, new ArrayList<String>(), flags, parent);
         }
 
+        public static StubDocument createDocumentWithFlags(
+                File file, String mimeType, StubDocument parent, int flags) {
+            return new StubDocument(file, mimeType, new ArrayList<String>(), flags, parent);
+        }
+
         public static StubDocument createVirtualDocument(
                 File file, String mimeType, List<String> streamTypes, StubDocument parent) {
             int flags = Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_WRITE
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
index c4def8f..d609fa84 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
@@ -17,7 +17,11 @@
 package com.android.documentsui;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.assertFalse;
 
+import android.content.Context;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
 import android.support.test.uiautomator.UiDevice;
@@ -28,11 +32,13 @@
 import android.support.test.uiautomator.UiSelector;
 import android.support.test.uiautomator.Until;
 import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
 
 import junit.framework.Assert;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
 import java.util.regex.Pattern;
 
@@ -48,10 +54,12 @@
             By.desc(Pattern.compile("^Deleting [0-9]+ file.+"));
 
     private UiDevice mDevice;
+    private Context mContext;
     private int mTimeout;
 
-    public UiBot(UiDevice device, int timeout) {
+    public UiBot(UiDevice device, Context context, int timeout) {
         mDevice = device;
+        mContext = context;
         mTimeout = timeout;
     }
 
@@ -109,25 +117,39 @@
         }
     }
 
-    UiObject findDocument(String label) throws UiObjectNotFoundException {
-        final UiSelector docList = new UiSelector().resourceId(
-                "com.android.documentsui:id/container_directory").childSelector(
-                        new UiSelector().resourceId("com.android.documentsui:id/list"));
-
-        // Wait for the first list item to appear
-        new UiObject(docList.childSelector(new UiSelector())).waitForExists(mTimeout);
-
-        // new UiScrollable(docList).scrollIntoView(new UiSelector().text(label));
-        return mDevice.findObject(docList.childSelector(new UiSelector().text(label)));
+    void assertMenuEnabled(int id, boolean enabled) {
+        UiObject2 menu= findMenuWithName(mContext.getString(id));
+        assertNotNull(menu);
+        assertEquals(enabled, menu.isEnabled());
     }
 
-    boolean hasDocuments(String... labels) throws UiObjectNotFoundException {
-        for (String label : labels) {
-            if (!findDocument(label).exists()) {
-                return false;
-            }
+    void assertDocumentsCount(int count) throws UiObjectNotFoundException {
+        UiObject docsList = findDocumentsList();
+        assertEquals(count, docsList.getChildCount());
+    }
+
+    void assertDocumentsCount(String dir, int count) throws UiObjectNotFoundException {
+        openRoot(dir);
+        UiObject docsList = findDocumentsList();
+        assertEquals(count, docsList.getChildCount());
+    }
+
+    void assertSearchTextField(boolean isFocused, String query)
+            throws UiObjectNotFoundException {
+        UiObject textField = findSearchViewTextField();
+        UiObject searchIcon = findSearchViewIcon();
+
+        assertFalse(searchIcon.exists());
+        assertTrue(textField.exists());
+        assertEquals(isFocused, textField.isFocused());
+        if(query != null) {
+            assertEquals(query, textField.getText());
         }
-        return true;
+    }
+
+    void assertSearchTextFiledAndIcon(boolean searchTextFieldExists, boolean searchIconExists) {
+        assertEquals(searchTextFieldExists, findSearchViewTextField().exists());
+        assertEquals(searchIconExists, findSearchViewIcon().exists());
     }
 
     void assertHasDocuments(String... labels) throws UiObjectNotFoundException {
@@ -143,10 +165,77 @@
         }
     }
 
+    void assertDocument(String name, boolean exists) throws UiObjectNotFoundException {
+        UiObject doc = findDocument(name);
+        assertEquals(exists, doc.exists());
+    }
+
+    void assertDocumentsCountOnList(boolean exists, int count) throws UiObjectNotFoundException {
+        UiObject docsList = findDocumentsList();
+        assertEquals(exists, docsList.exists());
+        if(docsList.exists()) {
+            assertEquals(count, docsList.getChildCount());
+        }
+    }
+
+    void assertMessageTextView(String message) throws UiObjectNotFoundException {
+        UiObject messageTextView = findMessageTextView();
+        assertTrue(messageTextView.exists());
+
+        String msg = String.valueOf(message);
+        assertEquals(String.format(msg, "TEST_ROOT_0"), messageTextView.getText());
+
+    }
+    void assertSnackbar(int id) {
+        assertNotNull(getSnackbar(mContext.getString(id)));
+    }
+
     void clickDocument(String label) throws UiObjectNotFoundException {
         findDocument(label).click();
     }
 
+    void openSearchView() throws UiObjectNotFoundException {
+        UiObject searchView = findSearchView();
+        searchView.click();
+        assertTrue(searchView.exists());
+    }
+
+    void setSearchQuery(String query) throws UiObjectNotFoundException {
+        UiObject searchView = findSearchView();
+        assertTrue(searchView.exists());
+        UiObject searchTextField = findSearchViewTextField();
+        searchTextField.setText(query);
+        assertSearchTextField(true, query);
+    }
+
+    UiObject openOverflowMenu() throws UiObjectNotFoundException {
+        UiObject obj = findMenuMoreOptions();
+        obj.click();
+        mDevice.waitForIdle(mTimeout);
+        return obj;
+    }
+
+    void openDialog(int id) {
+        UiObject2 menu= findMenuWithName(mContext.getString(id));
+        assertNotNull(menu);
+        assertEquals(true, menu.isEnabled());
+        menu.click();
+    }
+
+    void setDialogText(String text) throws UiObjectNotFoundException {
+        findDialogEditText().setText(text);
+    }
+
+    UiObject selectDocument(String label) throws UiObjectNotFoundException {
+        UiObject doc = findDocument(label);
+        doc.longClick();
+        return doc;
+    }
+
+    UiObject2 getSnackbar(String message) {
+        return mDevice.wait(Until.findObject(By.text(message)), mTimeout);
+    }
+
     void waitForDeleteSnackbar() {
         mDevice.wait(Until.findObject(SNACK_DELETE), mTimeout);
     }
@@ -200,6 +289,27 @@
         return mDevice.findObject(selector);
     }
 
+    UiObject findDocument(String label) throws UiObjectNotFoundException {
+        final UiSelector docList = new UiSelector().resourceId(
+                "com.android.documentsui:id/container_directory").childSelector(
+                        new UiSelector().resourceId("com.android.documentsui:id/list"));
+
+        // Wait for the first list item to appear
+        new UiObject(docList.childSelector(new UiSelector())).waitForExists(mTimeout);
+
+        // new UiScrollable(docList).scrollIntoView(new UiSelector().text(label));
+        return mDevice.findObject(docList.childSelector(new UiSelector().text(label)));
+    }
+
+    boolean hasDocuments(String... labels) throws UiObjectNotFoundException {
+        for (String label : labels) {
+            if (!findDocument(label).exists()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     UiObject findDocumentsList() {
         return findObject(
                 "com.android.documentsui:id/container_directory",
@@ -224,4 +334,60 @@
                 "com.android.documentsui:id/message");
     }
 
+    UiObject findActionModeBar() {
+        return findObject("android:id/action_mode_bar");
+    }
+
+    UiObject findDialogEditText() {
+        return findObject("android:id/content", "android:id/text1");
+    }
+
+    UiObject findRenameDialogOkButton() {
+        return findObject("android:id/content", "android:id/button1");
+    }
+
+    UiObject findRenameDialogCancelButton() {
+        return findObject("android:id/content", "android:id/button2");
+    }
+
+    UiObject findMenuLabelWithName(String label) {
+        UiSelector selector = new UiSelector().text(label);
+        return mDevice.findObject(selector);
+    }
+
+    UiObject2 findMenuWithName(String label) {
+        List<UiObject2> menuItems = mDevice.findObjects(By.clazz("android.widget.LinearLayout"));
+        Iterator<UiObject2> it = menuItems.iterator();
+
+        UiObject2 menuItem = null;
+        while(it.hasNext()) {
+            menuItem = it.next();
+            UiObject2 text = menuItem.findObject(By.text(label));
+            if(text != null) {
+                break;
+            }
+        }
+        return menuItem;
+    }
+
+    UiObject findMenuMoreOptions() {
+        UiSelector selector = new UiSelector().className("android.widget.ImageButton")
+                .descriptionContains("More options");
+        //TODO: use the system string ? android.R.string.action_menu_overflow_description
+        return mDevice.findObject(selector);
+    }
+
+    // Indirect way to detect the keyboard.
+    boolean isKeyboardPresent() {
+        InputMethodManager inputManager = (InputMethodManager) mContext
+                .getSystemService(Context.INPUT_METHOD_SERVICE);
+        return inputManager.isAcceptingText();
+    }
+
+    void dismissKeyboardIfPresent() {
+        if(isKeyboardPresent()) {
+            mDevice.pressBack();
+        }
+    }
+
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UiTestEnvironment.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UiTestEnvironment.java
new file mode 100644
index 0000000..9e30589
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/UiTestEnvironment.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static com.android.documentsui.StubProvider.DEFAULT_AUTHORITY;
+import static com.android.documentsui.StubProvider.ROOT_0_ID;
+import static com.android.documentsui.StubProvider.ROOT_1_ID;
+
+import android.app.Instrumentation;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.provider.DocumentsContract.Document;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Configurator;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.Until;
+import android.view.MotionEvent;
+
+import com.android.documentsui.model.RootInfo;
+
+/**
+ * Provides basic test environment for UI tests:
+ * - Launches activity
+ * - Creates and gives access to test root directories and test files
+ * - Cleans up the test environment
+ */
+class UiTestEnvironment {
+
+    public static final int TIMEOUT = 5000;
+    public static final String NO_RENAME = "NO_RENAME";
+
+    public static final String dirName1 = "Dir1";
+    public static final String fileName1 = "file1.log";
+    public static final String fileName2 = "file12.png";
+    public static final String fileName3 = "anotherFile0.log";
+    public static final String fileName4 = "poodles.text";
+    public static final String fileNameNoRename = NO_RENAME + "file.txt";
+
+    private static final String TARGET_PKG = "com.android.documentsui";
+    private static final String LAUNCHER_PKG = "com.android.launcher";
+
+    private final UiBot mBot;
+    private final UiDevice mDevice;
+    private final Context mContext;
+
+    private  RootInfo mRootDir0;
+    private  RootInfo mRootDir1;
+    private int mDocsCountDir0;
+    private int mDocsCountDir1;
+
+    private ContentResolver mResolver;
+    private DocumentsProviderHelper mDocsHelper;
+    private ContentProviderClient mClient;
+
+    private final Instrumentation mInstrumentation;
+
+    public UiTestEnvironment(Instrumentation instrumentation) {
+        mInstrumentation = instrumentation;
+        mDevice = UiDevice.getInstance(mInstrumentation);
+        // NOTE: Must be the "target" context, else security checks in content provider will fail.
+        mContext = mInstrumentation.getTargetContext();
+        mBot = new UiBot(mDevice, mContext, TIMEOUT);
+    }
+
+/**
+ * Launches default activity and waits for the application to appear.
+ * @throws Exception
+ */
+    public void launch() throws Exception {
+        Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(TARGET_PKG);
+        launch(intent);
+    }
+
+    /**
+     * Launches activity specified by intent and waits for the application to appear.
+     * @param intent Intent describing activity to launch.
+     * @throws Exception
+     */
+    public void launch(Intent intent) throws Exception {
+        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
+        // Start from the home screen.
+        mDevice.pressHome();
+        mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), TIMEOUT);
+
+        mResolver = mContext.getContentResolver();
+        mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
+        mDocsHelper = new DocumentsProviderHelper(DEFAULT_AUTHORITY, mClient);
+
+        // Launch app.
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+        // Wait for the app to appear.
+        mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), TIMEOUT);
+        mDevice.waitForIdle();
+
+        resetStorage(); // Just incase a test failed and tearDown didn't happen.
+    }
+
+    public void cleanUp() throws Exception {
+        resetStorage();
+        mClient.release();
+    }
+
+    public void resetStorage() throws RemoteException {
+        mClient.call("clear", null, null);
+        mDevice.waitForIdle();
+    }
+
+    public void initTestFiles() throws RemoteException {
+        mRootDir0 = mDocsHelper.getRoot(ROOT_0_ID);
+        mRootDir1 = mDocsHelper.getRoot(ROOT_1_ID);
+
+        mDocsHelper.createFolder(mRootDir0, dirName1);
+        mDocsHelper.createDocument(mRootDir0, "text/plain", fileName1);
+        mDocsHelper.createDocument(mRootDir0, "image/png", fileName2);
+        mDocsHelper.createDocumentWithFlags(mRootDir0.documentId, "text/plain", fileNameNoRename,
+                Document.FLAG_SUPPORTS_WRITE);
+        mDocsCountDir0 = 4;
+
+        mDocsHelper.createDocument(mRootDir1, "text/plain", fileName3);
+        mDocsHelper.createDocument(mRootDir1, "text/plain", fileName4);
+        mDocsCountDir1 = 2;
+    }
+
+    public void assertDefaultContentOfTestDir0() throws UiObjectNotFoundException {
+        bot().assertDocumentsCount(ROOT_0_ID, getDocumentsCountDir0());
+        bot().assertHasDocuments(UiTestEnvironment.fileName1, UiTestEnvironment.fileName2,
+                UiTestEnvironment.dirName1, UiTestEnvironment.fileNameNoRename);
+    }
+
+    public void assertDefaultContentOfTestDir1() throws UiObjectNotFoundException {
+        bot().assertDocumentsCount(ROOT_1_ID, getDocumentsCountDir1());
+        bot().assertHasDocuments(UiTestEnvironment.fileName3, UiTestEnvironment.fileName4);
+    }
+
+    public UiBot bot() {
+        return mBot;
+    }
+
+    public UiDevice device() {
+        return mDevice;
+    }
+
+    public Context context() {
+        return mContext;
+    }
+
+    public RootInfo getRootDir0() {
+        return mRootDir0;
+    }
+
+    public int getDocumentsCountDir0() {
+        return mDocsCountDir0;
+    }
+
+    public int getDocumentsCountDir1() {
+        return mDocsCountDir1;
+    }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/DocumentHolderTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/DocumentHolderTest.java
index 16efc6e..87cd42f 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/DocumentHolderTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/DocumentHolderTest.java
@@ -22,6 +22,7 @@
 import android.os.SystemClock;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.MotionEvent.PointerCoords;
@@ -130,5 +131,10 @@
             return true;
         }
 
+        @Override
+        public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event) {
+            return false;
+        }
+
     }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java
index d3ef9aa..b1cb29e 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java
@@ -173,12 +173,6 @@
         assertRangeSelection(0, 7);
     }
 
-    public void testKeyboardSelection() {
-        // This simulates shift-navigation.
-        keyToPosition(5, 10, true);
-        assertRangeSelection(5, 10);
-    }
-
     public void testSingleSelectMode() {
         mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_SINGLE);
         mManager.addCallback(mCallback);
@@ -195,14 +189,6 @@
         assertSelection(items.get(20));
     }
 
-    public void testSingleSelectMode_ShiftDoesNotExtendSelection() {
-        mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_SINGLE);
-        mManager.addCallback(mCallback);
-        longPress(20);
-        keyToPosition(20, 22, true);
-        assertSelection(items.get(22));
-    }
-
     public void testProvisionalSelection() {
         Selection s = mManager.getSelection();
         assertSelection();
@@ -263,10 +249,6 @@
         mManager.onSingleTapUp(TestInputEvent.shiftClick(position));
     }
 
-    private void keyToPosition(int startPos, int endPos, boolean shift) {
-        mManager.changeFocus(startPos, endPos, shift);
-    }
-
     private void assertSelected(String... expected) {
         for (int i = 0; i < expected.length; i++) {
             Selection selection = mManager.getSelection();
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
index 7920c50..353d4bd 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
@@ -23,7 +23,6 @@
 import android.support.v7.widget.RecyclerView.OnScrollListener;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.view.View;
 
 import com.android.documentsui.dirlist.MultiSelectManager.GridModel;
 
@@ -326,16 +325,6 @@
         }
 
         @Override
-        public int getAdapterPositionForChildView(View view) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void focusItem(int i) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
         public boolean isLayoutItem(int adapterPosition) {
             return false;
         }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
index 0e79561..8e624a0 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
@@ -19,7 +19,6 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.support.v7.widget.RecyclerView.OnScrollListener;
-import android.view.View;
 
 import com.android.documentsui.dirlist.MultiSelectManager.SelectionEnvironment;
 
@@ -83,11 +82,6 @@
     }
 
     @Override
-    public int getAdapterPositionForChildView(View view) {
-        return 0;
-    }
-
-    @Override
     public int getColumnCount() {
         return 0;
     }
@@ -108,10 +102,6 @@
     }
 
     @Override
-    public void focusItem(int position) {
-    }
-
-    @Override
     public boolean isLayoutItem(int adapterPosition) {
         return false;
     }
diff --git a/packages/ExtServices/Android.mk b/packages/ExtServices/Android.mk
new file mode 100644
index 0000000..e8a4007
--- /dev/null
+++ b/packages/ExtServices/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := ExtServices
+
+LOCAL_CERTIFICATE := platform
+
+LOCAL_AAPT_FLAGS := --shared-lib
+
+LOCAL_EXPORT_PACKAGE_RESOURCES := true
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.proguard
+
+LOCAL_PRIVILEGED_MODULE := true
+
+include $(BUILD_PACKAGE)
+
+
+
+
+
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
new file mode 100644
index 0000000..100b35c
--- /dev/null
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.ext.services"
+    android:versionCode="1"
+    android:versionName="1"
+    coreApp="true">
+
+    <application android:label="@string/app_name"
+        android:allowBackup="false"
+        android:forceDeviceEncrypted="true"
+        android:encryptionAware="true">
+
+        <library android:name="android.ext.services"/>
+
+    </application>
+
+</manifest>
diff --git a/packages/ExtServices/MODULE_LICENSE_APACHE2 b/packages/ExtServices/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/packages/ExtServices/MODULE_LICENSE_APACHE2
diff --git a/packages/ExtServices/NOTICE b/packages/ExtServices/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/packages/ExtServices/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/packages/ExtServices/proguard.proguard b/packages/ExtServices/proguard.proguard
new file mode 100644
index 0000000..e5dfbe1
--- /dev/null
+++ b/packages/ExtServices/proguard.proguard
@@ -0,0 +1,7 @@
+-keepparameternames
+-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
+                SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
+
+-keep public class * {
+    public protected *;
+}
diff --git a/packages/PrintSpooler/res/color/item_text_color.xml b/packages/ExtServices/res/values/strings.xml
similarity index 71%
copy from packages/PrintSpooler/res/color/item_text_color.xml
copy to packages/ExtServices/res/values/strings.xml
index f580fbd..531e517 100644
--- a/packages/PrintSpooler/res/color/item_text_color.xml
+++ b/packages/ExtServices/res/values/strings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-   <item android:state_enabled="true" android:color="#333333" />
-   <item android:color="#888888"/>
-</selector>
\ No newline at end of file
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">Android Services Library</string>
+</resources>
diff --git a/packages/ExtServices/src/android/ext/services/Version.java b/packages/ExtServices/src/android/ext/services/Version.java
new file mode 100644
index 0000000..026cccd
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/Version.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.ext.services;
+
+/**
+ * Class that provides the version of the library.
+ */
+public final class Version {
+
+    private Version() {
+        /* do nothing - hide constructor */
+    }
+
+    /**
+     * Gets the version of the library.
+     *
+     * @return The version.
+     */
+    public static int getVersionCode() {
+        return 1;
+    }
+}
\ No newline at end of file
diff --git a/packages/ExtShared/Android.mk b/packages/ExtShared/Android.mk
new file mode 100644
index 0000000..d8052df
--- /dev/null
+++ b/packages/ExtShared/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := ExtShared
+
+LOCAL_CERTIFICATE := platform
+
+LOCAL_AAPT_FLAGS := --shared-lib
+
+LOCAL_EXPORT_PACKAGE_RESOURCES := true
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.proguard
+
+include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/packages/ExtShared/AndroidManifest.xml b/packages/ExtShared/AndroidManifest.xml
new file mode 100644
index 0000000..e2e81d0
--- /dev/null
+++ b/packages/ExtShared/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.ext.shared"
+    android:versionCode="1"
+    android:versionName="1"
+    coreApp="true">
+
+    <application android:label="@string/app_name"
+        android:allowBackup="false"
+        android:forceDeviceEncrypted="true"
+        android:encryptionAware="true">
+
+        <library android:name="android.ext.shared"/>
+
+    </application>
+
+</manifest>
diff --git a/packages/ExtShared/MODULE_LICENSE_APACHE2 b/packages/ExtShared/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/packages/ExtShared/MODULE_LICENSE_APACHE2
diff --git a/packages/ExtShared/NOTICE b/packages/ExtShared/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/packages/ExtShared/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/packages/ExtShared/proguard.proguard b/packages/ExtShared/proguard.proguard
new file mode 100644
index 0000000..e5dfbe1
--- /dev/null
+++ b/packages/ExtShared/proguard.proguard
@@ -0,0 +1,7 @@
+-keepparameternames
+-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
+                SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
+
+-keep public class * {
+    public protected *;
+}
diff --git a/packages/PrintSpooler/res/color/item_text_color.xml b/packages/ExtShared/res/values/strings.xml
similarity index 71%
copy from packages/PrintSpooler/res/color/item_text_color.xml
copy to packages/ExtShared/res/values/strings.xml
index f580fbd..0914e43 100644
--- a/packages/PrintSpooler/res/color/item_text_color.xml
+++ b/packages/ExtShared/res/values/strings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-   <item android:state_enabled="true" android:color="#333333" />
-   <item android:color="#888888"/>
-</selector>
\ No newline at end of file
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">Android Shared Library</string>
+</resources>
diff --git a/packages/ExtShared/src/android/ext/shared/Version.java b/packages/ExtShared/src/android/ext/shared/Version.java
new file mode 100644
index 0000000..3ff2d41
--- /dev/null
+++ b/packages/ExtShared/src/android/ext/shared/Version.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.ext.shared;
+
+/**
+ * Class that provides the version of the library.
+ */
+public final class Version {
+
+    private Version() {
+        /* do nothing - hide constructor */
+    }
+
+    /**
+     * Gets the version of the library.
+     *
+     * @return The version.
+     */
+    public static int getVersionCode() {
+        return 1;
+    }
+}
\ No newline at end of file
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 1bfc19c..f89934d 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -27,6 +27,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.Environment;
 import android.os.FileObserver;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -133,9 +134,6 @@
             final String rootId;
             final String title;
             if (volume.getType() == VolumeInfo.TYPE_EMULATED) {
-                // save off the primary volume for subsequent "Home" dir initialization.
-                primaryVolume = volume;
-
                 // We currently only support a single emulated volume mounted at
                 // a time, and it's always considered the primary
                 rootId = ROOT_ID_PRIMARY_EMULATED;
@@ -166,9 +164,14 @@
             mRoots.put(rootId, root);
 
             root.rootId = rootId;
-            root.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED
+            root.flags = Root.FLAG_LOCAL_ONLY
                     | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
 
+            if (volume.isPrimary()) {
+                // save off the primary volume for subsequent "Home" dir initialization.
+                primaryVolume = volume;
+                root.flags |= Root.FLAG_ADVANCED;
+            }
             // Dunno when this would NOT be the case, but never hurts to be correct.
             if (volume.isMountedWritable()) {
                 root.flags |= Root.FLAG_SUPPORTS_CREATE;
@@ -208,8 +211,10 @@
                 root.flags |= Root.FLAG_SUPPORTS_CREATE;
             }
 
+            // Create the "Home" directory on disk, but don't the localized root.title
+            // since the directories shouldn't be localized.
             root.visiblePath = new File(
-                    primaryVolume.getPathForUser(userId), root.rootId);
+                    primaryVolume.getPathForUser(userId), Environment.DIRECTORY_HOME);
             root.path = new File(
                     primaryVolume.getInternalPathForUser(userId), root.rootId);
             try {
diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml
index 2b279ad..439de3d 100644
--- a/packages/Keyguard/res/values-ro/strings.xml
+++ b/packages/Keyguard/res/values-ro/strings.xml
@@ -59,7 +59,7 @@
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Model uitat"</string>
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Model greşit"</string>
-    <string name="kg_wrong_password" msgid="2333281762128113157">"Parolă greşită"</string>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"Parolă greșită"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Cod PIN greşit"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Încercați din nou peste <xliff:g id="NUMBER">%d</xliff:g> (de) secunde."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Desenaţi modelul"</string>
@@ -92,8 +92,8 @@
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="6853071165802933545">"Ați efectuat <xliff:g id="NUMBER_0">%1$d</xliff:g> încercări incorecte de deblocare a telefonului. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4686386497449912146">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a tabletei. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4951507352869831265">"Ați efectuat <xliff:g id="NUMBER">%d</xliff:g> încercări incorecte de deblocare a telefonului. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereuşite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g> (de) secunde."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Codul PIN pentru cardul SIM este incorect. Contactați operatorul pentru a vă debloca dispozitivul."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
       <item quantity="few">Codul PIN pentru cardul SIM este incorect. V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> încercări.</item>
diff --git a/packages/MtpDocumentsProvider/AndroidManifest.xml b/packages/MtpDocumentsProvider/AndroidManifest.xml
index 7ea54c9..2dd49ab 100644
--- a/packages/MtpDocumentsProvider/AndroidManifest.xml
+++ b/packages/MtpDocumentsProvider/AndroidManifest.xml
@@ -30,16 +30,12 @@
         </activity>
 
         <receiver android:name=".UsbIntentReceiver" android:exported="true">
-            <!-- TODO: Remove an intent-filter for USB_DEVICE_ATTACHED after the provider becomes to
-                       open devices on demand. -->
             <intent-filter>
                 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
+                <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
             </intent-filter>
             <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                        android:resource="@xml/device_filter" />
-            <intent-filter>
-                <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
-            </intent-filter>
         </receiver>
     </application>
 </manifest>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 1d72647..ef1e8e2 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -24,9 +24,11 @@
 import android.os.Bundle;
 import android.os.Process;
 import android.provider.DocumentsContract;
+import android.util.Log;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.LinkedList;
@@ -56,11 +58,17 @@
 
     private static MtpObjectInfo[] loadDocuments(MtpManager manager, int deviceId, int[] handles)
             throws IOException {
-        final MtpObjectInfo[] objectInfos = new MtpObjectInfo[handles.length];
+        final ArrayList<MtpObjectInfo> objects = new ArrayList<>();
         for (int i = 0; i < handles.length; i++) {
-            objectInfos[i] = manager.getObjectInfo(deviceId, handles[i]);
+            final MtpObjectInfo info = manager.getObjectInfo(deviceId, handles[i]);
+            if (info == null) {
+                Log.e(MtpDocumentsProvider.TAG,
+                        "Failed to obtain object info handle=" + handles[i]);
+                continue;
+            }
+            objects.add(info);
         }
-        return objectInfos;
+        return objects.toArray(new MtpObjectInfo[objects.size()]);
     }
 
     synchronized Cursor queryChildDocuments(String[] columnNames, Identifier parent)
@@ -74,7 +82,7 @@
             int parentHandle = parent.mObjectHandle;
             // Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
             // getObjectHandles if we would like to obtain children under the root.
-            if (parentHandle == Identifier.DUMMY_HANDLE_FOR_ROOT) {
+            if (parent.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
                 parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
             }
             // TODO: Handle nit race around here.
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
index 20b3bf5..124d207 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
@@ -17,36 +17,65 @@
 package com.android.mtp;
 
 import java.util.Objects;
+import static com.android.mtp.MtpDatabaseConstants.DocumentType;
 
 /**
  * Static utilities for ID.
  */
 class Identifier {
-    final static int DUMMY_HANDLE_FOR_ROOT = 0;
-
     final int mDeviceId;
     final int mStorageId;
     final int mObjectHandle;
     final String mDocumentId;
+    final @DocumentType int mDocumentType;
 
-    Identifier(int deviceId, int storageId, int objectHandle, String documentId) {
+    Identifier(int deviceId, int storageId, int objectHandle, String documentId,
+            @DocumentType int documentType) {
         mDeviceId = deviceId;
         mStorageId = storageId;
         mObjectHandle = objectHandle;
         mDocumentId = documentId;
+        mDocumentType = documentType;
     }
 
     @Override
     public boolean equals(Object obj) {
         if (!(obj instanceof Identifier))
             return false;
-        final Identifier other = (Identifier)obj;
+        final Identifier other = (Identifier) obj;
         return mDeviceId == other.mDeviceId && mStorageId == other.mStorageId &&
-                mObjectHandle == other.mObjectHandle;
+                mObjectHandle == other.mObjectHandle && mDocumentId.equals(other.mDocumentId);
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mDeviceId, mStorageId, mObjectHandle, mDocumentId);
     }
+
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder();
+        builder.append("Identifier { ");
+
+        builder.append("mDeviceId: ");
+        builder.append(mDeviceId);
+        builder.append(", ");
+
+        builder.append("mStorageId: ");
+        builder.append(mStorageId);
+        builder.append(", ");
+
+        builder.append("mObjectHandle: ");
+        builder.append(mObjectHandle);
+        builder.append(", ");
+
+        builder.append("mDocumentId: ");
+        builder.append(mDocumentId);
+        builder.append(", ");
+
+        builder.append("mDocumentType: ");
+        builder.append(mDocumentType);
+        builder.append(" }");
+        return builder.toString();
+    }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
index ac47067..3faa8f4 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
@@ -20,11 +20,9 @@
 
 import android.annotation.Nullable;
 import android.content.ContentValues;
-import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
 import android.mtp.MtpObjectInfo;
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
@@ -87,12 +85,10 @@
     /**
      * Puts root information to database.
      * @param parentDocumentId Document ID of device document.
-     * @param resources Resources required to localize root name.
      * @param roots List of root information.
      * @return If roots are added or removed from the database.
      */
-    synchronized boolean putStorageDocuments(
-            String parentDocumentId, Resources resources, MtpRoot[] roots) {
+    synchronized boolean putStorageDocuments(String parentDocumentId, MtpRoot[] roots) {
         final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
         database.beginTransaction();
         try {
@@ -117,7 +113,7 @@
                 valuesList[i] = new ContentValues();
                 extraValuesList[i] = new ContentValues();
                 MtpDatabase.getStorageDocumentValues(
-                        valuesList[i], extraValuesList[i], resources, parentDocumentId, roots[i]);
+                        valuesList[i], extraValuesList[i], parentDocumentId, roots[i]);
             }
             final boolean changed = putDocuments(
                     valuesList,
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 959fac6..8a3ebef 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -108,7 +108,7 @@
      * @param columnNames Column names defined in {@link android.provider.DocumentsContract.Root}.
      * @return Database cursor.
      */
-    Cursor queryRoots(String[] columnNames) {
+    Cursor queryRoots(Resources resources, String[] columnNames) {
         final String selection =
                 COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + " = ?";
         final Cursor deviceCursor = mDatabase.query(
@@ -143,49 +143,54 @@
                         null);
                 try {
                     values.clear();
-                    if (storageCursor.getCount() == 1) {
-                        storageCursor.moveToNext();
-                        DatabaseUtils.cursorRowToContentValues(storageCursor, values);
-                    } else {
-                        final Cursor cursor = builder.query(
-                                mDatabase,
-                                columnNames,
-                                selection + " AND " + COLUMN_DEVICE_ID + " = ?",
-                                strings(ROW_STATE_VALID,
-                                        ROW_STATE_INVALIDATED,
-                                        DOCUMENT_TYPE_DEVICE,
-                                        deviceId),
-                                null,
-                                null,
-                                null);
-                        try {
-                            cursor.moveToNext();
-                            DatabaseUtils.cursorRowToContentValues(cursor, values);
-                        } finally {
-                            cursor.close();
-                        }
+                    try (final Cursor deviceRoot = builder.query(
+                            mDatabase,
+                            columnNames,
+                            selection + " AND " + COLUMN_DEVICE_ID + " = ?",
+                            strings(ROW_STATE_VALID,
+                                    ROW_STATE_INVALIDATED,
+                                    DOCUMENT_TYPE_DEVICE,
+                                    deviceId),
+                            null,
+                            null,
+                            null)) {
+                        deviceRoot.moveToNext();
+                        DatabaseUtils.cursorRowToContentValues(deviceRoot, values);
+                    }
 
-                        if (storageCursor.getCount() != 0) {
-                            long capacityBytes = 0;
-                            long availableBytes = 0;
-                            int capacityIndex = cursor.getColumnIndex(Root.COLUMN_CAPACITY_BYTES);
-                            int availableIndex = cursor.getColumnIndex(Root.COLUMN_AVAILABLE_BYTES);
-                            while (storageCursor.moveToNext()) {
-                                // If requested columnNames does not include COLUMN_XXX_BYTES, we
-                                // don't calculate corresponding values.
-                                if (capacityIndex != -1) {
-                                    capacityBytes += cursor.getLong(capacityIndex);
-                                }
-                                if (availableIndex != -1) {
-                                    availableBytes += cursor.getLong(availableIndex);
-                                }
+                    if (storageCursor.getCount() != 0) {
+                        long capacityBytes = 0;
+                        long availableBytes = 0;
+                        final int capacityIndex =
+                                storageCursor.getColumnIndex(Root.COLUMN_CAPACITY_BYTES);
+                        final int availableIndex =
+                                storageCursor.getColumnIndex(Root.COLUMN_AVAILABLE_BYTES);
+                        while (storageCursor.moveToNext()) {
+                            // If requested columnNames does not include COLUMN_XXX_BYTES, we
+                            // don't calculate corresponding values.
+                            if (capacityIndex != -1) {
+                                capacityBytes += storageCursor.getLong(capacityIndex);
                             }
-                            values.put(Root.COLUMN_CAPACITY_BYTES, capacityBytes);
-                            values.put(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
-                        } else {
-                            values.putNull(Root.COLUMN_CAPACITY_BYTES);
-                            values.putNull(Root.COLUMN_AVAILABLE_BYTES);
+                            if (availableIndex != -1) {
+                                availableBytes += storageCursor.getLong(availableIndex);
+                            }
                         }
+                        values.put(Root.COLUMN_CAPACITY_BYTES, capacityBytes);
+                        values.put(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
+                    } else {
+                        values.putNull(Root.COLUMN_CAPACITY_BYTES);
+                        values.putNull(Root.COLUMN_AVAILABLE_BYTES);
+                    }
+                    if (storageCursor.getCount() == 1 && values.containsKey(Root.COLUMN_TITLE)) {
+                        storageCursor.moveToFirst();
+                        // Add storage name to device name if we have only 1 storage.
+                        values.put(
+                                Root.COLUMN_TITLE,
+                                resources.getString(
+                                        R.string.root_name,
+                                        values.getAsString(Root.COLUMN_TITLE),
+                                        storageCursor.getString(
+                                                storageCursor.getColumnIndex(Root.COLUMN_TITLE))));
                     }
                 } finally {
                     storageCursor.close();
@@ -239,12 +244,45 @@
     }
 
     /**
+     * Returns identifier of single storage if given document points device and it has only one
+     * storage. Otherwise null.
+     *
+     * @param documentId Document ID that may point a device.
+     * @return Identifier for single storage or null.
+     * @throws FileNotFoundException The given document ID is not registered in database.
+     */
+    @Nullable Identifier getSingleStorageIdentifier(String documentId)
+            throws FileNotFoundException {
+        // Check if the parent document is device that has single storage.
+        try (final Cursor cursor = mDatabase.query(
+                TABLE_DOCUMENTS,
+                strings(Document.COLUMN_DOCUMENT_ID),
+                COLUMN_ROW_STATE + " IN (?, ?) AND " +
+                COLUMN_PARENT_DOCUMENT_ID + " = ? AND " +
+                COLUMN_DOCUMENT_TYPE + " = ?",
+                strings(ROW_STATE_VALID,
+                        ROW_STATE_INVALIDATED,
+                        documentId,
+                        DOCUMENT_TYPE_STORAGE),
+                null,
+                null,
+                null)) {
+            if (cursor.getCount() == 1) {
+                cursor.moveToNext();
+                return createIdentifier(cursor.getString(0));
+            } else {
+                return null;
+            }
+        }
+    }
+
+    /**
      * Queries a single document.
      * @param documentId
      * @param projection
      * @return Database cursor.
      */
-    public Cursor queryDocument(String documentId, String[] projection) {
+    Cursor queryDocument(String documentId, String[] projection) {
         return mDatabase.query(
                 TABLE_DOCUMENTS,
                 projection,
@@ -287,12 +325,12 @@
     }
 
     /**
-     * Obtains parent document ID.
+     * Obtains parent identifier.
      * @param documentId
-     * @return parent document ID.
+     * @return parent identifier.
      * @throws FileNotFoundException
      */
-    String getParentId(String documentId) throws FileNotFoundException {
+    Identifier getParentIdentifier(String documentId) throws FileNotFoundException {
         final Cursor cursor = mDatabase.query(
                 TABLE_DOCUMENTS,
                 strings(COLUMN_PARENT_DOCUMENT_ID),
@@ -304,7 +342,7 @@
                 "1");
         try {
             if (cursor.moveToNext()) {
-                return cursor.getString(0);
+                return createIdentifier(cursor.getString(0));
             } else {
                 throw new FileNotFoundException("Cannot find a row having ID=" + documentId);
             }
@@ -352,7 +390,10 @@
         // Currently documentId is old format.
         final Cursor cursor = mDatabase.query(
                 TABLE_DOCUMENTS,
-                strings(COLUMN_DEVICE_ID, COLUMN_STORAGE_ID, COLUMN_OBJECT_HANDLE),
+                strings(COLUMN_DEVICE_ID,
+                        COLUMN_STORAGE_ID,
+                        COLUMN_OBJECT_HANDLE,
+                        COLUMN_DOCUMENT_TYPE),
                 SELECTION_DOCUMENT_ID,
                 strings(documentId),
                 null,
@@ -367,8 +408,9 @@
                 return new Identifier(
                         cursor.getInt(0),
                         cursor.getInt(1),
-                        cursor.isNull(2) ? Identifier.DUMMY_HANDLE_FOR_ROOT : cursor.getInt(2),
-                        documentId);
+                        cursor.getInt(2),
+                        documentId,
+                        cursor.getInt(3));
             }
         } finally {
             cursor.close();
@@ -495,13 +537,11 @@
     /**
      * Gets {@link ContentValues} for the given root.
      * @param values {@link ContentValues} that receives values.
-     * @param resources Resources used to get localized root name.
      * @param root Root to be converted {@link ContentValues}.
      */
     static void getStorageDocumentValues(
             ContentValues values,
             ContentValues extraValues,
-            Resources resources,
             String parentDocumentId,
             MtpRoot root) {
         values.clear();
@@ -512,13 +552,12 @@
         values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
         values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_STORAGE);
         values.put(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
-        values.put(Document.COLUMN_DISPLAY_NAME, root.getRootName(resources));
+        values.put(Document.COLUMN_DISPLAY_NAME, root.mDescription);
         values.putNull(Document.COLUMN_SUMMARY);
         values.putNull(Document.COLUMN_LAST_MODIFIED);
         values.put(Document.COLUMN_ICON, R.drawable.ic_root_mtp);
         values.put(Document.COLUMN_FLAGS, 0);
-        values.put(Document.COLUMN_SIZE,
-                (int) Math.min(root.mMaxCapacity - root.mFreeSpace, Integer.MAX_VALUE));
+        values.put(Document.COLUMN_SIZE, root.mMaxCapacity - root.mFreeSpace);
 
         extraValues.put(
                 Root.COLUMN_FLAGS,
@@ -538,9 +577,7 @@
     static void getObjectDocumentValues(
             ContentValues values, int deviceId, String parentId, MtpObjectInfo info) {
         values.clear();
-        final String mimeType = info.getFormat() == MtpConstants.FORMAT_ASSOCIATION ?
-                DocumentsContract.Document.MIME_TYPE_DIR :
-                MediaFile.getMimeTypeForFormatCode(info.getFormat());
+        final String mimeType = getMimeType(info);
         int flag = 0;
         if (info.getProtectionStatus() == 0) {
             flag |= Document.FLAG_SUPPORTS_DELETE |
@@ -569,6 +606,17 @@
         values.put(Document.COLUMN_SIZE, info.getCompressedSize());
     }
 
+    private static String getMimeType(MtpObjectInfo info) {
+        if (info.getFormat() == MtpConstants.FORMAT_ASSOCIATION) {
+            return DocumentsContract.Document.MIME_TYPE_DIR;
+        }
+        final String formatCodeMimeType = MediaFile.getMimeTypeForFormatCode(info.getFormat());
+        if (formatCodeMimeType != null) {
+            return formatCodeMimeType;
+        }
+        return MediaFile.getMimeTypeForFile(info.getName());
+    }
+
     static String[] strings(Object... args) {
         final String[] results = new String[args.length];
         for (int i = 0; i < args.length; i++) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
index f252e0f..3cfb82f 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
@@ -16,10 +16,13 @@
 
 package com.android.mtp;
 
+import android.annotation.IntDef;
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -92,6 +95,10 @@
      */
     static final int MAP_BY_NAME = 1;
 
+    @IntDef(value = { DOCUMENT_TYPE_DEVICE, DOCUMENT_TYPE_STORAGE, DOCUMENT_TYPE_OBJECT })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DocumentType {}
+
     /**
      * Document that represents a MTP device.
      */
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 6b5f16a..0338454 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -58,6 +58,8 @@
             Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
     };
 
+    static final boolean DEBUG = false;
+
     private final Object mDeviceListLock = new Object();
 
     private static MtpDocumentsProvider sSingleton;
@@ -70,6 +72,7 @@
     private Resources mResources;
     private MtpDatabase mDatabase;
     private AppFuse mAppFuse;
+    private ServiceIntentSender mIntentSender;
 
     /**
      * Provides singleton instance to MtpDocumentsService.
@@ -86,8 +89,9 @@
         mResolver = getContext().getContentResolver();
         mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
         mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_FILE);
-        mRootScanner = new RootScanner(mResolver, mResources, mMtpManager, mDatabase);
+        mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
         mAppFuse = new AppFuse(TAG, new AppFuseCallback());
+        mIntentSender = new ServiceIntentSender(getContext());
         // TODO: Mount AppFuse on demands.
         try {
             mAppFuse.mount(getContext().getSystemService(StorageManager.class));
@@ -105,14 +109,16 @@
             MtpManager mtpManager,
             ContentResolver resolver,
             MtpDatabase database,
-            StorageManager storageManager) {
+            StorageManager storageManager,
+            ServiceIntentSender intentSender) {
         mResources = resources;
         mMtpManager = mtpManager;
         mResolver = resolver;
         mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
         mDatabase = database;
-        mRootScanner = new RootScanner(mResolver, mResources, mMtpManager, mDatabase);
+        mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
         mAppFuse = new AppFuse(TAG, new AppFuseCallback());
+        mIntentSender = intentSender;
         // TODO: Mount AppFuse on demands.
         try {
             mAppFuse.mount(storageManager);
@@ -129,7 +135,7 @@
         if (projection == null) {
             projection = MtpDocumentsProvider.DEFAULT_ROOT_PROJECTION;
         }
-        final Cursor cursor = mDatabase.queryRoots(projection);
+        final Cursor cursor = mDatabase.queryRoots(mResources, projection);
         cursor.setNotificationUri(
                 mResolver, DocumentsContract.buildRootsUri(MtpDocumentsProvider.AUTHORITY));
         return cursor;
@@ -147,14 +153,29 @@
     @Override
     public Cursor queryChildDocuments(String parentDocumentId,
             String[] projection, String sortOrder) throws FileNotFoundException {
+        if (DEBUG) {
+            Log.d(TAG, "queryChildDocuments: " + parentDocumentId);
+        }
         if (projection == null) {
             projection = MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION;
         }
-        final Identifier parentIdentifier = mDatabase.createIdentifier(parentDocumentId);
+        Identifier parentIdentifier = mDatabase.createIdentifier(parentDocumentId);
         try {
+            openDevice(parentIdentifier.mDeviceId);
+            if (parentIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) {
+                final Identifier singleStorageIdentifier =
+                        mDatabase.getSingleStorageIdentifier(parentDocumentId);
+                if (singleStorageIdentifier == null) {
+                    // Returns storage list from database.
+                    return mDatabase.queryChildDocuments(projection, parentDocumentId);
+                }
+                parentIdentifier = singleStorageIdentifier;
+            }
+            // Returns object list from document loader.
             return getDocumentLoader(parentIdentifier).queryChildDocuments(
                     projection, parentIdentifier);
         } catch (IOException exception) {
+            Log.e(MtpDocumentsProvider.TAG, "queryChildDocuments", exception);
             throw new FileNotFoundException(exception.getMessage());
         }
     }
@@ -163,13 +184,17 @@
     public ParcelFileDescriptor openDocument(
             String documentId, String mode, CancellationSignal signal)
                     throws FileNotFoundException {
+        if (DEBUG) {
+            Log.d(TAG, "openDocument: " + documentId);
+        }
         final Identifier identifier = mDatabase.createIdentifier(documentId);
         try {
+            openDevice(identifier.mDeviceId);
             switch (mode) {
                 case "r":
                     final long fileSize = getFileSize(documentId);
-                    // MTP getPartialObject operation does not support files that are larger than 4GB.
-                    // Fallback to non-seekable file descriptor.
+                    // MTP getPartialObject operation does not support files that are larger than
+                    // 4GB. Fallback to non-seekable file descriptor.
                     // TODO: Use getPartialObject64 for MTP devices that support Android vendor
                     // extension.
                     if (fileSize <= 0xffffffffl) {
@@ -190,6 +215,7 @@
                     throw new IllegalArgumentException("Unknown mode for openDocument: " + mode);
             }
         } catch (IOException error) {
+            Log.e(MtpDocumentsProvider.TAG, "openDocument", error);
             throw new FileNotFoundException(error.getMessage());
         }
     }
@@ -201,11 +227,13 @@
             CancellationSignal signal) throws FileNotFoundException {
         final Identifier identifier = mDatabase.createIdentifier(documentId);
         try {
+            openDevice(identifier.mDeviceId);
             return new AssetFileDescriptor(
                     getPipeManager(identifier).readThumbnail(mMtpManager, identifier),
                     0,  // Start offset.
                     AssetFileDescriptor.UNKNOWN_LENGTH);
         } catch (IOException error) {
+            Log.e(MtpDocumentsProvider.TAG, "openDocumentThumbnail", error);
             throw new FileNotFoundException(error.getMessage());
         }
     }
@@ -214,13 +242,21 @@
     public void deleteDocument(String documentId) throws FileNotFoundException {
         try {
             final Identifier identifier = mDatabase.createIdentifier(documentId);
-            final Identifier parentIdentifier =
-                    mDatabase.createIdentifier(mDatabase.getParentId(documentId));
+            openDevice(identifier.mDeviceId);
+            final Identifier parentIdentifier = mDatabase.getParentIdentifier(documentId);
             mMtpManager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle);
             mDatabase.deleteDocument(documentId);
             getDocumentLoader(parentIdentifier).clearTask(parentIdentifier);
             notifyChildDocumentsChange(parentIdentifier.mDocumentId);
+            if (parentIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
+                // If the parent is storage, the object might be appeared as child of device because
+                // we skip storage when the device has only one storage.
+                final Identifier deviceIdentifier = mDatabase.getParentIdentifier(
+                        parentIdentifier.mDocumentId);
+                notifyChildDocumentsChange(deviceIdentifier.mDocumentId);
+            }
         } catch (IOException error) {
+            Log.e(MtpDocumentsProvider.TAG, "deleteDocument", error);
             throw new FileNotFoundException(error.getMessage());
         }
     }
@@ -237,8 +273,12 @@
     @Override
     public String createDocument(String parentDocumentId, String mimeType, String displayName)
             throws FileNotFoundException {
+        if (DEBUG) {
+            Log.d(TAG, "createDocument: " + displayName);
+        }
         try {
             final Identifier parentId = mDatabase.createIdentifier(parentDocumentId);
+            openDevice(parentId.mDeviceId);
             final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe();
             pipe[0].close();  // 0 bytes for a new document.
             final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
@@ -259,18 +299,29 @@
             notifyChildDocumentsChange(parentDocumentId);
             return documentId;
         } catch (IOException error) {
-            Log.e(TAG, error.getMessage());
+            Log.e(TAG, "createDocument", error);
             throw new FileNotFoundException(error.getMessage());
         }
     }
 
     void openDevice(int deviceId) throws IOException {
         synchronized (mDeviceListLock) {
+            if (mDeviceToolkits.containsKey(deviceId)) {
+                return;
+            }
+            if (DEBUG) {
+                Log.d(TAG, "Open device " + deviceId);
+            }
             mMtpManager.openDevice(deviceId);
             mDeviceToolkits.put(
                     deviceId, new DeviceToolkit(mMtpManager, mResolver, mDatabase));
+            mIntentSender.sendUpdateNotificationIntent();
+            try {
+                mRootScanner.resume().await();
+            } catch (InterruptedException error) {
+                Log.e(TAG, "openDevice", error);
+            }
         }
-        mRootScanner.resume();
     }
 
     void closeDevice(int deviceId) throws IOException, InterruptedException {
@@ -278,6 +329,7 @@
             closeDeviceInternal(deviceId);
         }
         mRootScanner.resume();
+        mIntentSender.sendUpdateNotificationIntent();
     }
 
     int[] getOpenedDeviceIds() {
@@ -298,6 +350,13 @@
     }
 
     /**
+     * Resumes root scanner to handle the update of device list.
+     */
+    void resumeRootScanner() {
+        mRootScanner.resume();
+    }
+
+    /**
      * Finalize the content provider for unit tests.
      */
     @Override
@@ -336,6 +395,12 @@
 
     private void closeDeviceInternal(int deviceId) throws IOException, InterruptedException {
         // TODO: Flush the device before closing (if not closed externally).
+        if (!mDeviceToolkits.containsKey(deviceId)) {
+            return;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "Close device " + deviceId);
+        }
         getDeviceToolkit(deviceId).mDocumentLoader.clearTasks();
         mDeviceToolkits.remove(deviceId);
         mMtpManager.closeDevice(deviceId);
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
index 5bede86..9c4952b 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
@@ -19,13 +19,12 @@
 import android.app.Notification;
 import android.app.Service;
 import android.app.NotificationManager;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
-import android.hardware.usb.UsbDevice;
 import android.os.IBinder;
 import android.util.Log;
 
-import com.android.internal.util.Preconditions;
-
 import java.io.IOException;
 
 /**
@@ -36,6 +35,7 @@
 public class MtpDocumentsService extends Service {
     static final String ACTION_OPEN_DEVICE = "com.android.mtp.OPEN_DEVICE";
     static final String ACTION_CLOSE_DEVICE = "com.android.mtp.CLOSE_DEVICE";
+    static final String ACTION_UPDATE_NOTIFICATION = "com.android.mtp.UPDATE_NOTIFICATION";
     static final String EXTRA_DEVICE = "device";
 
     NotificationManager mNotificationManager;
@@ -55,32 +55,10 @@
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         // If intent is null, the service was restarted.
-        if (intent != null) {
-            final MtpDocumentsProvider provider = MtpDocumentsProvider.getInstance();
-            final UsbDevice device = intent.<UsbDevice>getParcelableExtra(EXTRA_DEVICE);
-            try {
-                Preconditions.checkNotNull(device);
-                switch (intent.getAction()) {
-                    case ACTION_OPEN_DEVICE:
-                        provider.openDevice(device.getDeviceId());
-                        break;
-
-                    case ACTION_CLOSE_DEVICE:
-                        mNotificationManager.cancel(device.getDeviceId());
-                        provider.closeDevice(device.getDeviceId());
-                        break;
-
-                    default:
-                        throw new IllegalArgumentException("Received unknown intent action.");
-                }
-            } catch (IOException | InterruptedException | IllegalArgumentException error) {
-                logErrorMessage(error);
-            }
-        } else {
-            // TODO: Fetch devices again.
+        if (intent == null || ACTION_UPDATE_NOTIFICATION.equals(intent.getAction())) {
+            return updateForegroundState() ? START_STICKY : START_NOT_STICKY;
         }
-
-        return updateForegroundState() ? START_STICKY : START_NOT_STICKY;
+        return START_NOT_STICKY;
     }
 
     /**
@@ -92,6 +70,7 @@
         final int[] deviceIds = provider.getOpenedDeviceIds();
         int notificationId = 0;
         Notification notification = null;
+        // TODO: Hide notification if the device has already been removed.
         for (final int deviceId : deviceIds) {
             try {
                 final String title = getResources().getString(
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index efe5ff1..5519efd 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -273,9 +273,7 @@
             final MtpRoot[] results = new MtpRoot[storageIds.length];
             for (int i = 0; i < storageIds.length; i++) {
                 results[i] = new MtpRoot(
-                        device.getDeviceId(),
-                        device.getDeviceInfo().getModel(),
-                        device.getStorageInfo(storageIds[i]));
+                        device.getDeviceId(), device.getStorageInfo(storageIds[i]));
             }
             return results;
         }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
index ec338c3..8530aaf 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
@@ -16,7 +16,6 @@
 
 package com.android.mtp;
 
-import android.content.res.Resources;
 import android.mtp.MtpStorageInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -24,7 +23,6 @@
 class MtpRoot {
     final int mDeviceId;
     final int mStorageId;
-    final String mDeviceModelName;
     final String mDescription;
     final long mFreeSpace;
     final long mMaxCapacity;
@@ -33,24 +31,21 @@
     @VisibleForTesting
     MtpRoot(int deviceId,
             int storageId,
-            String deviceName,
             String description,
             long freeSpace,
             long maxCapacity,
             String volumeIdentifier) {
         mDeviceId = deviceId;
         mStorageId = storageId;
-        mDeviceModelName = deviceName;
         mDescription = description;
         mFreeSpace = freeSpace;
         mMaxCapacity = maxCapacity;
         mVolumeIdentifier = volumeIdentifier;
     }
 
-    MtpRoot(int deviceId, String deviceModelName, MtpStorageInfo storageInfo) {
+    MtpRoot(int deviceId, MtpStorageInfo storageInfo) {
         mDeviceId = deviceId;
         mStorageId = storageInfo.getStorageId();
-        mDeviceModelName = deviceModelName;
         mDescription = storageInfo.getDescription();
         mFreeSpace = storageInfo.getFreeSpace();
         mMaxCapacity = storageInfo.getMaxCapacity();
@@ -64,7 +59,6 @@
         final MtpRoot other = (MtpRoot) object;
         return mDeviceId == other.mDeviceId &&
                 mStorageId == other.mStorageId &&
-                mDeviceModelName.equals(other.mDeviceModelName) &&
                 mDescription.equals(other.mDescription) &&
                 mFreeSpace == other.mFreeSpace &&
                 mMaxCapacity == other.mMaxCapacity &&
@@ -73,19 +67,12 @@
 
     @Override
     public int hashCode() {
-        return mDeviceId ^ mStorageId ^ mDeviceModelName.hashCode() ^ mDescription.hashCode() ^
+        return mDeviceId ^ mStorageId ^ mDescription.hashCode() ^
                 ((int) mFreeSpace) ^ ((int) mMaxCapacity) ^ mVolumeIdentifier.hashCode();
     }
-    
+
     @Override
     public String toString() {
-        return "MtpRoot{Name: " + mDeviceModelName + " " + mDescription + "}";
-    }
-    
-    String getRootName(Resources resources) {
-        return String.format(
-                resources.getString(R.string.root_name),
-                mDeviceModelName,
-                mDescription);
+        return "MtpRoot{Name: " + mDescription + "}";
     }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
index 15b8ef3..a4c3cf4 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
@@ -1,12 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.android.mtp;
 
 import android.content.ContentResolver;
-import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Process;
 import android.provider.DocumentsContract;
 import android.util.Log;
 
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.FutureTask;
@@ -35,7 +51,6 @@
     private final static long AWAIT_TERMINATION_TIMEOUT = 2000;
 
     final ContentResolver mResolver;
-    final Resources mResources;
     final MtpManager mManager;
     final MtpDatabase mDatabase;
 
@@ -44,11 +59,9 @@
 
     RootScanner(
             ContentResolver resolver,
-            Resources resources,
             MtpManager manager,
             MtpDatabase database) {
         mResolver = resolver;
-        mResources = resources;
         mManager = manager;
         mDatabase = database;
     }
@@ -64,9 +77,8 @@
 
     /**
      * Starts to check new changes right away.
-     * If the background thread has already gone, it restarts another background thread.
      */
-    synchronized void resume() {
+    synchronized CountDownLatch resume() {
         if (mExecutor == null) {
             // Only single thread updates the database.
             mExecutor = Executors.newSingleThreadExecutor();
@@ -75,8 +87,10 @@
             // Cancel previous task.
             mCurrentTask.cancel(true);
         }
-        mCurrentTask = new FutureTask<Void>(new UpdateRootsRunnable(), null);
+        final UpdateRootsRunnable runnable = new UpdateRootsRunnable();
+        mCurrentTask = new FutureTask<Void>(runnable, null);
         mExecutor.submit(mCurrentTask);
+        return runnable.mFirstScanCompleted;
     }
 
     /**
@@ -98,6 +112,8 @@
      * Runnable to scan roots and update the database information.
      */
     private final class UpdateRootsRunnable implements Runnable {
+        final CountDownLatch mFirstScanCompleted = new CountDownLatch(1);
+
         @Override
         public void run() {
             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
@@ -124,8 +140,7 @@
                         continue;
                     }
                     mDatabase.getMapper().startAddingDocuments(documentId);
-                    if (mDatabase.getMapper().putStorageDocuments(
-                            documentId, mResources, device.roots)) {
+                    if (mDatabase.getMapper().putStorageDocuments(documentId, device.roots)) {
                         changed = true;
                     }
                     if (mDatabase.getMapper().stopAddingDocuments(documentId)) {
@@ -136,6 +151,7 @@
                 if (changed) {
                     notifyChange();
                 }
+                mFirstScanCompleted.countDown();
                 pollingCount++;
                 try {
                     // Use SHORT_POLLING_PERIOD for the first SHORT_POLLING_TIMES because it is
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
new file mode 100644
index 0000000..a1bb2c1
--- /dev/null
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.mtp;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Sends intent to MtpDocumentsService.
+ */
+class ServiceIntentSender {
+    private Context mContext;
+
+    ServiceIntentSender(Context context) {
+        mContext = context;
+    }
+
+    void sendUpdateNotificationIntent() {
+        final Intent intent = new Intent(MtpDocumentsService.ACTION_UPDATE_NOTIFICATION);
+        intent.setComponent(new ComponentName(mContext, MtpDocumentsService.class));
+        mContext.startService(intent);
+    }
+}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/UsbIntentReceiver.java b/packages/MtpDocumentsProvider/src/com/android/mtp/UsbIntentReceiver.java
index 0ac130e..0489ea8 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/UsbIntentReceiver.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/UsbIntentReceiver.java
@@ -21,7 +21,9 @@
 import android.content.Intent;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbManager;
-import android.net.Uri;
+import android.util.Log;
+
+import java.io.IOException;
 
 public class UsbIntentReceiver extends BroadcastReceiver {
     @Override
@@ -29,17 +31,15 @@
         final UsbDevice device = intent.getExtras().getParcelable(UsbManager.EXTRA_DEVICE);
         switch (intent.getAction()) {
             case UsbManager.ACTION_USB_DEVICE_ATTACHED:
-                startService(context, MtpDocumentsService.ACTION_OPEN_DEVICE, device);
+                MtpDocumentsProvider.getInstance().resumeRootScanner();
                 break;
             case UsbManager.ACTION_USB_DEVICE_DETACHED:
-                startService(context, MtpDocumentsService.ACTION_CLOSE_DEVICE, device);
+                try {
+                    MtpDocumentsProvider.getInstance().closeDevice(device.getDeviceId());
+                } catch (IOException | InterruptedException e) {
+                    Log.e(MtpDocumentsProvider.TAG, "Failed to close device", e);
+                }
                 break;
         }
     }
-
-    private void startService(Context context, String action, UsbDevice device) {
-        final Intent intent = new Intent(action, Uri.EMPTY, context, MtpDocumentsService.class);
-        intent.putExtra(MtpDocumentsService.EXTRA_DEVICE, device);
-        context.startService(intent);
-    }
 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index f37a55c..af1fed4 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -35,14 +35,15 @@
     private BlockableTestMtpManager mManager;
     private TestContentResolver mResolver;
     private DocumentLoader mLoader;
-    final private Identifier mParentIdentifier = new Identifier(0, 0, 0, "1");
+    final private Identifier mParentIdentifier = new Identifier(
+            0, 0, 0, "1", MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE);
 
     @Override
     public void setUp() {
         mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", new TestResources(), new MtpRoot[] {
-                new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "")
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 0, "Storage", 1000, 1000, "")
         });
         mDatabase.getMapper().stopAddingDocuments("deviceDocId");
         mManager = new BlockableTestMtpManager(getContext());
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 8075999..a49dc67 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -81,8 +81,8 @@
         mDatabase.getMapper().stopAddingDocuments(null);
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 1, "Device", "Storage", 1000, 2000, "")
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 1, "Storage", 1000, 2000, "")
         });
         mDatabase.getMapper().stopAddingDocuments("1");
 
@@ -96,7 +96,7 @@
             assertEquals(1, getInt(cursor, COLUMN_STORAGE_ID));
             assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
             assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, getString(cursor, COLUMN_MIME_TYPE));
-            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             assertTrue(isNull(cursor, COLUMN_SUMMARY));
             assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
             assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
@@ -109,7 +109,7 @@
         }
 
         {
-            final Cursor cursor = mDatabase.queryRoots(new String [] {
+            final Cursor cursor = mDatabase.queryRoots(resources, new String [] {
                     Root.COLUMN_ROOT_ID,
                     Root.COLUMN_FLAGS,
                     Root.COLUMN_ICON,
@@ -122,14 +122,14 @@
             assertEquals(1, cursor.getCount());
 
             cursor.moveToNext();
-            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
             assertEquals(
                     Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE,
                     getInt(cursor, Root.COLUMN_FLAGS));
             assertEquals(R.drawable.ic_root_mtp, getInt(cursor, Root.COLUMN_ICON));
             assertEquals("Device Storage", getString(cursor, Root.COLUMN_TITLE));
             assertTrue(isNull(cursor, Root.COLUMN_SUMMARY));
-            assertEquals(2, getInt(cursor, Root.COLUMN_DOCUMENT_ID));
+            assertEquals(1, getInt(cursor, Root.COLUMN_DOCUMENT_ID));
             assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             assertEquals(2000, getInt(cursor, Root.COLUMN_CAPACITY_BYTES));
 
@@ -139,10 +139,10 @@
 
     public void testPutStorageDocuments() throws Exception {
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", resources, new MtpRoot[] {
-                new MtpRoot(0, 1, "Device", "Storage", 1000, 2000, ""),
-                new MtpRoot(0, 2, "Device", "Storage", 2000, 4000, ""),
-                new MtpRoot(0, 3, "Device", "/@#%&<>Storage", 3000, 6000,"")
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 1, "Storage", 1000, 2000, ""),
+                new MtpRoot(0, 2, "Storage", 2000, 4000, ""),
+                new MtpRoot(0, 3, "/@#%&<>Storage", 3000, 6000,"")
         });
 
         {
@@ -155,7 +155,7 @@
             assertEquals(1, getInt(cursor, COLUMN_STORAGE_ID));
             assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
             assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, getString(cursor, COLUMN_MIME_TYPE));
-            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             assertTrue(isNull(cursor, COLUMN_SUMMARY));
             assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
             assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
@@ -166,11 +166,11 @@
 
             cursor.moveToNext();
             assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
-            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
 
             cursor.moveToNext();
             assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
-            assertEquals("Device /@#%&<>Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("/@#%&<>Storage", getString(cursor, COLUMN_DISPLAY_NAME));
 
             cursor.close();
         }
@@ -264,9 +264,9 @@
         };
 
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage A", 1000, 0, ""),
-                new MtpRoot(0, 101, "Device", "Storage B", 1001, 0, "")
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 1000, 0, ""),
+                new MtpRoot(0, 101, "Storage B", 1001, 0, "")
         });
 
         {
@@ -275,11 +275,11 @@
             cursor.moveToNext();
             assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
             assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(101, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
@@ -291,18 +291,18 @@
             cursor.moveToNext();
             assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
             assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", resources, new MtpRoot[] {
-                new MtpRoot(0, 200, "Device", "Storage A", 2000, 0, ""),
-                new MtpRoot(0, 202, "Device", "Storage C", 2002, 0, "")
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 200, "Storage A", 2000, 0, ""),
+                new MtpRoot(0, 202, "Storage C", 2002, 0, "")
         });
 
         {
@@ -311,15 +311,15 @@
             cursor.moveToNext();
             assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
             assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
             assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
@@ -331,11 +331,11 @@
             cursor.moveToNext();
             assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
             assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
     }
@@ -432,11 +432,11 @@
 
         mDatabase.getMapper().startAddingDocuments("1");
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device A", "Storage", 0, 0, "")
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage", 0, 0, "")
         });
-        mDatabase.getMapper().putStorageDocuments("2", resources, new MtpRoot[] {
-                new MtpRoot(1, 100, "Device B", "Storage", 0, 0, "")
+        mDatabase.getMapper().putStorageDocuments("2", new MtpRoot[] {
+                new MtpRoot(1, 100, "Storage", 0, 0, "")
         });
 
         {
@@ -445,22 +445,22 @@
             cursor.moveToNext();
             assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device A Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
             assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device B Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
         {
-            final Cursor cursor = mDatabase.queryRoots(rootColumns);
+            final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals(3, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
             assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals(4, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
             assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
@@ -469,11 +469,11 @@
 
         mDatabase.getMapper().startAddingDocuments("1");
         mDatabase.getMapper().startAddingDocuments("2");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 200, "Device", "Storage", 2000, 0, "")
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 200, "Storage", 2000, 0, "")
         });
-        mDatabase.getMapper().putStorageDocuments("2", resources, new MtpRoot[] {
-                new MtpRoot(1, 300, "Device", "Storage", 3000, 0, "")
+        mDatabase.getMapper().putStorageDocuments("2", new MtpRoot[] {
+                new MtpRoot(1, 300, "Storage", 3000, 0, "")
         });
         mDatabase.getMapper().stopAddingDocuments("1");
         mDatabase.getMapper().stopAddingDocuments("2");
@@ -482,24 +482,24 @@
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
-            assertEquals(6, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
         {
-            final Cursor cursor = mDatabase.queryRoots(rootColumns);
+            final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals(5, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
             assertEquals(2000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals(6, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
             assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
@@ -562,24 +562,24 @@
 
         mDatabase.getMapper().startAddingDocuments(null);
         mDatabase.getMapper().putDeviceDocument(
-                new MtpDeviceRecord(0, "Device",  false,  new MtpRoot[0], null, null));
+                new MtpDeviceRecord(0, "Device", false,  new MtpRoot[0], null, null));
         mDatabase.getMapper().stopAddingDocuments(null);
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage", 0, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage", 0, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 200, "Device", "Storage", 2000, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 200, "Storage", 2000, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 300, "Device", "Storage", 3000, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 300, "Storage", 3000, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("1");
 
@@ -589,14 +589,14 @@
             cursor.moveToNext();
             assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
         {
-            final Cursor cursor = mDatabase.queryRoots(rootColumns);
+            final Cursor cursor = mDatabase.queryRoots(resources, rootColumns);
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
             assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
@@ -610,15 +610,15 @@
         };
 
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage", 0, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage", 0, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
 
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", resources, new MtpRoot[] {
-                new MtpRoot(0, 200, "Device", "Storage", 2000, 0, ""),
-                new MtpRoot(0, 201, "Device", "Storage", 2001, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 200, "Storage", 2000, 0, ""),
+                new MtpRoot(0, 201, "Storage", 2001, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
@@ -628,11 +628,11 @@
             cursor.moveToNext();
             assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
             assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(201, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
     }
@@ -646,14 +646,14 @@
         // The client code should be able to replace existing rows with new information.
         // Add one.
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("1");
         // Replace it.
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage B", 1000, 1000, ""),
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage B", 1000, 1000, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("1");
         {
@@ -667,7 +667,7 @@
             cursor.moveToNext();
             assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
             assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
-            assertEquals("Device Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertEquals("Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
         {
@@ -676,10 +676,10 @@
                     Root.COLUMN_TITLE,
                     Root.COLUMN_AVAILABLE_BYTES
             };
-            final Cursor cursor = mDatabase.queryRoots(columns);
+            final Cursor cursor = mDatabase.queryRoots(resources, columns);
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
             assertEquals("Device Storage B", getString(cursor, Root.COLUMN_TITLE));
             assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
@@ -695,21 +695,21 @@
         mDatabase.getMapper().stopAddingDocuments(null);
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
-        final Cursor oldCursor = mDatabase.queryRoots(strings(Root.COLUMN_ROOT_ID));
+        final Cursor oldCursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_ROOT_ID));
         assertEquals(1, oldCursor.getCount());
 
         // Add one.
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 101, "Device", "Storage B", 1000, 1000, ""),
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 101, "Storage B", 1000, 1000, ""),
         });
         // Add one more before resolving unmapped documents.
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 102, "Device", "Storage B", 1000, 1000, ""),
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 102, "Storage B", 1000, 1000, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("1");
 
@@ -729,15 +729,15 @@
 
     public void testQueryDocuments() {
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
         final Cursor cursor = mDatabase.queryDocument("1", strings(Document.COLUMN_DISPLAY_NAME));
         assertEquals(1, cursor.getCount());
         cursor.moveToNext();
-        assertEquals("Device Storage A", getString(cursor, Document.COLUMN_DISPLAY_NAME));
+        assertEquals("Storage A", getString(cursor, Document.COLUMN_DISPLAY_NAME));
         cursor.close();
     }
 
@@ -750,7 +750,7 @@
 
         // It the device does not have storages, it shows a device root.
         {
-            final Cursor cursor = mDatabase.queryRoots(strings(Root.COLUMN_TITLE));
+            final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
             assertEquals("Device", cursor.getString(0));
@@ -758,14 +758,14 @@
         }
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, "")
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 0, 0, "")
         });
         mDatabase.getMapper().stopAddingDocuments("1");
 
         // It the device has single storage, it shows a storage root.
         {
-            final Cursor cursor = mDatabase.queryRoots(strings(Root.COLUMN_TITLE));
+            final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
             assertEquals("Device Storage A", cursor.getString(0));
@@ -773,15 +773,15 @@
         }
 
         mDatabase.getMapper().startAddingDocuments("1");
-        mDatabase.getMapper().putStorageDocuments("1", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
-                new MtpRoot(0, 101, "Device", "Storage B", 0, 0, "")
+        mDatabase.getMapper().putStorageDocuments("1", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
+                new MtpRoot(0, 101, "Storage B", 0, 0, "")
         });
         mDatabase.getMapper().stopAddingDocuments("1");
 
         // It the device has multiple storages, it shows a device root.
         {
-            final Cursor cursor = mDatabase.queryRoots(strings(Root.COLUMN_TITLE));
+            final Cursor cursor = mDatabase.queryRoots(resources, strings(Root.COLUMN_TITLE));
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
             assertEquals("Device", cursor.getString(0));
@@ -791,8 +791,8 @@
 
     public void testGetParentId() throws FileNotFoundException {
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
@@ -805,13 +805,13 @@
                 });
         mDatabase.getMapper().stopAddingDocuments("1");
 
-        assertEquals("1", mDatabase.getParentId("2"));
+        assertEquals("1", mDatabase.getParentIdentifier("2").mDocumentId);
     }
 
     public void testDeleteDocument() {
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
@@ -854,8 +854,8 @@
 
     public void testPutNewDocument() {
         mDatabase.getMapper().startAddingDocuments("deviceDocId");
-        mDatabase.getMapper().putStorageDocuments("deviceDocId", resources, new MtpRoot[] {
-                new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
+        mDatabase.getMapper().putStorageDocuments("deviceDocId", new MtpRoot[] {
+                new MtpRoot(0, 100, "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
@@ -911,7 +911,7 @@
                 DocumentsContract.Root.COLUMN_TITLE,
                 DocumentsContract.Root.COLUMN_AVAILABLE_BYTES
         };
-        try (final Cursor cursor = mDatabase.queryRoots(columns)) {
+        try (final Cursor cursor = mDatabase.queryRoots(resources, columns)) {
             assertEquals(1, cursor.getCount());
             assertTrue(cursor.moveToNext());
             assertEquals(1, cursor.getLong(0));
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 7066f7d..5b0f557 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -23,13 +23,11 @@
 import android.os.ParcelFileDescriptor;
 import android.os.storage.StorageManager;
 import android.provider.DocumentsContract.Root;
-import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
 import android.provider.DocumentsContract;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -64,13 +62,12 @@
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         mMtpManager.addValidDevice(new MtpDeviceRecord(
                 0,
-                "Device",
+                "Device A",
                 false /* unopened */,
                 new MtpRoot[] {
                     new MtpRoot(
                             0 /* deviceId */,
                             1 /* storageId */,
-                            "Device A" /* device model name */,
                             "Storage A" /* volume description */,
                             1024 /* free space */,
                             2048 /* total space */,
@@ -79,11 +76,14 @@
                 null,
                 null));
 
-        mProvider.openDevice(0);
+        mProvider.resumeRootScanner();
         mResolver.waitForNotification(ROOTS_URI, 1);
 
-        mProvider.closeDevice(0);
+        mProvider.openDevice(0);
         mResolver.waitForNotification(ROOTS_URI, 2);
+
+        mProvider.closeDevice(0);
+        mResolver.waitForNotification(ROOTS_URI, 3);
     }
 
     public void testOpenAndCloseErrorDevice() throws Exception {
@@ -94,24 +94,17 @@
         } catch (Throwable error) {
             assertTrue(error instanceof IOException);
         }
-
-        try {
-            mProvider.closeDevice(1);
-            fail();
-        } catch (Throwable error) {
-            assertTrue(error instanceof IOException);
-        }
+        assertEquals(0, mProvider.getOpenedDeviceIds().length);
 
         // Check if the following notification is the first one or not.
         mMtpManager.addValidDevice(new MtpDeviceRecord(
                 0,
-                "Device",
+                "Device A",
                 false /* unopened */,
                 new MtpRoot[] {
                     new MtpRoot(
                             0 /* deviceId */,
                             1 /* storageId */,
-                            "Device A" /* device model name */,
                             "Storage A" /* volume description */,
                             1024 /* free space */,
                             2048 /* total space */,
@@ -119,21 +112,66 @@
                 },
                 null,
                 null));
-        mProvider.openDevice(0);
+        mProvider.resumeRootScanner();
         mResolver.waitForNotification(ROOTS_URI, 1);
+        mProvider.openDevice(0);
+        mResolver.waitForNotification(ROOTS_URI, 2);
+    }
+
+    public void testOpenDeviceOnDemand() throws Exception {
+        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+        mMtpManager.addValidDevice(new MtpDeviceRecord(
+                0,
+                "Device A",
+                false /* unopened */,
+                new MtpRoot[] {
+                    new MtpRoot(
+                            0 /* deviceId */,
+                            1 /* storageId */,
+                            "Storage A" /* volume description */,
+                            1024 /* free space */,
+                            2048 /* total space */,
+                            "" /* no volume identifier */)
+                },
+                null,
+                null));
+        mMtpManager.setObjectHandles(0, 1, -1, new int[0]);
+        mProvider.resumeRootScanner();
+        mResolver.waitForNotification(ROOTS_URI, 1);
+        final String[] columns = new String[] {
+                DocumentsContract.Root.COLUMN_TITLE,
+                DocumentsContract.Root.COLUMN_DOCUMENT_ID
+        };
+        try (final Cursor cursor = mProvider.queryRoots(columns)) {
+            assertEquals(1, cursor.getCount());
+            assertTrue(cursor.moveToNext());
+            assertEquals("Device A", cursor.getString(0));
+            assertEquals(1, cursor.getLong(1));
+        }
+        {
+            final int [] openedDevice = mProvider.getOpenedDeviceIds();
+            assertEquals(0, openedDevice.length);
+        }
+        // Device is opened automatically when querying its children.
+        try (final Cursor cursor = mProvider.queryChildDocuments("1", null, null)) {}
+
+        {
+            final int [] openedDevice = mProvider.getOpenedDeviceIds();
+            assertEquals(1, openedDevice.length);
+            assertEquals(0, openedDevice[0]);
+        }
     }
 
     public void testQueryRoots() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         mMtpManager.addValidDevice(new MtpDeviceRecord(
                 0,
-                "Device",
+                "Device A",
                 false /* unopened */,
                 new MtpRoot[] {
                         new MtpRoot(
                                 0 /* deviceId */,
                                 1 /* storageId */,
-                                "Device A" /* device model name */,
                                 "Storage A" /* volume description */,
                                 1024 /* free space */,
                                 2048 /* total space */,
@@ -143,13 +181,12 @@
                 null));
         mMtpManager.addValidDevice(new MtpDeviceRecord(
                 1,
-                "Device",
+                "Device B",
                 false /* unopened */,
                 new MtpRoot[] {
                     new MtpRoot(
                             1 /* deviceId */,
                             1 /* storageId */,
-                            "Device B" /* device model name */,
                             "Storage B" /* volume description */,
                             2048 /* free space */,
                             4096 /* total space */,
@@ -164,11 +201,11 @@
             final Cursor cursor = mProvider.queryRoots(null);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("3", cursor.getString(0));
+            assertEquals("1", cursor.getString(0));
             assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
             assertEquals("Device A Storage A", cursor.getString(3));
-            assertEquals("3", cursor.getString(4));
+            assertEquals("1", cursor.getString(4));
             assertEquals(1024, cursor.getInt(5));
         }
 
@@ -179,11 +216,11 @@
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
             cursor.moveToNext();
-            assertEquals("4", cursor.getString(0));
+            assertEquals("2", cursor.getString(0));
             assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
             assertEquals("Device B Storage B", cursor.getString(3));
-            assertEquals("4", cursor.getString(4));
+            assertEquals("2", cursor.getString(4));
             assertEquals(2048, cursor.getInt(5));
         }
     }
@@ -194,13 +231,12 @@
                 0, "Device A", false /* unopened */, new MtpRoot[0], null, null));
         mMtpManager.addValidDevice(new MtpDeviceRecord(
                 1,
-                "Device",
+                "Device B",
                 false /* unopened */,
                 new MtpRoot[] {
                     new MtpRoot(
                             1 /* deviceId */,
                             1 /* storageId */,
-                            "Device B" /* device model name */,
                             "Storage B" /* volume description */,
                             2048 /* free space */,
                             4096 /* total space */,
@@ -210,9 +246,13 @@
                 null));
         {
             mProvider.openDevice(0);
-            mProvider.openDevice(1);
+            mProvider.resumeRootScanner();
             mResolver.waitForNotification(ROOTS_URI, 1);
 
+            mProvider.openDevice(1);
+            mProvider.resumeRootScanner();
+            mResolver.waitForNotification(ROOTS_URI, 2);
+
             final Cursor cursor = mProvider.queryRoots(null);
             assertEquals(2, cursor.getCount());
 
@@ -225,18 +265,18 @@
             assertEquals(0, cursor.getInt(5));
 
             cursor.moveToNext();
-            assertEquals("3", cursor.getString(0));
+            assertEquals("2", cursor.getString(0));
             assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
             assertEquals("Device B Storage B", cursor.getString(3));
-            assertEquals("3", cursor.getString(4));
+            assertEquals("2", cursor.getString(4));
             assertEquals(2048, cursor.getInt(5));
         }
     }
 
     public void testQueryDocument() throws IOException, InterruptedException, TimeoutException {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
-        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") });
+        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
         setupDocuments(
                 0,
                 0,
@@ -273,7 +313,7 @@
     public void testQueryDocument_directory()
             throws IOException, InterruptedException, TimeoutException {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
-        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") });
+        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
         setupDocuments(
                 0,
                 0,
@@ -312,7 +352,6 @@
                 new MtpRoot(
                         0 /* deviceId */,
                         1 /* storageId */,
-                        "Device A" /* device model name */,
                         "Storage A" /* volume description */,
                         1024 /* free space */,
                         4096 /* total space */,
@@ -324,7 +363,7 @@
         cursor.moveToNext();
         assertEquals("2", cursor.getString(0));
         assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
-        assertEquals("Device A Storage A", cursor.getString(2));
+        assertEquals("Storage A", cursor.getString(2));
         assertTrue(cursor.isNull(3));
         assertEquals(0, cursor.getInt(4));
         assertEquals(3072, cursor.getInt(5));
@@ -332,7 +371,7 @@
 
     public void testQueryChildDocuments() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
-        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") });
+        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
         setupDocuments(
                 0,
                 0,
@@ -375,7 +414,7 @@
 
     public void testQueryChildDocuments_documentError() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
-        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") });
+        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
         mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 });
         try {
             mProvider.queryChildDocuments("1", null, null);
@@ -388,7 +427,7 @@
     public void testDeleteDocument() throws IOException, InterruptedException, TimeoutException {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         setupRoots(0, new MtpRoot[] {
-                new MtpRoot(0, 0, "Device", "Storage", 0, 0, "")
+                new MtpRoot(0, 0, "Storage", 0, 0, "")
         });
         setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
                 new MtpObjectInfo.Builder()
@@ -408,7 +447,7 @@
             throws IOException, InterruptedException, TimeoutException {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         setupRoots(0, new MtpRoot[] {
-                new MtpRoot(0, 0, "Device", "Storage", 0, 0, "")
+                new MtpRoot(0, 0, "Storage", 0, 0, "")
         });
         setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
                 new MtpObjectInfo.Builder()
@@ -431,7 +470,7 @@
     public void testOpenDocument() throws Exception {
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         setupRoots(0, new MtpRoot[] {
-                new MtpRoot(0, 0, "Device", "Storage", 0, 0, "")
+                new MtpRoot(0, 0, "Storage", 0, 0, "")
         });
         final byte[] bytes = "Hello world".getBytes();
         setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
@@ -469,7 +508,7 @@
         };
         setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
         setupRoots(0, new MtpRoot[] {
-                new MtpRoot(0, 0, "Device", "Storage", 0, 0, "")
+                new MtpRoot(0, 0, "Storage", 0, 0, "")
         });
         final byte[] bytes = "Hello world".getBytes();
         setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] {
@@ -492,7 +531,12 @@
         mProvider = new MtpDocumentsProvider();
         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
         assertTrue(mProvider.onCreateForTesting(
-                mResources, mMtpManager, mResolver, mDatabase, storageManager));
+                mResources,
+                mMtpManager,
+                mResolver,
+                mDatabase,
+                storageManager,
+                new TestServiceIntentSender()));
     }
 
     private String[] getStrings(Cursor cursor) {
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index ccdea03..4dfc785 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -44,13 +44,15 @@
     public void testReadDocument_basic() throws Exception {
         mtpManager.setImportFileBytes(0, 1, HELLO_BYTES);
         final ParcelFileDescriptor descriptor = mPipeManager.readDocument(
-                mtpManager, new Identifier(0, 0, 1, null));
+                mtpManager,
+                new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
         assertDescriptor(descriptor, HELLO_BYTES);
     }
 
     public void testReadDocument_error() throws Exception {
-        final ParcelFileDescriptor descriptor =
-                mPipeManager.readDocument(mtpManager, new Identifier(0, 0, 1, null));
+        final ParcelFileDescriptor descriptor = mPipeManager.readDocument(
+                mtpManager,
+                new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
         assertDescriptorError(descriptor);
     }
 
@@ -62,7 +64,9 @@
 
         // Upload testing bytes.
         final ParcelFileDescriptor descriptor = mPipeManager.writeDocument(
-                getContext(), mtpManager, new Identifier(0, 0, 1, null));
+                getContext(),
+                mtpManager,
+                new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
         final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
                 new ParcelFileDescriptor.AutoCloseOutputStream(descriptor);
         outputStream.write(HELLO_BYTES, 0, HELLO_BYTES.length);
@@ -94,13 +98,15 @@
     public void testReadThumbnail_basic() throws Exception {
         mtpManager.setThumbnail(0, 1, HELLO_BYTES);
         final ParcelFileDescriptor descriptor = mPipeManager.readThumbnail(
-                mtpManager, new Identifier(0, 0, 1, null));
+                mtpManager,
+                new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
         assertDescriptor(descriptor, HELLO_BYTES);
     }
 
     public void testReadThumbnail_error() throws Exception {
-        final ParcelFileDescriptor descriptor =
-                mPipeManager.readThumbnail(mtpManager, new Identifier(0, 0, 1, null));
+        final ParcelFileDescriptor descriptor = mPipeManager.readThumbnail(
+                mtpManager,
+                new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
         assertDescriptorError(descriptor);
     }
 
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java
index eb80e3b..b23038b 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java
@@ -27,4 +27,9 @@
         }
         throw new NotFoundException();
     }
+
+    @Override
+    public String getString(int id, Object... formatArgs) throws NotFoundException {
+        return String.format(getString(id), formatArgs);
+    }
 }
diff --git a/wifi/java/android/net/wifi/ScanInfo.aidl b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java
similarity index 61%
copy from wifi/java/android/net/wifi/ScanInfo.aidl
copy to packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java
index 18ae508..d4a4a48 100644
--- a/wifi/java/android/net/wifi/ScanInfo.aidl
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2015, 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,6 +14,13 @@
  * limitations under the License.
  */
 
-package android.net.wifi;
+package com.android.mtp;
 
-parcelable ScanInfo;
+class TestServiceIntentSender extends ServiceIntentSender {
+    TestServiceIntentSender() {
+        super(null);
+    }
+
+    @Override
+    void sendUpdateNotificationIntent() {}
+}
diff --git a/packages/Osu/Android.mk b/packages/Osu/Android.mk
new file mode 100644
index 0000000..15744c5
--- /dev/null
+++ b/packages/Osu/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := telephony-common ims-common bouncycastle conscrypt
+
+LOCAL_PACKAGE_NAME := Osu
+LOCAL_CERTIFICATE := platform
+LOCAL_PRIVILEGED_MODULE := true
+
+include $(BUILD_PACKAGE)
+
+########################
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/Osu/AndroidManifest.xml b/packages/Osu/AndroidManifest.xml
new file mode 100644
index 0000000..288f1a4
--- /dev/null
+++ b/packages/Osu/AndroidManifest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android">
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.READ_WIFI_CREDENTIAL" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application
+	android:enabled="false"
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+	android:persistent="true"
+        android:supportsRtl="true">
+        <activity android:name=".MainActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="com.android.hotspot2.OSU_NOTIFICATION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+	<receiver android:name="com.android.MainActivity$WifiReceiver" >
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" android:enabled="true"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.net.wifi.SCAN_RESULTS" android:enabled="true"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.net.wifi.PASSPOINT_WNM_FRAME_RECEIVED" android:enabled="true"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.net.wifi.PASSPOINT_ICON_RECEIVED" android:enabled="true"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.net.wifi.CONFIGURED_NETWORKS_CHANGE" android:enabled="true"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" android:enabled="true"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.net.wifi.STATE_CHANGE" android:enabled="true"/>
+            </intent-filter>
+	</receiver>
+	<service android:name="com.android.MainActivity$OSUService" />
+    </application>
+
+</manifest>
diff --git a/packages/Osu/res/layout/activity_main.xml b/packages/Osu/res/layout/activity_main.xml
new file mode 100644
index 0000000..7e33537
--- /dev/null
+++ b/packages/Osu/res/layout/activity_main.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/no_osu"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/no_osu"/>
+    <ListView
+        android:id="@+id/profile_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:divider="#1F000000"
+        android:dividerHeight="1dp"
+        android:padding="16dp" />
+
+</LinearLayout>
diff --git a/packages/Osu/res/layout/list_item.xml b/packages/Osu/res/layout/list_item.xml
new file mode 100644
index 0000000..eb431d3
--- /dev/null
+++ b/packages/Osu/res/layout/list_item.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:gravity="top"
+    android:layout_marginTop="10sp"
+    android:layout_marginBottom="10sp"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+    <ImageView
+        android:id="@+id/profile_logo"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_weight="1"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content">
+
+        <TextView
+            android:id="@+id/profile_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="20sp"/>
+
+        <TextView
+            android:id="@+id/profile_detail"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="10sp"
+            android:textSize="12sp"/>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/Osu/res/mipmap-hdpi/ic_launcher.png b/packages/Osu/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
--- /dev/null
+++ b/packages/Osu/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/packages/Osu/res/mipmap-mdpi/ic_launcher.png b/packages/Osu/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
--- /dev/null
+++ b/packages/Osu/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/packages/Osu/res/mipmap-xhdpi/ic_launcher.png b/packages/Osu/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
--- /dev/null
+++ b/packages/Osu/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/packages/Osu/res/mipmap-xxhdpi/ic_launcher.png b/packages/Osu/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
--- /dev/null
+++ b/packages/Osu/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/packages/Osu/res/mipmap-xxxhdpi/ic_launcher.png b/packages/Osu/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/packages/Osu/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/packages/Osu/res/values-w820dp/dimens.xml b/packages/Osu/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/packages/Osu/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+<resources>
+    <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+    <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
diff --git a/packages/Osu/res/values/colors.xml b/packages/Osu/res/values/colors.xml
new file mode 100644
index 0000000..3ab3e9c
--- /dev/null
+++ b/packages/Osu/res/values/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+</resources>
diff --git a/packages/Osu/res/values/dimens.xml b/packages/Osu/res/values/dimens.xml
new file mode 100644
index 0000000..47c8224
--- /dev/null
+++ b/packages/Osu/res/values/dimens.xml
@@ -0,0 +1,5 @@
+<resources>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/packages/Osu/res/values/strings.xml b/packages/Osu/res/values/strings.xml
new file mode 100644
index 0000000..93593dc
--- /dev/null
+++ b/packages/Osu/res/values/strings.xml
@@ -0,0 +1,4 @@
+<resources>
+    <string name="app_name">OSU</string>
+    <string name="no_osu">No OSU available</string>
+</resources>
diff --git a/packages/Osu/src/com/android/MainActivity.java b/packages/Osu/src/com/android/MainActivity.java
new file mode 100644
index 0000000..7e7d49a
--- /dev/null
+++ b/packages/Osu/src/com/android/MainActivity.java
@@ -0,0 +1,419 @@
+package com.android;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.IntentService;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.TaskStackBuilder;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.anqp.OSUProvider;
+import com.android.hotspot2.AppBridge;
+import com.android.hotspot2.PasspointMatch;
+import com.android.hotspot2.osu.OSUInfo;
+import com.android.hotspot2.osu.OSUManager;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+
+//import com.android.Osu.R;
+
+/**
+ * Main activity.
+ */
+public class MainActivity extends Activity {
+    private static final int NOTIFICATION_ID = 0; // Used for OSU count
+    private static final int NOTIFICATION_MESSAGE_ID = 1; // Used for other messages
+    private static final Locale LOCALE = java.util.Locale.getDefault();
+
+    private static volatile OSUService sOsuService;
+
+    private ListView osuListView;
+    private OsuListAdapter2 osuListAdapter;
+    private String message;
+
+    public MainActivity() {
+
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (message != null) {
+            showDialog(message);
+            message = null;
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent intent = getIntent();
+        Bundle bundle = intent.getExtras();
+
+        if (bundle == null) {   // User interaction
+            if (sOsuService == null) {
+                Intent serviceIntent = new Intent(this, OSUService.class);
+                serviceIntent.putExtra(ACTION_KEY, "dummy-key");
+                startService(serviceIntent);
+                return;
+            }
+
+            List<OSUInfo> osuInfos = sOsuService.getOsuInfos();
+
+            setContentView(R.layout.activity_main);
+            Log.d("osu", "osu count:" + osuInfos.size());
+            View noOsuView = findViewById(R.id.no_osu);
+            if (osuInfos.size() > 0) {
+                noOsuView.setVisibility(View.GONE);
+                osuListAdapter = new OsuListAdapter2(this, osuInfos);
+                osuListView = (ListView) findViewById(R.id.profile_list);
+                osuListView.setAdapter(osuListAdapter);
+                osuListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+                    @Override
+                    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
+                        OSUInfo osuData = (OSUInfo) adapterView.getAdapter().getItem(position);
+                        Log.d("osu", "launch osu:" + osuData.getName(LOCALE)
+                                + " id:" + osuData.getOsuID());
+                        sOsuService.selectOsu(osuData.getOsuID());
+                        finish();
+                    }
+                });
+            } else {
+                noOsuView.setVisibility(View.VISIBLE);
+            }
+        } else if (intent.getAction().equals(AppBridge.ACTION_OSU_NOTIFICATION)) {
+            if (bundle.containsKey(AppBridge.OSU_COUNT)) {
+                showOsuCount(bundle.getInt("osu-count", 0), Collections.<OSUInfo>emptyList());
+            } else if (bundle.containsKey(AppBridge.PROV_SUCCESS)) {
+                showStatus(bundle.getBoolean(AppBridge.PROV_SUCCESS),
+                        bundle.getString(AppBridge.SP_NAME),
+                        bundle.getString(AppBridge.PROV_MESSAGE),
+                        null);
+            } else if (bundle.containsKey(AppBridge.DEAUTH)) {
+                showDeauth(bundle.getString(AppBridge.SP_NAME),
+                        bundle.getBoolean(AppBridge.DEAUTH),
+                        bundle.getInt(AppBridge.DEAUTH_DELAY),
+                        bundle.getString(AppBridge.DEAUTH_URL));
+            }
+            /*
+            else if (bundle.containsKey(AppBridge.OSU_INFO)) {
+                List<OsuData> osus = printOsuDataList(bundle.getParcelableArray(AppBridge.OSU_INFO));
+                showOsuList(osus);
+            }
+            */
+        }
+    }
+
+    private void showOsuCount(int osuCount, List<OSUInfo> osus) {
+        if (osuCount > 0) {
+            printOsuDataList(osus);
+            sendNotification(osuCount);
+        } else {
+            cancelNotification();
+        }
+        finish();
+    }
+
+    private void showStatus(boolean provSuccess, String spName, String provMessage,
+                            String remoteStatus) {
+        if (provSuccess) {
+            sendDialogMessage(
+                    String.format("Credentials for %s was successfully installed", spName));
+        } else {
+            if (spName != null) {
+                if (remoteStatus != null) {
+                    sendDialogMessage(
+                            String.format("Failed to install credentials for %s: %s: %s",
+                                    spName, provMessage, remoteStatus));
+                } else {
+                    sendDialogMessage(
+                            String.format("Failed to install credentials for %s: %s",
+                                    spName, provMessage));
+                }
+            } else {
+                sendDialogMessage(
+                        String.format("Failed to contact OSU: %s", provMessage));
+            }
+        }
+    }
+
+    private void showDeauth(String spName, boolean ess, int delay, String url) {
+        String delayReadable = getReadableTimeInSeconds(delay);
+        if (ess) {
+            if (delay > 60) {
+                sendDialogMessage(
+                        String.format("There is an issue connecting to %s [for the next %s]. " +
+                                "Please visit %s for details", spName, delayReadable, url));
+            } else {
+                sendDialogMessage(
+                        String.format("There is an issue connecting to %s. " +
+                                "Please visit %s for details", spName, url));
+            }
+        } else {
+            sendDialogMessage(
+                    String.format("There is an issue with the closest Access Point for %s. " +
+                                    "You may wait %s or move to another Access Point to " +
+                                    "regain access. Please visit %s for details.",
+                            spName, delayReadable, url));
+        }
+    }
+
+    private static final String ACTION_KEY = "action";
+
+    public static class WifiReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context c, Intent intent) {
+            Log.d(OSUManager.TAG, "OSU App got intent: " + intent.getAction());
+            Intent serviceIntent;
+            serviceIntent = new Intent(c, OSUService.class);
+            serviceIntent.putExtra(ACTION_KEY, intent.getAction());
+            serviceIntent.putExtras(intent);
+            c.startService(serviceIntent);
+        }
+    }
+
+    public static class OSUService extends IntentService {
+        private OSUManager mOsuManager;
+        private final IBinder mBinder = new Binder();
+
+        public OSUService() {
+            super("OSUService");
+        }
+
+        @Override
+        public int onStartCommand(Intent intent, int flags, int startId) {
+            onHandleIntent(intent);
+            return START_STICKY;
+        }
+
+        @Override
+        public void onCreate() {
+            super.onCreate();
+            Log.d("YYY", String.format("Service %x running, OSU %x",
+                    System.identityHashCode(this), System.identityHashCode(mOsuManager)));
+            if (mOsuManager == null) {
+                mOsuManager = new OSUManager(this);
+            }
+            sOsuService = this;
+        }
+
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+            Log.d("YYY", String.format("Service %x killed", System.identityHashCode(this)));
+        }
+
+        @Override
+        public IBinder onBind(Intent intent) {
+            return mBinder;
+        }
+
+        @Override
+        protected void onHandleIntent(Intent intent) {
+            Bundle bundle = intent.getExtras();
+            WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+            Log.d(OSUManager.TAG, "OSU Service got intent: " + intent.getStringExtra(ACTION_KEY));
+            switch (intent.getStringExtra(ACTION_KEY)) {
+                case WifiManager.SCAN_RESULTS_AVAILABLE_ACTION:
+                    mOsuManager.pushScanResults(wifiManager.getScanResults());
+                    break;
+                case WifiManager.PASSPOINT_WNM_FRAME_RECEIVED_ACTION:
+                    long bssid = bundle.getLong(WifiManager.EXTRA_PASSPOINT_WNM_BSSID);
+                    String url = bundle.getString(WifiManager.EXTRA_PASSPOINT_WNM_URL);
+
+                    try {
+                        if (bundle.containsKey(WifiManager.EXTRA_PASSPOINT_WNM_METHOD)) {
+                            int method = bundle.getInt(WifiManager.EXTRA_PASSPOINT_WNM_METHOD);
+                            if (method != OSUProvider.OSUMethod.SoapXml.ordinal()) {
+                                Log.w(OSUManager.TAG, "Unsupported remediation method: " + method);
+                            }
+                            PasspointMatch match = null;
+                            if (bundle.containsKey(WifiManager.EXTRA_PASSPOINT_WNM_PPOINT_MATCH)) {
+                                int ordinal =
+                                        bundle.getInt(WifiManager.EXTRA_PASSPOINT_WNM_PPOINT_MATCH);
+                                if (ordinal >= 0 && ordinal < PasspointMatch.values().length) {
+                                    match = PasspointMatch.values()[ordinal];
+                                }
+                            }
+                            mOsuManager.wnmRemediate(bssid, url, match);
+                        } else if (bundle.containsKey(WifiManager.EXTRA_PASSPOINT_WNM_ESS)) {
+                            boolean ess = bundle.getBoolean(WifiManager.EXTRA_PASSPOINT_WNM_ESS);
+                            int delay = bundle.getInt(WifiManager.EXTRA_PASSPOINT_WNM_DELAY);
+                            mOsuManager.deauth(bssid, ess, delay, url);
+                        } else {
+                            Log.w(OSUManager.TAG, "Unknown WNM event");
+                        }
+                    } catch (IOException | SAXException e) {
+                        Log.w(OSUManager.TAG, "Remediation event failed to parse: " + e);
+                    }
+                    break;
+                case WifiManager.PASSPOINT_ICON_RECEIVED_ACTION:
+                    mOsuManager.notifyIconReceived(
+                            bundle.getLong(WifiManager.EXTRA_PASSPOINT_ICON_BSSID),
+                            bundle.getString(WifiManager.EXTRA_PASSPOINT_ICON_FILE),
+                            bundle.getByteArray(WifiManager.EXTRA_PASSPOINT_ICON_DATA));
+                    break;
+                case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
+                    mOsuManager.networkConfigChange((WifiConfiguration)
+                            intent.getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION));
+                    break;
+                case WifiManager.WIFI_STATE_CHANGED_ACTION:
+                    int state = bundle.getInt(WifiManager.EXTRA_WIFI_STATE);
+                    if (state == WifiManager.WIFI_STATE_DISABLED) {
+                        mOsuManager.wifiStateChange(false);
+                    } else if (state == WifiManager.WIFI_STATE_ENABLED) {
+                        mOsuManager.wifiStateChange(true);
+                    }
+                    break;
+                case WifiManager.NETWORK_STATE_CHANGED_ACTION:
+                    mOsuManager.networkConnectEvent((WifiInfo)
+                            intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO));
+                    break;
+            }
+        }
+
+        public List<OSUInfo> getOsuInfos() {
+            return mOsuManager.getAvailableOSUs();
+        }
+
+        public void selectOsu(int id) {
+            mOsuManager.setOSUSelection(id);
+        }
+    }
+
+    private String getReadableTimeInSeconds(int timeSeconds) {
+        long hours = TimeUnit.SECONDS.toHours(timeSeconds);
+        long minutes = TimeUnit.SECONDS.toMinutes(timeSeconds) - TimeUnit.HOURS.toMinutes(hours);
+        long seconds =
+                timeSeconds - TimeUnit.HOURS.toSeconds(hours) - TimeUnit.MINUTES.toSeconds(minutes);
+        if (hours > 0) {
+            return String.format("%02d:%02d:%02d", hours, minutes, seconds);
+        } else {
+            return String.format("%ds", seconds);
+        }
+    }
+
+    private void sendNotification(int count) {
+        Notification.Builder builder =
+                new Notification.Builder(this)
+                        .setContentTitle(String.format("%s OSU available", count))
+                        .setContentText("Choose one to connect")
+                        .setSmallIcon(android.R.drawable.ic_dialog_info)
+                        .setAutoCancel(false);
+        Intent resultIntent = new Intent(this, MainActivity.class);
+
+        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+        stackBuilder.addParentStack(MainActivity.class);
+        stackBuilder.addNextIntent(resultIntent);
+        PendingIntent resultPendingIntent =
+                stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
+        builder.setContentIntent(resultPendingIntent);
+        NotificationManager notificationManager =
+                (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+        notificationManager.notify(NOTIFICATION_ID, builder.build());
+    }
+
+    private void cancelNotification() {
+        NotificationManager notificationManager =
+                (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+        notificationManager.cancel(NOTIFICATION_ID);
+    }
+
+    private void sendDialogMessage(String message) {
+//        sendNotificationMessage(message);
+        this.message = message;
+    }
+
+    private void showDialog(String message) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        builder.setMessage(message)
+                .setTitle("OSU");
+        builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
+            @Override
+            public void onCancel(DialogInterface dialogInterface) {
+                dialogInterface.cancel();
+                finish();
+            }
+        });
+        AlertDialog dialog = builder.create();
+        dialog.show();
+    }
+
+    private void sendNotificationMessage(String title) {
+        Notification.Builder builder =
+                new Notification.Builder(this)
+                        .setContentTitle(title)
+                        .setContentText("Click to dismiss.")
+                        .setSmallIcon(android.R.drawable.ic_dialog_info)
+                        .setAutoCancel(true);
+        NotificationManager notificationManager =
+                (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+        notificationManager.notify(NOTIFICATION_MESSAGE_ID, builder.build());
+    }
+
+    private static class OsuListAdapter2 extends ArrayAdapter<OSUInfo> {
+        private Activity activity;
+
+        public OsuListAdapter2(Activity activity, List<OSUInfo> osuDataList) {
+            super(activity, R.layout.list_item, osuDataList);
+            this.activity = activity;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            View view = convertView;
+            if (view == null) {
+                view = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
+            }
+            OSUInfo osuData = getItem(position);
+            TextView osuName = (TextView) view.findViewById(R.id.profile_name);
+            osuName.setText(osuData.getName(LOCALE));
+            TextView osuDetail = (TextView) view.findViewById(R.id.profile_detail);
+            osuDetail.setText(osuData.getServiceDescription(LOCALE));
+            ImageView osuIcon = (ImageView) view.findViewById(R.id.profile_logo);
+            byte[] iconData = osuData.getIconFileElement().getIconData();
+            osuIcon.setImageDrawable(
+                    new BitmapDrawable(activity.getResources(),
+                            BitmapFactory.decodeByteArray(iconData, 0, iconData.length)));
+            return view;
+        }
+    }
+
+    private void printOsuDataList(List<OSUInfo> osuDataList) {
+        for (OSUInfo osuData : osuDataList) {
+            Log.d("osu", String.format("OSUData:[%s][%s][%d]",
+                    osuData.getName(LOCALE), osuData.getServiceDescription(LOCALE),
+                    osuData.getOsuID()));
+        }
+    }
+
+}
diff --git a/packages/Osu/src/com/android/anqp/ANQPElement.java b/packages/Osu/src/com/android/anqp/ANQPElement.java
new file mode 100644
index 0000000..58aee29
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/ANQPElement.java
@@ -0,0 +1,16 @@
+package com.android.anqp;
+
+/**
+ * Base class for an IEEE802.11u ANQP element.
+ */
+public abstract class ANQPElement {
+    private final Constants.ANQPElementType mID;
+
+    protected ANQPElement(Constants.ANQPElementType id) {
+        mID = id;
+    }
+
+    public Constants.ANQPElementType getID() {
+        return mID;
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/Constants.java b/packages/Osu/src/com/android/anqp/Constants.java
new file mode 100644
index 0000000..214bb93
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/Constants.java
@@ -0,0 +1,233 @@
+package com.android.anqp;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+import java.util.Collection;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ANQP related constants (802.11-2012)
+ */
+public class Constants {
+
+    public static final int NIBBLE_MASK = 0x0f;
+    public static final int BYTE_MASK = 0xff;
+    public static final int SHORT_MASK = 0xffff;
+    public static final long INT_MASK = 0xffffffffL;
+    public static final int BYTES_IN_SHORT = 2;
+    public static final int BYTES_IN_INT = 4;
+    public static final int BYTES_IN_EUI48 = 6;
+    public static final long MILLIS_IN_A_SEC = 1000L;
+
+    public static final int HS20_PREFIX = 0x119a6f50;   // Note that this is represented as a LE int
+    public static final int HS20_FRAME_PREFIX = 0x109a6f50;
+    public static final int UTF8_INDICATOR = 1;
+
+    public static final int LANG_CODE_LENGTH = 3;
+
+    public static final int ANQP_QUERY_LIST = 256;
+    public static final int ANQP_CAPABILITY_LIST = 257;
+    public static final int ANQP_VENUE_NAME = 258;
+    public static final int ANQP_EMERGENCY_NUMBER = 259;
+    public static final int ANQP_NWK_AUTH_TYPE = 260;
+    public static final int ANQP_ROAMING_CONSORTIUM = 261;
+    public static final int ANQP_IP_ADDR_AVAILABILITY = 262;
+    public static final int ANQP_NAI_REALM = 263;
+    public static final int ANQP_3GPP_NETWORK = 264;
+    public static final int ANQP_GEO_LOC = 265;
+    public static final int ANQP_CIVIC_LOC = 266;
+    public static final int ANQP_LOC_URI = 267;
+    public static final int ANQP_DOM_NAME = 268;
+    public static final int ANQP_EMERGENCY_ALERT = 269;
+    public static final int ANQP_TDLS_CAP = 270;
+    public static final int ANQP_EMERGENCY_NAI = 271;
+    public static final int ANQP_NEIGHBOR_REPORT = 272;
+    public static final int ANQP_VENDOR_SPEC = 56797;
+
+    public static final int HS_QUERY_LIST = 1;
+    public static final int HS_CAPABILITY_LIST = 2;
+    public static final int HS_FRIENDLY_NAME = 3;
+    public static final int HS_WAN_METRICS = 4;
+    public static final int HS_CONN_CAPABILITY = 5;
+    public static final int HS_NAI_HOME_REALM_QUERY = 6;
+    public static final int HS_OPERATING_CLASS = 7;
+    public static final int HS_OSU_PROVIDERS = 8;
+    public static final int HS_ICON_REQUEST = 10;
+    public static final int HS_ICON_FILE = 11;
+
+    public enum ANQPElementType {
+        ANQPQueryList,
+        ANQPCapabilityList,
+        ANQPVenueName,
+        ANQPEmergencyNumber,
+        ANQPNwkAuthType,
+        ANQPRoamingConsortium,
+        ANQPIPAddrAvailability,
+        ANQPNAIRealm,
+        ANQP3GPPNetwork,
+        ANQPGeoLoc,
+        ANQPCivicLoc,
+        ANQPLocURI,
+        ANQPDomName,
+        ANQPEmergencyAlert,
+        ANQPTDLSCap,
+        ANQPEmergencyNAI,
+        ANQPNeighborReport,
+        ANQPVendorSpec,
+        HSQueryList,
+        HSCapabilityList,
+        HSFriendlyName,
+        HSWANMetrics,
+        HSConnCapability,
+        HSNAIHomeRealmQuery,
+        HSOperatingclass,
+        HSOSUProviders,
+        HSIconRequest,
+        HSIconFile
+    }
+
+    private static final Map<Integer, ANQPElementType> sAnqpMap = new HashMap<>();
+    private static final Map<Integer, ANQPElementType> sHs20Map = new HashMap<>();
+    private static final Map<ANQPElementType, Integer> sRevAnqpmap =
+            new EnumMap<>(ANQPElementType.class);
+    private static final Map<ANQPElementType, Integer> sRevHs20map =
+            new EnumMap<>(ANQPElementType.class);
+
+    static {
+        sAnqpMap.put(ANQP_QUERY_LIST, ANQPElementType.ANQPQueryList);
+        sAnqpMap.put(ANQP_CAPABILITY_LIST, ANQPElementType.ANQPCapabilityList);
+        sAnqpMap.put(ANQP_VENUE_NAME, ANQPElementType.ANQPVenueName);
+        sAnqpMap.put(ANQP_EMERGENCY_NUMBER, ANQPElementType.ANQPEmergencyNumber);
+        sAnqpMap.put(ANQP_NWK_AUTH_TYPE, ANQPElementType.ANQPNwkAuthType);
+        sAnqpMap.put(ANQP_ROAMING_CONSORTIUM, ANQPElementType.ANQPRoamingConsortium);
+        sAnqpMap.put(ANQP_IP_ADDR_AVAILABILITY, ANQPElementType.ANQPIPAddrAvailability);
+        sAnqpMap.put(ANQP_NAI_REALM, ANQPElementType.ANQPNAIRealm);
+        sAnqpMap.put(ANQP_3GPP_NETWORK, ANQPElementType.ANQP3GPPNetwork);
+        sAnqpMap.put(ANQP_GEO_LOC, ANQPElementType.ANQPGeoLoc);
+        sAnqpMap.put(ANQP_CIVIC_LOC, ANQPElementType.ANQPCivicLoc);
+        sAnqpMap.put(ANQP_LOC_URI, ANQPElementType.ANQPLocURI);
+        sAnqpMap.put(ANQP_DOM_NAME, ANQPElementType.ANQPDomName);
+        sAnqpMap.put(ANQP_EMERGENCY_ALERT, ANQPElementType.ANQPEmergencyAlert);
+        sAnqpMap.put(ANQP_TDLS_CAP, ANQPElementType.ANQPTDLSCap);
+        sAnqpMap.put(ANQP_EMERGENCY_NAI, ANQPElementType.ANQPEmergencyNAI);
+        sAnqpMap.put(ANQP_NEIGHBOR_REPORT, ANQPElementType.ANQPNeighborReport);
+        sAnqpMap.put(ANQP_VENDOR_SPEC, ANQPElementType.ANQPVendorSpec);
+
+        sHs20Map.put(HS_QUERY_LIST, ANQPElementType.HSQueryList);
+        sHs20Map.put(HS_CAPABILITY_LIST, ANQPElementType.HSCapabilityList);
+        sHs20Map.put(HS_FRIENDLY_NAME, ANQPElementType.HSFriendlyName);
+        sHs20Map.put(HS_WAN_METRICS, ANQPElementType.HSWANMetrics);
+        sHs20Map.put(HS_CONN_CAPABILITY, ANQPElementType.HSConnCapability);
+        sHs20Map.put(HS_NAI_HOME_REALM_QUERY, ANQPElementType.HSNAIHomeRealmQuery);
+        sHs20Map.put(HS_OPERATING_CLASS, ANQPElementType.HSOperatingclass);
+        sHs20Map.put(HS_OSU_PROVIDERS, ANQPElementType.HSOSUProviders);
+        sHs20Map.put(HS_ICON_REQUEST, ANQPElementType.HSIconRequest);
+        sHs20Map.put(HS_ICON_FILE, ANQPElementType.HSIconFile);
+
+        for (Map.Entry<Integer, ANQPElementType> entry : sAnqpMap.entrySet()) {
+            sRevAnqpmap.put(entry.getValue(), entry.getKey());
+        }
+        for (Map.Entry<Integer, ANQPElementType> entry : sHs20Map.entrySet()) {
+            sRevHs20map.put(entry.getValue(), entry.getKey());
+        }
+    }
+
+    public static ANQPElementType mapANQPElement(int id) {
+        return sAnqpMap.get(id);
+    }
+
+    public static ANQPElementType mapHS20Element(int id) {
+        return sHs20Map.get(id);
+    }
+
+    public static Integer getANQPElementID(ANQPElementType elementType) {
+        return sRevAnqpmap.get(elementType);
+    }
+
+    public static Integer getHS20ElementID(ANQPElementType elementType) {
+        return sRevHs20map.get(elementType);
+    }
+
+    public static boolean hasBaseANQPElements(Collection<ANQPElementType> elements) {
+        if (elements == null) {
+            return false;
+        }
+        for (ANQPElementType element : elements) {
+            if (sRevAnqpmap.containsKey(element)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean hasR2Elements(List<ANQPElementType> elements) {
+        return elements.contains(ANQPElementType.HSOSUProviders);
+    }
+
+    public static long getInteger(ByteBuffer payload, ByteOrder bo, int size) {
+        byte[] octets = new byte[size];
+        payload.get(octets);
+        long value = 0;
+        if (bo == ByteOrder.LITTLE_ENDIAN) {
+            for (int n = octets.length - 1; n >= 0; n--) {
+                value = (value << Byte.SIZE) | (octets[n] & BYTE_MASK);
+            }
+        }
+        else {
+            for (byte octet : octets) {
+                value = (value << Byte.SIZE) | (octet & BYTE_MASK);
+            }
+        }
+        return value;
+    }
+
+    public static String getPrefixedString(ByteBuffer payload, int lengthLength, Charset charset)
+            throws ProtocolException {
+        return getPrefixedString(payload, lengthLength, charset, false);
+    }
+
+    public static String getPrefixedString(ByteBuffer payload, int lengthLength, Charset charset,
+                                           boolean useNull) throws ProtocolException {
+        if (payload.remaining() < lengthLength) {
+            throw new ProtocolException("Runt string: " + payload.remaining());
+        }
+        return getString(payload, (int) getInteger(payload, ByteOrder.LITTLE_ENDIAN,
+                lengthLength), charset, useNull);
+    }
+
+    public static String getTrimmedString(ByteBuffer payload, int length, Charset charset)
+            throws ProtocolException {
+        String s = getString(payload, length, charset, false);
+        int zero = length - 1;
+        while (zero >= 0) {
+            if (s.charAt(zero) != 0) {
+                break;
+            }
+            zero--;
+        }
+        return zero < length - 1 ? s.substring(0, zero + 1) : s;
+    }
+
+    public static String getString(ByteBuffer payload, int length, Charset charset)
+            throws ProtocolException {
+        return getString(payload, length, charset, false);
+    }
+
+    public static String getString(ByteBuffer payload, int length, Charset charset, boolean useNull)
+            throws ProtocolException {
+        if (length > payload.remaining()) {
+            throw new ProtocolException("Bad string length: " + length);
+        }
+        if (useNull && length == 0) {
+            return null;
+        }
+        byte[] octets = new byte[length];
+        payload.get(octets);
+        return new String(octets, charset);
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/HSIconFileElement.java b/packages/Osu/src/com/android/anqp/HSIconFileElement.java
new file mode 100644
index 0000000..bd14e3f
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/HSIconFileElement.java
@@ -0,0 +1,59 @@
+package com.android.anqp;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+
+import static com.android.anqp.Constants.BYTE_MASK;
+import static com.android.anqp.Constants.SHORT_MASK;
+
+/**
+ * The Icon Binary File vendor specific ANQP Element,
+ * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
+ * section 4.11
+ */
+public class HSIconFileElement extends ANQPElement {
+
+    public enum StatusCode {Success, FileNotFound, Unspecified}
+
+    private final StatusCode mStatusCode;
+    private final String mType;
+    private final byte[] mIconData;
+
+    public HSIconFileElement(Constants.ANQPElementType infoID, ByteBuffer payload)
+            throws ProtocolException {
+        super(infoID);
+
+        if (payload.remaining() < 4) {
+            throw new ProtocolException("Truncated icon file: " + payload.remaining());
+        }
+
+        int statusID = payload.get() & BYTE_MASK;
+        mStatusCode = statusID < StatusCode.values().length ? StatusCode.values()[statusID] : null;
+        mType = Constants.getPrefixedString(payload, 1, StandardCharsets.US_ASCII);
+
+        int dataLength = payload.getShort() & SHORT_MASK;
+        mIconData = new byte[dataLength];
+        payload.get(mIconData);
+    }
+
+    public StatusCode getStatusCode() {
+        return mStatusCode;
+    }
+
+    public String getType() {
+        return mType;
+    }
+
+    public byte[] getIconData() {
+        return mIconData;
+    }
+
+    @Override
+    public String toString() {
+        return "HSIconFile{" +
+                "statusCode=" + mStatusCode +
+                ", type='" + mType + '\'' +
+                ", iconData=" + mIconData.length + " bytes }";
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/HSOsuProvidersElement.java b/packages/Osu/src/com/android/anqp/HSOsuProvidersElement.java
new file mode 100644
index 0000000..646e003
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/HSOsuProvidersElement.java
@@ -0,0 +1,49 @@
+package com.android.anqp;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * The OSU Providers List vendor specific ANQP Element,
+ * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
+ * section 4.8
+ */
+public class HSOsuProvidersElement extends ANQPElement {
+    private final String mSSID;
+    private final List<OSUProvider> mProviders;
+
+    public HSOsuProvidersElement(Constants.ANQPElementType infoID, ByteBuffer payload)
+            throws ProtocolException {
+        super(infoID);
+
+        mSSID = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8);
+        int providerCount = payload.get() & Constants.BYTE_MASK;
+
+        mProviders = new ArrayList<>(providerCount);
+
+        while (providerCount > 0) {
+            mProviders.add(new OSUProvider(mSSID, payload));
+            providerCount--;
+        }
+    }
+
+    public String getSSID() {
+        return mSSID;
+    }
+
+    public List<OSUProvider> getProviders() {
+        return Collections.unmodifiableList(mProviders);
+    }
+
+    @Override
+    public String toString() {
+        return "HSOsuProviders{" +
+                "SSID='" + mSSID + '\'' +
+                ", providers=" + mProviders +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/I18Name.java b/packages/Osu/src/com/android/anqp/I18Name.java
new file mode 100644
index 0000000..0a16db7
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/I18Name.java
@@ -0,0 +1,80 @@
+package com.android.anqp;
+
+import java.io.IOException;
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Locale;
+
+import static com.android.anqp.Constants.BYTE_MASK;
+
+/**
+ * A generic Internationalized name used in ANQP elements as specified in 802.11-2012 and
+ * "Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00"
+ */
+public class I18Name {
+    private final String mLanguage;
+    private final Locale mLocale;
+    private final String mText;
+
+    public I18Name(ByteBuffer payload) throws ProtocolException {
+        if (payload.remaining() < Constants.LANG_CODE_LENGTH + 1) {
+            throw new ProtocolException("Truncated I18Name: " + payload.remaining());
+        }
+        int nameLength = payload.get() & BYTE_MASK;
+        if (nameLength < Constants.LANG_CODE_LENGTH) {
+            throw new ProtocolException("Runt I18Name: " + nameLength);
+        }
+        mLanguage = Constants.getTrimmedString(payload,
+                Constants.LANG_CODE_LENGTH, StandardCharsets.US_ASCII);
+        mLocale = Locale.forLanguageTag(mLanguage);
+        mText = Constants.getString(payload, nameLength -
+                Constants.LANG_CODE_LENGTH, StandardCharsets.UTF_8);
+    }
+
+    public I18Name(String compoundString) throws IOException {
+        if (compoundString.length() < Constants.LANG_CODE_LENGTH) {
+            throw new IOException("I18String too short: '" + compoundString + "'");
+        }
+        mLanguage = compoundString.substring(0, Constants.LANG_CODE_LENGTH);
+        mText = compoundString.substring(Constants.LANG_CODE_LENGTH);
+        mLocale = Locale.forLanguageTag(mLanguage);
+    }
+
+    public String getLanguage() {
+        return mLanguage;
+    }
+
+    public Locale getLocale() {
+        return mLocale;
+    }
+
+    public String getText() {
+        return mText;
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (this == thatObject) {
+            return true;
+        }
+        if (thatObject == null || getClass() != thatObject.getClass()) {
+            return false;
+        }
+
+        I18Name that = (I18Name) thatObject;
+        return mLanguage.equals(that.mLanguage) && mText.equals(that.mText);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mLanguage.hashCode();
+        result = 31 * result + mText.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return mText + ':' + mLocale.getLanguage();
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/IconInfo.java b/packages/Osu/src/com/android/anqp/IconInfo.java
new file mode 100644
index 0000000..9e9f1ee
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/IconInfo.java
@@ -0,0 +1,91 @@
+package com.android.anqp;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+
+import static com.android.anqp.Constants.SHORT_MASK;
+
+/**
+ * The Icons available OSU Providers sub field, as specified in
+ * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
+ * section 4.8.1.4
+ */
+public class IconInfo {
+    private final int mWidth;
+    private final int mHeight;
+    private final String mLanguage;
+    private final String mIconType;
+    private final String mFileName;
+
+    public IconInfo(ByteBuffer payload) throws ProtocolException {
+        if (payload.remaining() < 9) {
+            throw new ProtocolException("Truncated icon meta data");
+        }
+
+        mWidth = payload.getShort() & SHORT_MASK;
+        mHeight = payload.getShort() & SHORT_MASK;
+        mLanguage = Constants.getTrimmedString(payload,
+                Constants.LANG_CODE_LENGTH, StandardCharsets.US_ASCII);
+        mIconType = Constants.getPrefixedString(payload, 1, StandardCharsets.US_ASCII);
+        mFileName = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8);
+    }
+
+    public int getWidth() {
+        return mWidth;
+    }
+
+    public int getHeight() {
+        return mHeight;
+    }
+
+    public String getLanguage() {
+        return mLanguage;
+    }
+
+    public String getIconType() {
+        return mIconType;
+    }
+
+    public String getFileName() {
+        return mFileName;
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (this == thatObject) {
+            return true;
+        }
+        if (thatObject == null || getClass() != thatObject.getClass()) {
+            return false;
+        }
+
+        IconInfo that = (IconInfo) thatObject;
+        return mHeight == that.mHeight &&
+                mWidth == that.mWidth &&
+                mFileName.equals(that.mFileName) &&
+                mIconType.equals(that.mIconType) &&
+                mLanguage.equals(that.mLanguage);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mWidth;
+        result = 31 * result + mHeight;
+        result = 31 * result + mLanguage.hashCode();
+        result = 31 * result + mIconType.hashCode();
+        result = 31 * result + mFileName.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "IconInfo{" +
+                "Width=" + mWidth +
+                ", Height=" + mHeight +
+                ", Language=" + mLanguage +
+                ", IconType='" + mIconType + '\'' +
+                ", FileName='" + mFileName + '\'' +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/OSUProvider.java b/packages/Osu/src/com/android/anqp/OSUProvider.java
new file mode 100644
index 0000000..e2669d4
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/OSUProvider.java
@@ -0,0 +1,158 @@
+package com.android.anqp;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.anqp.Constants.BYTE_MASK;
+import static com.android.anqp.Constants.SHORT_MASK;
+
+/**
+ * An OSU Provider, as specified in
+ * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
+ * section 4.8.1
+ */
+public class OSUProvider {
+
+    public enum OSUMethod {OmaDm, SoapXml}
+
+    private final String mSSID;
+    private final List<I18Name> mNames;
+    private final String mOSUServer;
+    private final List<OSUMethod> mOSUMethods;
+    private final List<IconInfo> mIcons;
+    private final String mOsuNai;
+    private final List<I18Name> mServiceDescriptions;
+    private final int mHashCode;
+
+    public OSUProvider(String ssid, ByteBuffer payload) throws ProtocolException {
+        if (payload.remaining() < 11) {
+            throw new ProtocolException("Truncated OSU provider: " + payload.remaining());
+        }
+
+        mSSID = ssid;
+
+        int length = payload.getShort() & SHORT_MASK;
+        int namesLength = payload.getShort() & SHORT_MASK;
+
+        ByteBuffer namesBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
+        namesBuffer.limit(namesBuffer.position() + namesLength);
+        payload.position(payload.position() + namesLength);
+
+        mNames = new ArrayList<>();
+
+        while (namesBuffer.hasRemaining()) {
+            mNames.add(new I18Name(namesBuffer));
+        }
+
+        mOSUServer = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8);
+        int methodLength = payload.get() & BYTE_MASK;
+        mOSUMethods = new ArrayList<>(methodLength);
+        while (methodLength > 0) {
+            int methodID = payload.get() & BYTE_MASK;
+            mOSUMethods.add(methodID < OSUMethod.values().length ?
+                    OSUMethod.values()[methodID] :
+                    null);
+            methodLength--;
+        }
+
+        int iconsLength = payload.getShort() & SHORT_MASK;
+        ByteBuffer iconsBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
+        iconsBuffer.limit(iconsBuffer.position() + iconsLength);
+        payload.position(payload.position() + iconsLength);
+
+        mIcons = new ArrayList<>();
+
+        while (iconsBuffer.hasRemaining()) {
+            mIcons.add(new IconInfo(iconsBuffer));
+        }
+
+        mOsuNai = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8, true);
+
+        int descriptionsLength = payload.getShort() & SHORT_MASK;
+        ByteBuffer descriptionsBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
+        descriptionsBuffer.limit(descriptionsBuffer.position() + descriptionsLength);
+        payload.position(payload.position() + descriptionsLength);
+
+        mServiceDescriptions = new ArrayList<>();
+
+        while (descriptionsBuffer.hasRemaining()) {
+            mServiceDescriptions.add(new I18Name(descriptionsBuffer));
+        }
+
+        int result = mNames.hashCode();
+        result = 31 * result + mSSID.hashCode();
+        result = 31 * result + mOSUServer.hashCode();
+        result = 31 * result + mOSUMethods.hashCode();
+        result = 31 * result + mIcons.hashCode();
+        result = 31 * result + (mOsuNai != null ? mOsuNai.hashCode() : 0);
+        result = 31 * result + mServiceDescriptions.hashCode();
+        mHashCode = result;
+    }
+
+    public String getSSID() {
+        return mSSID;
+    }
+
+    public List<I18Name> getNames() {
+        return mNames;
+    }
+
+    public String getOSUServer() {
+        return mOSUServer;
+    }
+
+    public List<OSUMethod> getOSUMethods() {
+        return mOSUMethods;
+    }
+
+    public List<IconInfo> getIcons() {
+        return mIcons;
+    }
+
+    public String getOsuNai() {
+        return mOsuNai;
+    }
+
+    public List<I18Name> getServiceDescriptions() {
+        return mServiceDescriptions;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        OSUProvider that = (OSUProvider) o;
+
+        if (!mSSID.equals(that.mSSID)) return false;
+        if (!mOSUServer.equals(that.mOSUServer)) return false;
+        if (!mNames.equals(that.mNames)) return false;
+        if (!mServiceDescriptions.equals(that.mServiceDescriptions)) return false;
+        if (!mIcons.equals(that.mIcons)) return false;
+        if (!mOSUMethods.equals(that.mOSUMethods)) return false;
+        if (mOsuNai != null ? !mOsuNai.equals(that.mOsuNai) : that.mOsuNai != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return mHashCode;
+    }
+
+    @Override
+    public String toString() {
+        return "OSUProvider{" +
+                "names=" + mNames +
+                ", OSUServer='" + mOSUServer + '\'' +
+                ", OSUMethods=" + mOSUMethods +
+                ", icons=" + mIcons +
+                ", NAI='" + mOsuNai + '\'' +
+                ", serviceDescriptions=" + mServiceDescriptions +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/eap/AuthParam.java b/packages/Osu/src/com/android/anqp/eap/AuthParam.java
new file mode 100644
index 0000000..4243954
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/eap/AuthParam.java
@@ -0,0 +1,9 @@
+package com.android.anqp.eap;
+
+/**
+ * An Authentication parameter, part of the NAI Realm ANQP element, specified in
+ * IEEE802.11-2012 section 8.4.4.10, table 8-188
+ */
+public interface AuthParam {
+    public EAP.AuthInfoID getAuthInfoID();
+}
diff --git a/packages/Osu/src/com/android/anqp/eap/Credential.java b/packages/Osu/src/com/android/anqp/eap/Credential.java
new file mode 100644
index 0000000..0a89f4f
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/eap/Credential.java
@@ -0,0 +1,72 @@
+package com.android.anqp.eap;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+
+import static com.android.anqp.Constants.BYTE_MASK;
+
+/**
+ * An EAP authentication parameter, IEEE802.11-2012, table 8-188
+ */
+public class Credential implements AuthParam {
+
+    public enum CredType {
+        Reserved,
+        SIM,
+        USIM,
+        NFC,
+        HWToken,
+        Softoken,
+        Certificate,
+        Username,
+        None,
+        Anonymous,
+        VendorSpecific}
+
+    private final EAP.AuthInfoID mAuthInfoID;
+    private final CredType mCredType;
+
+    public Credential(EAP.AuthInfoID infoID, int length, ByteBuffer payload)
+            throws ProtocolException {
+        if (length != 1) {
+            throw new ProtocolException("Bad length: " + length);
+        }
+
+        mAuthInfoID = infoID;
+        int typeID = payload.get() & BYTE_MASK;
+
+        mCredType = typeID < CredType.values().length ?
+                CredType.values()[typeID] :
+                CredType.Reserved;
+    }
+
+    @Override
+    public EAP.AuthInfoID getAuthInfoID() {
+        return mAuthInfoID;
+    }
+
+    @Override
+    public int hashCode() {
+        return mAuthInfoID.hashCode() * 31 + mCredType.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (thatObject == this) {
+            return true;
+        } else if (thatObject == null || thatObject.getClass() != Credential.class) {
+            return false;
+        } else {
+            return ((Credential) thatObject).getCredType() == getCredType();
+        }
+    }
+
+    public CredType getCredType() {
+        return mCredType;
+    }
+
+    @Override
+    public String toString() {
+        return "Auth method " + mAuthInfoID + " = " + mCredType + "\n";
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/eap/EAP.java b/packages/Osu/src/com/android/anqp/eap/EAP.java
new file mode 100644
index 0000000..4b968b6
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/eap/EAP.java
@@ -0,0 +1,155 @@
+package com.android.anqp.eap;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * EAP Related constants for the ANQP NAIRealm element, IEEE802.11-2012 section 8.4.4.10
+ */
+public abstract class EAP {
+
+    private static final Map<Integer, EAPMethodID> sEapIds = new HashMap<>();
+    private static final Map<EAPMethodID, Integer> sRevEapIds = new HashMap<>();
+    private static final Map<Integer, AuthInfoID> sAuthIds = new HashMap<>();
+
+    public static final int EAP_MD5 = 4;
+    public static final int EAP_OTP = 5;
+    public static final int EAP_RSA = 9;
+    public static final int EAP_KEA = 11;
+    public static final int EAP_KEA_VALIDATE = 12;
+    public static final int EAP_TLS = 13;
+    public static final int EAP_LEAP = 17;
+    public static final int EAP_SIM = 18;
+    public static final int EAP_TTLS = 21;
+    public static final int EAP_AKA = 23;
+    public static final int EAP_3Com = 24;
+    public static final int EAP_MSCHAPv2 = 26;
+    public static final int EAP_PEAP = 29;
+    public static final int EAP_POTP = 32;
+    public static final int EAP_ActiontecWireless = 35;
+    public static final int EAP_HTTPDigest = 38;
+    public static final int EAP_SPEKE = 41;
+    public static final int EAP_MOBAC = 42;
+    public static final int EAP_FAST = 43;
+    public static final int EAP_ZLXEAP = 44;
+    public static final int EAP_Link = 45;
+    public static final int EAP_PAX = 46;
+    public static final int EAP_PSK = 47;
+    public static final int EAP_SAKE = 48;
+    public static final int EAP_IKEv2 = 49;
+    public static final int EAP_AKAPrim = 50;
+    public static final int EAP_GPSK = 51;
+    public static final int EAP_PWD = 52;
+    public static final int EAP_EKE = 53;
+    public static final int EAP_TEAP = 55;
+
+    public enum EAPMethodID {
+        EAP_MD5,
+        EAP_OTP,
+        EAP_RSA,
+        EAP_KEA,
+        EAP_KEA_VALIDATE,
+        EAP_TLS,
+        EAP_LEAP,
+        EAP_SIM,
+        EAP_TTLS,
+        EAP_AKA,
+        EAP_3Com,
+        EAP_MSCHAPv2,
+        EAP_PEAP,
+        EAP_POTP,
+        EAP_ActiontecWireless,
+        EAP_HTTPDigest,
+        EAP_SPEKE,
+        EAP_MOBAC,
+        EAP_FAST,
+        EAP_ZLXEAP,
+        EAP_Link,
+        EAP_PAX,
+        EAP_PSK,
+        EAP_SAKE,
+        EAP_IKEv2,
+        EAP_AKAPrim,
+        EAP_GPSK,
+        EAP_PWD,
+        EAP_EKE,
+        EAP_TEAP
+    }
+
+    public static final int ExpandedEAPMethod = 1;
+    public static final int NonEAPInnerAuthType = 2;
+    public static final int InnerAuthEAPMethodType = 3;
+    public static final int ExpandedInnerEAPMethod = 4;
+    public static final int CredentialType = 5;
+    public static final int TunneledEAPMethodCredType = 6;
+    public static final int VendorSpecific = 221;
+
+    public enum AuthInfoID {
+        Undefined,
+        ExpandedEAPMethod,
+        NonEAPInnerAuthType,
+        InnerAuthEAPMethodType,
+        ExpandedInnerEAPMethod,
+        CredentialType,
+        TunneledEAPMethodCredType,
+        VendorSpecific
+    }
+
+    static {
+        sEapIds.put(EAP_MD5, EAPMethodID.EAP_MD5);
+        sEapIds.put(EAP_OTP, EAPMethodID.EAP_OTP);
+        sEapIds.put(EAP_RSA, EAPMethodID.EAP_RSA);
+        sEapIds.put(EAP_KEA, EAPMethodID.EAP_KEA);
+        sEapIds.put(EAP_KEA_VALIDATE, EAPMethodID.EAP_KEA_VALIDATE);
+        sEapIds.put(EAP_TLS, EAPMethodID.EAP_TLS);
+        sEapIds.put(EAP_LEAP, EAPMethodID.EAP_LEAP);
+        sEapIds.put(EAP_SIM, EAPMethodID.EAP_SIM);
+        sEapIds.put(EAP_TTLS, EAPMethodID.EAP_TTLS);
+        sEapIds.put(EAP_AKA, EAPMethodID.EAP_AKA);
+        sEapIds.put(EAP_3Com, EAPMethodID.EAP_3Com);
+        sEapIds.put(EAP_MSCHAPv2, EAPMethodID.EAP_MSCHAPv2);
+        sEapIds.put(EAP_PEAP, EAPMethodID.EAP_PEAP);
+        sEapIds.put(EAP_POTP, EAPMethodID.EAP_POTP);
+        sEapIds.put(EAP_ActiontecWireless, EAPMethodID.EAP_ActiontecWireless);
+        sEapIds.put(EAP_HTTPDigest, EAPMethodID.EAP_HTTPDigest);
+        sEapIds.put(EAP_SPEKE, EAPMethodID.EAP_SPEKE);
+        sEapIds.put(EAP_MOBAC, EAPMethodID.EAP_MOBAC);
+        sEapIds.put(EAP_FAST, EAPMethodID.EAP_FAST);
+        sEapIds.put(EAP_ZLXEAP, EAPMethodID.EAP_ZLXEAP);
+        sEapIds.put(EAP_Link, EAPMethodID.EAP_Link);
+        sEapIds.put(EAP_PAX, EAPMethodID.EAP_PAX);
+        sEapIds.put(EAP_PSK, EAPMethodID.EAP_PSK);
+        sEapIds.put(EAP_SAKE, EAPMethodID.EAP_SAKE);
+        sEapIds.put(EAP_IKEv2, EAPMethodID.EAP_IKEv2);
+        sEapIds.put(EAP_AKAPrim, EAPMethodID.EAP_AKAPrim);
+        sEapIds.put(EAP_GPSK, EAPMethodID.EAP_GPSK);
+        sEapIds.put(EAP_PWD, EAPMethodID.EAP_PWD);
+        sEapIds.put(EAP_EKE, EAPMethodID.EAP_EKE);
+        sEapIds.put(EAP_TEAP, EAPMethodID.EAP_TEAP);
+
+        for (Map.Entry<Integer, EAPMethodID> entry : sEapIds.entrySet()) {
+            sRevEapIds.put(entry.getValue(), entry.getKey());
+        }
+
+        sAuthIds.put(ExpandedEAPMethod, AuthInfoID.ExpandedEAPMethod);
+        sAuthIds.put(NonEAPInnerAuthType, AuthInfoID.NonEAPInnerAuthType);
+        sAuthIds.put(InnerAuthEAPMethodType, AuthInfoID.InnerAuthEAPMethodType);
+        sAuthIds.put(ExpandedInnerEAPMethod, AuthInfoID.ExpandedInnerEAPMethod);
+        sAuthIds.put(CredentialType, AuthInfoID.CredentialType);
+        sAuthIds.put(TunneledEAPMethodCredType, AuthInfoID.TunneledEAPMethodCredType);
+        sAuthIds.put(VendorSpecific, AuthInfoID.VendorSpecific);
+    }
+
+    public static EAPMethodID mapEAPMethod(int methodID) {
+        return sEapIds.get(methodID);
+    }
+
+    public static Integer mapEAPMethod(EAPMethodID methodID) {
+        return sRevEapIds.get(methodID);
+    }
+
+    public static AuthInfoID mapAuthMethod(int methodID) {
+        return sAuthIds.get(methodID);
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/eap/EAPMethod.java b/packages/Osu/src/com/android/anqp/eap/EAPMethod.java
new file mode 100644
index 0000000..fa6c2f9
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/eap/EAPMethod.java
@@ -0,0 +1,191 @@
+package com.android.anqp.eap;
+
+import com.android.anqp.Constants;
+import com.android.hotspot2.AuthMatch;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An EAP Method, part of the NAI Realm ANQP element, specified in
+ * IEEE802.11-2012 section 8.4.4.10, figure 8-420
+ */
+public class EAPMethod {
+    private final EAP.EAPMethodID mEAPMethodID;
+    private final Map<EAP.AuthInfoID, Set<AuthParam>> mAuthParams;
+
+    public EAPMethod(ByteBuffer payload) throws ProtocolException {
+        if (payload.remaining() < 3) {
+            throw new ProtocolException("Runt EAP Method: " + payload.remaining());
+        }
+
+        int length = payload.get() & Constants.BYTE_MASK;
+        int methodID = payload.get() & Constants.BYTE_MASK;
+        int count = payload.get() & Constants.BYTE_MASK;
+
+        mEAPMethodID = EAP.mapEAPMethod(methodID);
+        mAuthParams = new EnumMap<>(EAP.AuthInfoID.class);
+
+        int realCount = 0;
+
+        ByteBuffer paramPayload = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
+        paramPayload.limit(paramPayload.position() + length - 2);
+        payload.position(payload.position() + length - 2);
+        while (paramPayload.hasRemaining()) {
+            int id = paramPayload.get() & Constants.BYTE_MASK;
+
+            EAP.AuthInfoID authInfoID = EAP.mapAuthMethod(id);
+            if (authInfoID == null) {
+                throw new ProtocolException("Unknown auth parameter ID: " + id);
+            }
+
+            int len = paramPayload.get() & Constants.BYTE_MASK;
+            if (len == 0 || len > paramPayload.remaining()) {
+                throw new ProtocolException("Bad auth method length: " + len);
+            }
+
+            switch (authInfoID) {
+                case ExpandedEAPMethod:
+                    addAuthParam(new ExpandedEAPMethod(authInfoID, len, paramPayload));
+                    break;
+                case NonEAPInnerAuthType:
+                    addAuthParam(new NonEAPInnerAuth(len, paramPayload));
+                    break;
+                case InnerAuthEAPMethodType:
+                    addAuthParam(new InnerAuthEAP(len, paramPayload));
+                    break;
+                case ExpandedInnerEAPMethod:
+                    addAuthParam(new ExpandedEAPMethod(authInfoID, len, paramPayload));
+                    break;
+                case CredentialType:
+                    addAuthParam(new Credential(authInfoID, len, paramPayload));
+                    break;
+                case TunneledEAPMethodCredType:
+                    addAuthParam(new Credential(authInfoID, len, paramPayload));
+                    break;
+                case VendorSpecific:
+                    addAuthParam(new VendorSpecificAuth(len, paramPayload));
+                    break;
+            }
+
+            realCount++;
+        }
+        if (realCount != count)
+            throw new ProtocolException("Invalid parameter count: " + realCount +
+                    ", expected " + count);
+    }
+
+    public EAPMethod(EAP.EAPMethodID eapMethodID, AuthParam authParam) {
+        mEAPMethodID = eapMethodID;
+        mAuthParams = new HashMap<>(1);
+        if (authParam != null) {
+            Set<AuthParam> authParams = new HashSet<>();
+            authParams.add(authParam);
+            mAuthParams.put(authParam.getAuthInfoID(), authParams);
+        }
+    }
+
+    private void addAuthParam(AuthParam param) {
+        Set<AuthParam> authParams = mAuthParams.get(param.getAuthInfoID());
+        if (authParams == null) {
+            authParams = new HashSet<>();
+            mAuthParams.put(param.getAuthInfoID(), authParams);
+        }
+        authParams.add(param);
+    }
+
+    public Map<EAP.AuthInfoID, Set<AuthParam>> getAuthParams() {
+        return Collections.unmodifiableMap(mAuthParams);
+    }
+
+    public EAP.EAPMethodID getEAPMethodID() {
+        return mEAPMethodID;
+    }
+
+    public int match(com.android.hotspot2.pps.Credential credential) {
+
+        EAPMethod credMethod = credential.getEAPMethod();
+        if (mEAPMethodID != credMethod.getEAPMethodID()) {
+            return AuthMatch.None;
+        }
+
+        switch (mEAPMethodID) {
+            case EAP_TTLS:
+                if (mAuthParams.isEmpty()) {
+                    return AuthMatch.Method;
+                }
+                int paramCount = 0;
+                for (Map.Entry<EAP.AuthInfoID, Set<AuthParam>> entry :
+                        credMethod.getAuthParams().entrySet()) {
+                    Set<AuthParam> params = mAuthParams.get(entry.getKey());
+                    if (params == null) {
+                        continue;
+                    }
+
+                    if (!Collections.disjoint(params, entry.getValue())) {
+                        return AuthMatch.MethodParam;
+                    }
+                    paramCount += params.size();
+                }
+                return paramCount > 0 ? AuthMatch.None : AuthMatch.Method;
+            case EAP_TLS:
+                return AuthMatch.MethodParam;
+            case EAP_SIM:
+            case EAP_AKA:
+            case EAP_AKAPrim:
+                return AuthMatch.Method;
+            default:
+                return AuthMatch.Method;
+        }
+    }
+
+    public AuthParam getAuthParam() {
+        if (mAuthParams.isEmpty()) {
+            return null;
+        }
+        Set<AuthParam> params = mAuthParams.values().iterator().next();
+        if (params.isEmpty()) {
+            return null;
+        }
+        return params.iterator().next();
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (this == thatObject) {
+            return true;
+        }
+        else if (thatObject == null || getClass() != thatObject.getClass()) {
+            return false;
+        }
+
+        EAPMethod that = (EAPMethod) thatObject;
+        return mEAPMethodID == that.mEAPMethodID && mAuthParams.equals(that.mAuthParams);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mEAPMethodID.hashCode();
+        result = 31 * result + mAuthParams.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("EAP Method ").append(mEAPMethodID).append('\n');
+        for (Set<AuthParam> paramSet : mAuthParams.values()) {
+            for (AuthParam param : paramSet) {
+                sb.append("      ").append(param.toString());
+            }
+        }
+        return sb.toString();
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/eap/ExpandedEAPMethod.java b/packages/Osu/src/com/android/anqp/eap/ExpandedEAPMethod.java
new file mode 100644
index 0000000..1358c09
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/eap/ExpandedEAPMethod.java
@@ -0,0 +1,78 @@
+package com.android.anqp.eap;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import static com.android.anqp.Constants.BYTE_MASK;
+import static com.android.anqp.Constants.INT_MASK;
+import static com.android.anqp.Constants.SHORT_MASK;
+
+/**
+ * An EAP authentication parameter, IEEE802.11-2012, table 8-188
+ */
+public class ExpandedEAPMethod implements AuthParam {
+
+    private final EAP.AuthInfoID mAuthInfoID;
+    private final int mVendorID;
+    private final long mVendorType;
+
+    public ExpandedEAPMethod(EAP.AuthInfoID authInfoID, int length, ByteBuffer payload)
+            throws ProtocolException {
+        if (length != 7) {
+            throw new ProtocolException("Bad length: " + payload.remaining());
+        }
+
+        mAuthInfoID = authInfoID;
+
+        ByteBuffer vndBuffer = payload.duplicate().order(ByteOrder.BIG_ENDIAN);
+
+        int id = vndBuffer.getShort() & SHORT_MASK;
+        id = (id << Byte.SIZE) | (vndBuffer.get() & BYTE_MASK);
+        mVendorID = id;
+        mVendorType = vndBuffer.getInt() & INT_MASK;
+
+        payload.position(payload.position()+7);
+    }
+
+    public ExpandedEAPMethod(EAP.AuthInfoID authInfoID, int vendorID, long vendorType) {
+        mAuthInfoID = authInfoID;
+        mVendorID = vendorID;
+        mVendorType = vendorType;
+    }
+
+    @Override
+    public EAP.AuthInfoID getAuthInfoID() {
+        return mAuthInfoID;
+    }
+
+    @Override
+    public int hashCode() {
+        return (mAuthInfoID.hashCode() * 31 + mVendorID) * 31 + (int) mVendorType;
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (thatObject == this) {
+            return true;
+        } else if (thatObject == null || thatObject.getClass() != ExpandedEAPMethod.class) {
+            return false;
+        } else {
+            ExpandedEAPMethod that = (ExpandedEAPMethod) thatObject;
+            return that.getVendorID() == getVendorID() && that.getVendorType() == getVendorType();
+        }
+    }
+
+    public int getVendorID() {
+        return mVendorID;
+    }
+
+    public long getVendorType() {
+        return mVendorType;
+    }
+
+    @Override
+    public String toString() {
+        return "Auth method " + mAuthInfoID + ", id " + mVendorID + ", type " + mVendorType + "\n";
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/eap/InnerAuthEAP.java b/packages/Osu/src/com/android/anqp/eap/InnerAuthEAP.java
new file mode 100644
index 0000000..571cf26
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/eap/InnerAuthEAP.java
@@ -0,0 +1,56 @@
+package com.android.anqp.eap;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+
+import static com.android.anqp.Constants.BYTE_MASK;
+
+/**
+ * An EAP authentication parameter, IEEE802.11-2012, table 8-188
+ */
+public class InnerAuthEAP implements AuthParam {
+
+    private final EAP.EAPMethodID mEapMethodID;
+
+    public InnerAuthEAP(int length, ByteBuffer payload) throws ProtocolException {
+        if (length != 1) {
+            throw new ProtocolException("Bad length: " + length);
+        }
+        int typeID = payload.get() & BYTE_MASK;
+        mEapMethodID = EAP.mapEAPMethod(typeID);
+    }
+
+    public InnerAuthEAP(EAP.EAPMethodID eapMethodID) {
+        mEapMethodID = eapMethodID;
+    }
+
+    @Override
+    public EAP.AuthInfoID getAuthInfoID() {
+        return EAP.AuthInfoID.InnerAuthEAPMethodType;
+    }
+
+    public EAP.EAPMethodID getEAPMethodID() {
+        return mEapMethodID;
+    }
+
+    @Override
+    public int hashCode() {
+        return mEapMethodID != null ? mEapMethodID.hashCode() : 0;
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (thatObject == this) {
+            return true;
+        } else if (thatObject == null || thatObject.getClass() != InnerAuthEAP.class) {
+            return false;
+        } else {
+            return ((InnerAuthEAP) thatObject).getEAPMethodID() == getEAPMethodID();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "Auth method InnerAuthEAP, inner = " + mEapMethodID + '\n';
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/eap/NonEAPInnerAuth.java b/packages/Osu/src/com/android/anqp/eap/NonEAPInnerAuth.java
new file mode 100644
index 0000000..9d37b4d
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/eap/NonEAPInnerAuth.java
@@ -0,0 +1,93 @@
+package com.android.anqp.eap;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.android.anqp.Constants.BYTE_MASK;
+
+/**
+ * An EAP authentication parameter, IEEE802.11-2012, table 8-188
+ */
+public class NonEAPInnerAuth implements AuthParam {
+
+    public enum NonEAPType {Reserved, PAP, CHAP, MSCHAP, MSCHAPv2}
+    private static final Map<NonEAPType, String> sOmaMap = new EnumMap<>(NonEAPType.class);
+    private static final Map<String, NonEAPType> sRevOmaMap = new HashMap<>();
+
+    private final NonEAPType mType;
+
+    static {
+        sOmaMap.put(NonEAPType.PAP, "PAP");
+        sOmaMap.put(NonEAPType.CHAP, "CHAP");
+        sOmaMap.put(NonEAPType.MSCHAP, "MS-CHAP");
+        sOmaMap.put(NonEAPType.MSCHAPv2, "MS-CHAP-V2");
+
+        for (Map.Entry<NonEAPType, String> entry : sOmaMap.entrySet()) {
+            sRevOmaMap.put(entry.getValue(), entry.getKey());
+        }
+    }
+
+    public NonEAPInnerAuth(int length, ByteBuffer payload) throws ProtocolException {
+        if (length != 1) {
+            throw new ProtocolException("Bad length: " + payload.remaining());
+        }
+
+        int typeID = payload.get() & BYTE_MASK;
+        mType = typeID < NonEAPType.values().length ?
+                NonEAPType.values()[typeID] :
+                NonEAPType.Reserved;
+    }
+
+    public NonEAPInnerAuth(NonEAPType type) {
+        mType = type;
+    }
+
+    /**
+     * Construct from the OMA-DM PPS data
+     * @param eapType as defined in the HS2.0 spec.
+     */
+    public NonEAPInnerAuth(String eapType) {
+        mType = sRevOmaMap.get(eapType);
+    }
+
+    @Override
+    public EAP.AuthInfoID getAuthInfoID() {
+        return EAP.AuthInfoID.NonEAPInnerAuthType;
+    }
+
+    public NonEAPType getType() {
+        return mType;
+    }
+
+    public String getOMAtype() {
+        return sOmaMap.get(mType);
+    }
+
+    public static String mapInnerType(NonEAPType type) {
+        return sOmaMap.get(type);
+    }
+
+    @Override
+    public int hashCode() {
+        return mType.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (thatObject == this) {
+            return true;
+        } else if (thatObject == null || thatObject.getClass() != NonEAPInnerAuth.class) {
+            return false;
+        } else {
+            return ((NonEAPInnerAuth) thatObject).getType() == getType();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "Auth method NonEAPInnerAuthEAP, inner = " + mType + '\n';
+    }
+}
diff --git a/packages/Osu/src/com/android/anqp/eap/VendorSpecificAuth.java b/packages/Osu/src/com/android/anqp/eap/VendorSpecificAuth.java
new file mode 100644
index 0000000..04a315d
--- /dev/null
+++ b/packages/Osu/src/com/android/anqp/eap/VendorSpecificAuth.java
@@ -0,0 +1,47 @@
+package com.android.anqp.eap;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * An EAP authentication parameter, IEEE802.11-2012, table 8-188
+ */
+public class VendorSpecificAuth implements AuthParam {
+
+    private final byte[] mData;
+
+    public VendorSpecificAuth(int length, ByteBuffer payload) throws ProtocolException {
+        mData = new byte[length];
+        payload.get(mData);
+    }
+
+    @Override
+    public EAP.AuthInfoID getAuthInfoID() {
+        return EAP.AuthInfoID.VendorSpecific;
+    }
+
+    public int hashCode() {
+        return Arrays.hashCode(mData);
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (thatObject == this) {
+            return true;
+        } else if (thatObject == null || thatObject.getClass() != VendorSpecificAuth.class) {
+            return false;
+        } else {
+            return Arrays.equals(((VendorSpecificAuth) thatObject).getData(), getData());
+        }
+    }
+
+    public byte[] getData() {
+        return mData;
+    }
+
+    @Override
+    public String toString() {
+        return "Auth method VendorSpecificAuth, data = " + Arrays.toString(mData) + '\n';
+    }
+}
diff --git a/packages/Osu/src/com/android/configparse/ConfigBuilder.java b/packages/Osu/src/com/android/configparse/ConfigBuilder.java
new file mode 100644
index 0000000..b760ade
--- /dev/null
+++ b/packages/Osu/src/com/android/configparse/ConfigBuilder.java
@@ -0,0 +1,258 @@
+package com.android.configparse;
+
+import android.content.Context;
+import android.net.Uri;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
+import android.util.Base64;
+import android.util.Log;
+
+import com.android.anqp.eap.AuthParam;
+import com.android.anqp.eap.EAP;
+import com.android.anqp.eap.EAPMethod;
+import com.android.anqp.eap.NonEAPInnerAuth;
+import com.android.hotspot2.IMSIParameter;
+import com.android.hotspot2.pps.Credential;
+import com.android.hotspot2.pps.HomeSP;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+public class ConfigBuilder {
+    private static final String TAG = "WCFG";
+
+    private static void dropFile(Uri uri, Context context) {
+        context.getContentResolver().delete(uri, null, null);
+    }
+
+    public static WifiConfiguration buildConfig(HomeSP homeSP, X509Certificate caCert,
+                                                 List<X509Certificate> clientChain, PrivateKey key)
+            throws IOException, GeneralSecurityException {
+
+        Credential credential = homeSP.getCredential();
+
+        WifiConfiguration config;
+
+        EAP.EAPMethodID eapMethodID = credential.getEAPMethod().getEAPMethodID();
+        switch (eapMethodID) {
+            case EAP_TTLS:
+                if (key != null || clientChain != null) {
+                    Log.w(TAG, "Client cert and/or key included with EAP-TTLS profile");
+                }
+                config = buildTTLSConfig(homeSP);
+                break;
+            case EAP_TLS:
+                config = buildTLSConfig(homeSP, clientChain, key);
+                break;
+            case EAP_AKA:
+            case EAP_AKAPrim:
+            case EAP_SIM:
+                if (key != null || clientChain != null || caCert != null) {
+                    Log.i(TAG, "Client/CA cert and/or key included with " +
+                            eapMethodID + " profile");
+                }
+                config = buildSIMConfig(homeSP);
+                break;
+            default:
+                throw new IOException("Unsupported EAP Method: " + eapMethodID);
+        }
+
+        WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;
+
+        enterpriseConfig.setCaCertificate(caCert);
+        enterpriseConfig.setAnonymousIdentity("anonymous@" + credential.getRealm());
+
+        return config;
+    }
+
+    // Retain for debugging purposes
+    /*
+    private static void xIterateCerts(KeyStore ks, X509Certificate caCert)
+            throws GeneralSecurityException {
+        Enumeration<String> aliases = ks.aliases();
+        while (aliases.hasMoreElements()) {
+            String alias = aliases.nextElement();
+            Certificate cert = ks.getCertificate(alias);
+            Log.d("HS2J", "Checking " + alias);
+            if (cert instanceof X509Certificate) {
+                X509Certificate x509Certificate = (X509Certificate) cert;
+                boolean sm = x509Certificate.getSubjectX500Principal().equals(
+                        caCert.getSubjectX500Principal());
+                boolean eq = false;
+                if (sm) {
+                    eq = Arrays.equals(x509Certificate.getEncoded(), caCert.getEncoded());
+                }
+                Log.d("HS2J", "Subject: " + x509Certificate.getSubjectX500Principal() +
+                        ": " + sm + "/" + eq);
+            }
+        }
+    }
+    */
+
+    private static WifiConfiguration buildTTLSConfig(HomeSP homeSP)
+            throws IOException {
+        Credential credential = homeSP.getCredential();
+
+        if (credential.getUserName() == null || credential.getPassword() == null) {
+            throw new IOException("EAP-TTLS provisioned without user name or password");
+        }
+
+        EAPMethod eapMethod = credential.getEAPMethod();
+
+        AuthParam authParam = eapMethod.getAuthParam();
+        if (authParam == null ||
+                authParam.getAuthInfoID() != EAP.AuthInfoID.NonEAPInnerAuthType) {
+            throw new IOException("Bad auth parameter for EAP-TTLS: " + authParam);
+        }
+
+        WifiConfiguration config = buildBaseConfiguration(homeSP);
+        NonEAPInnerAuth ttlsParam = (NonEAPInnerAuth) authParam;
+        WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;
+        enterpriseConfig.setPhase2Method(remapInnerMethod(ttlsParam.getType()));
+        enterpriseConfig.setIdentity(credential.getUserName());
+        enterpriseConfig.setPassword(credential.getPassword());
+
+        return config;
+    }
+
+    private static WifiConfiguration buildTLSConfig(HomeSP homeSP,
+                                                    List<X509Certificate> clientChain,
+                                                    PrivateKey clientKey)
+            throws IOException, GeneralSecurityException {
+
+        Credential credential = homeSP.getCredential();
+
+        X509Certificate clientCertificate = null;
+
+        if (clientKey == null || clientChain == null) {
+            throw new IOException("No key and/or cert passed for EAP-TLS");
+        }
+        if (credential.getCertType() != Credential.CertType.x509v3) {
+            throw new IOException("Invalid certificate type for TLS: " +
+                    credential.getCertType());
+        }
+
+        byte[] reference = credential.getFingerPrint();
+        MessageDigest digester = MessageDigest.getInstance("SHA-256");
+        for (X509Certificate certificate : clientChain) {
+            digester.reset();
+            byte[] fingerprint = digester.digest(certificate.getEncoded());
+            if (Arrays.equals(reference, fingerprint)) {
+                clientCertificate = certificate;
+                break;
+            }
+        }
+        if (clientCertificate == null) {
+            throw new IOException("No certificate in chain matches supplied fingerprint");
+        }
+
+        String alias = Base64.encodeToString(reference, Base64.DEFAULT);
+
+        WifiConfiguration config = buildBaseConfiguration(homeSP);
+        WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;
+        enterpriseConfig.setClientCertificateAlias(alias);
+        enterpriseConfig.setClientKeyEntry(clientKey, clientCertificate);
+
+        return config;
+    }
+
+    private static WifiConfiguration buildSIMConfig(HomeSP homeSP)
+            throws IOException {
+
+        Credential credential = homeSP.getCredential();
+        IMSIParameter credImsi = credential.getImsi();
+
+        /*
+         * Uncomment to enforce strict IMSI matching with currently installed SIM cards.
+         *
+        TelephonyManager tm = TelephonyManager.from(context);
+        SubscriptionManager sub = SubscriptionManager.from(context);
+        boolean match = false;
+
+        for (int subId : sub.getActiveSubscriptionIdList()) {
+            String imsi = tm.getSubscriberId(subId);
+            if (credImsi.matches(imsi)) {
+                match = true;
+                break;
+            }
+        }
+        if (!match) {
+            throw new IOException("Supplied IMSI does not match any SIM card");
+        }
+        */
+
+        WifiConfiguration config = buildBaseConfiguration(homeSP);
+        config.enterpriseConfig.setPlmn(credImsi.toString());
+        return config;
+    }
+
+    private static WifiConfiguration buildBaseConfiguration(HomeSP homeSP) throws IOException {
+        EAP.EAPMethodID eapMethodID = homeSP.getCredential().getEAPMethod().getEAPMethodID();
+
+        WifiConfiguration config = new WifiConfiguration();
+
+        config.FQDN = homeSP.getFQDN();
+
+        HashSet<Long> roamingConsortiumIds = homeSP.getRoamingConsortiums();
+        config.roamingConsortiumIds = new long[roamingConsortiumIds.size()];
+        int i = 0;
+        for (long id : roamingConsortiumIds) {
+            config.roamingConsortiumIds[i] = id;
+            i++;
+        }
+        config.providerFriendlyName = homeSP.getFriendlyName();
+
+        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        enterpriseConfig.setEapMethod(remapEAPMethod(eapMethodID));
+        enterpriseConfig.setRealm(homeSP.getCredential().getRealm());
+        if (homeSP.getUpdateIdentifier() >= 0) {
+            config.updateIdentifier = Integer.toString(homeSP.getUpdateIdentifier());
+        }
+        config.enterpriseConfig = enterpriseConfig;
+        if (homeSP.getUpdateIdentifier() >= 0) {
+            config.updateIdentifier = Integer.toString(homeSP.getUpdateIdentifier());
+        }
+
+        return config;
+    }
+
+    private static int remapEAPMethod(EAP.EAPMethodID eapMethodID) throws IOException {
+        switch (eapMethodID) {
+            case EAP_TTLS:
+                return WifiEnterpriseConfig.Eap.TTLS;
+            case EAP_TLS:
+                return WifiEnterpriseConfig.Eap.TLS;
+            case EAP_SIM:
+                return WifiEnterpriseConfig.Eap.SIM;
+            case EAP_AKA:
+                return WifiEnterpriseConfig.Eap.AKA;
+            case EAP_AKAPrim:
+                return WifiEnterpriseConfig.Eap.AKA_PRIME;
+            default:
+                throw new IOException("Bad EAP method: " + eapMethodID);
+        }
+    }
+
+    private static int remapInnerMethod(NonEAPInnerAuth.NonEAPType type) throws IOException {
+        switch (type) {
+            case PAP:
+                return WifiEnterpriseConfig.Phase2.PAP;
+            case MSCHAP:
+                return WifiEnterpriseConfig.Phase2.MSCHAP;
+            case MSCHAPv2:
+                return WifiEnterpriseConfig.Phase2.MSCHAPV2;
+            case CHAP:
+            default:
+                throw new IOException("Inner method " + type + " not supported");
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/AppBridge.java b/packages/Osu/src/com/android/hotspot2/AppBridge.java
new file mode 100644
index 0000000..95f5970
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/AppBridge.java
@@ -0,0 +1,63 @@
+package com.android.hotspot2;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+
+import com.android.hotspot2.osu.OSUInfo;
+import com.android.hotspot2.osu.OSUOperationStatus;
+
+import java.util.List;
+
+public class AppBridge {
+    public static final String ACTION_OSU_NOTIFICATION = "com.android.hotspot2.OSU_NOTIFICATION";
+    public static final String OSU_COUNT = "osu-count";
+    public static final String SP_NAME = "sp-name";
+    public static final String PROV_SUCCESS = "prov-success";
+    public static final String DEAUTH = "deauth";
+    public static final String DEAUTH_DELAY = "deauth-delay";
+    public static final String DEAUTH_URL = "deauth-url";
+    public static final String PROV_MESSAGE = "prov-message";
+    public static final String OSU_INFO = "osu-info";
+
+    public static final String GET_OSUS_ACTION = "com.android.hotspot2.GET_OSUS";
+
+    private final Context mContext;
+
+    public AppBridge(Context context) {
+        mContext = context;
+    }
+
+    public void showOsuCount(int osuCount, List<OSUInfo> osus) {
+        Intent intent = new Intent(ACTION_OSU_NOTIFICATION);
+        intent.putExtra(OSU_COUNT, osuCount);
+        intent.setFlags(
+                Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        mContext.startActivity(intent);
+    }
+
+    public void showStatus(OSUOperationStatus status, String spName, String message,
+                           String remoteStatus) {
+        Intent intent = new Intent(ACTION_OSU_NOTIFICATION);
+        intent.putExtra(SP_NAME, spName);
+        intent.putExtra(PROV_SUCCESS, status == OSUOperationStatus.ProvisioningSuccess);
+        if (message != null) {
+            intent.putExtra(PROV_MESSAGE, message);
+        }
+        intent.setFlags(
+                Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+
+    public void showDeauth(String spName, boolean ess, int delay, String url) {
+        Intent intent = new Intent(ACTION_OSU_NOTIFICATION);
+        intent.putExtra(SP_NAME, spName);
+        intent.putExtra(DEAUTH, ess);
+        intent.putExtra(DEAUTH_DELAY, delay);
+        intent.putExtra(DEAUTH_URL, url);
+        intent.setFlags(
+                Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/AuthMatch.java b/packages/Osu/src/com/android/hotspot2/AuthMatch.java
new file mode 100644
index 0000000..f9c1f42
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/AuthMatch.java
@@ -0,0 +1,39 @@
+package com.android.hotspot2;
+
+/**
+ * Match score for EAP credentials:
+ * None means that there is a distinct mismatch, i.e. realm, method or parameter is defined
+ * and mismatches that of the credential.
+ * Indeterminate means that there is no ANQP information to match against.
+ * Note: The numeric values given to the constants are used for preference comparison and
+ * must be maintained accordingly.
+ */
+public abstract class AuthMatch {
+    public static final int None = -1;
+    public static final int Indeterminate = 0;
+    public static final int Realm = 0x04;
+    public static final int Method = 0x02;
+    public static final int Param = 0x01;
+    public static final int MethodParam = Method | Param;
+    public static final int Exact = Realm | Method | Param;
+
+    public static String toString(int match) {
+        if (match < 0) {
+            return "None";
+        } else if (match == 0) {
+            return "Indeterminate";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        if ((match & Realm) != 0) {
+            sb.append("Realm");
+        }
+        if ((match & Method) != 0) {
+            sb.append("Method");
+        }
+        if ((match & Param) != 0) {
+            sb.append("Param");
+        }
+        return sb.toString();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/IMSIParameter.java b/packages/Osu/src/com/android/hotspot2/IMSIParameter.java
new file mode 100644
index 0000000..1d5d95d
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/IMSIParameter.java
@@ -0,0 +1,96 @@
+package com.android.hotspot2;
+
+import java.io.IOException;
+
+public class IMSIParameter {
+    private final String mImsi;
+    private final boolean mPrefix;
+
+    public IMSIParameter(String imsi, boolean prefix) {
+        mImsi = imsi;
+        mPrefix = prefix;
+    }
+
+    public IMSIParameter(String imsi) throws IOException {
+        if (imsi == null || imsi.length() == 0) {
+            throw new IOException("Bad IMSI: '" + imsi + "'");
+        }
+
+        int nonDigit;
+        char stopChar = '\0';
+        for (nonDigit = 0; nonDigit < imsi.length(); nonDigit++) {
+            stopChar = imsi.charAt(nonDigit);
+            if (stopChar < '0' || stopChar > '9') {
+                break;
+            }
+        }
+
+        if (nonDigit == imsi.length()) {
+            mImsi = imsi;
+            mPrefix = false;
+        } else if (nonDigit == imsi.length() - 1 && stopChar == '*') {
+            mImsi = imsi.substring(0, nonDigit);
+            mPrefix = true;
+        } else {
+            throw new IOException("Bad IMSI: '" + imsi + "'");
+        }
+    }
+
+    public boolean matches(String fullIMSI) {
+        if (mPrefix) {
+            return mImsi.regionMatches(false, 0, fullIMSI, 0, mImsi.length());
+        } else {
+            return mImsi.equals(fullIMSI);
+        }
+    }
+
+    public boolean matchesMccMnc(String mccMnc) {
+        if (mPrefix) {
+            // For a prefix match, the entire prefix must match the mcc+mnc
+            return mImsi.regionMatches(false, 0, mccMnc, 0, mImsi.length());
+        } else {
+            // For regular match, the entire length of mcc+mnc must match this IMSI
+            return mImsi.regionMatches(false, 0, mccMnc, 0, mccMnc.length());
+        }
+    }
+
+    public boolean isPrefix() {
+        return mPrefix;
+    }
+
+    public String getImsi() {
+        return mImsi;
+    }
+
+    public int prefixLength() {
+        return mImsi.length();
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (this == thatObject) {
+            return true;
+        } else if (thatObject == null || getClass() != thatObject.getClass()) {
+            return false;
+        }
+
+        IMSIParameter that = (IMSIParameter) thatObject;
+        return mPrefix == that.mPrefix && mImsi.equals(that.mImsi);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = mImsi != null ? mImsi.hashCode() : 0;
+        result = 31 * result + (mPrefix ? 1 : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        if (mPrefix) {
+            return mImsi + '*';
+        } else {
+            return mImsi;
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/OMADMAdapter.java b/packages/Osu/src/com/android/hotspot2/OMADMAdapter.java
new file mode 100644
index 0000000..1429b0b
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/OMADMAdapter.java
@@ -0,0 +1,601 @@
+package com.android.hotspot2;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.wifi.WifiManager;
+import android.os.SystemProperties;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.anqp.eap.EAP;
+import com.android.hotspot2.omadm.MOTree;
+import com.android.hotspot2.omadm.OMAConstants;
+import com.android.hotspot2.omadm.OMAConstructed;
+import com.android.hotspot2.osu.OSUManager;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static com.android.anqp.eap.NonEAPInnerAuth.NonEAPType;
+import static com.android.anqp.eap.NonEAPInnerAuth.mapInnerType;
+
+public class OMADMAdapter {
+    private final Context mContext;
+    private final String mImei;
+    private final String mImsi;
+    private final String mDevID;
+    private final List<PathAccessor> mDevInfo;
+    private final List<PathAccessor> mDevDetail;
+
+    private static final int IMEI_Length = 14;
+
+    private static final String[] ExtWiFiPath = {"DevDetail", "Ext", "org.wi-fi", "Wi-Fi"};
+
+    private static final Map<String, String> RTProps = new HashMap<>();
+
+    private MOTree mDevInfoTree;
+    private MOTree mDevDetailTree;
+
+    private static OMADMAdapter sInstance;
+
+    static {
+        RTProps.put(ExtWiFiPath[2], "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0");
+    }
+
+    private static abstract class PathAccessor {
+        private final String[] mPath;
+        private final int mHashCode;
+
+        protected PathAccessor(Object... path) {
+            int length = 0;
+            for (Object o : path) {
+                if (o.getClass() == String[].class) {
+                    length += ((String[]) o).length;
+                } else {
+                    length++;
+                }
+            }
+            mPath = new String[length];
+            int n = 0;
+            for (Object o : path) {
+                if (o.getClass() == String[].class) {
+                    for (String element : (String[]) o) {
+                        mPath[n++] = element;
+                    }
+                } else if (o.getClass() == Integer.class) {
+                    mPath[n++] = "x" + o.toString();
+                } else {
+                    mPath[n++] = o.toString();
+                }
+            }
+            mHashCode = Arrays.hashCode(mPath);
+        }
+
+        @Override
+        public int hashCode() {
+            return mHashCode;
+        }
+
+        @Override
+        public boolean equals(Object thatObject) {
+            return thatObject == this || (thatObject instanceof ConstPathAccessor &&
+                    Arrays.equals(mPath, ((PathAccessor) thatObject).mPath));
+        }
+
+        private String[] getPath() {
+            return mPath;
+        }
+
+        protected abstract Object getValue();
+    }
+
+    private static class ConstPathAccessor<T> extends PathAccessor {
+        private final T mValue;
+
+        protected ConstPathAccessor(T value, Object... path) {
+            super(path);
+            mValue = value;
+        }
+
+        protected Object getValue() {
+            return mValue;
+        }
+    }
+
+    public static OMADMAdapter getInstance(Context context) {
+        synchronized (OMADMAdapter.class) {
+            if (sInstance == null) {
+                sInstance = new OMADMAdapter(context);
+            }
+            return sInstance;
+        }
+    }
+
+    private OMADMAdapter(Context context) {
+        mContext = context;
+
+        TelephonyManager tm = (TelephonyManager) context
+                .getSystemService(Context.TELEPHONY_SERVICE);
+        String simOperator = tm.getSimOperator();
+        mImsi = tm.getSubscriberId();
+        mImei = tm.getImei();
+        String strDevId;
+
+        /* Use MEID for sprint */
+        if ("310120".equals(simOperator) || (mImsi != null && mImsi.startsWith("310120"))) {
+                /* MEID is 14 digits. If IMEI is returned as DevId, MEID can be extracted by taking
+                 * first 14 characters. This is not always true but should be the case for sprint */
+            strDevId = tm.getDeviceId().toUpperCase(Locale.US);
+            if (strDevId != null && strDevId.length() >= IMEI_Length) {
+                strDevId = strDevId.substring(0, IMEI_Length);
+            } else {
+                Log.w(OSUManager.TAG, "MEID cannot be extracted from DeviceId " + strDevId);
+            }
+        } else {
+            if (isPhoneTypeLTE()) {
+                strDevId = mImei;
+            } else {
+                strDevId = tm.getDeviceId();
+            }
+            if (strDevId == null) {
+                strDevId = "unknown";
+            }
+            strDevId = strDevId.toUpperCase(Locale.US);
+
+            if (!isPhoneTypeLTE()) {
+                strDevId = strDevId.substring(0, IMEI_Length);
+            }
+        }
+        mDevID = strDevId;
+
+        mDevInfo = new ArrayList<>();
+        mDevInfo.add(new ConstPathAccessor<>(strDevId, "DevInfo", "DevID"));
+        mDevInfo.add(new ConstPathAccessor<>(getProperty(context,
+                "Man", "ro.product.manufacturer", "unknown"), "DevInfo", "Man"));
+        mDevInfo.add(new ConstPathAccessor<>(getProperty(context,
+                "Mod", "ro.product.model", "generic"), "DevInfo", "Mod"));
+        mDevInfo.add(new ConstPathAccessor<>(getLocale(context), "DevInfo", "Lang"));
+        mDevInfo.add(new ConstPathAccessor<>("1.2", "DevInfo", "DmV"));
+
+        mDevDetail = new ArrayList<>();
+        mDevDetail.add(new ConstPathAccessor<>(getDeviceType(), "DevDetail", "DevType"));
+        mDevDetail.add(new ConstPathAccessor<>(SystemProperties.get("ro.product.brand"),
+                "DevDetail", "OEM"));
+        mDevDetail.add(new ConstPathAccessor<>(getVersion(context, false), "DevDetail", "FwV"));
+        mDevDetail.add(new ConstPathAccessor<>(getVersion(context, true), "DevDetail", "SwV"));
+        mDevDetail.add(new ConstPathAccessor<>(getHwV(), "DevDetail", "HwV"));
+        mDevDetail.add(new ConstPathAccessor<>("TRUE", "DevDetail", "LrgObj"));
+
+        mDevDetail.add(new ConstPathAccessor<>(32, "DevDetail", "URI", "MaxDepth"));
+        mDevDetail.add(new ConstPathAccessor<>(2048, "DevDetail", "URI", "MaxTotLen"));
+        mDevDetail.add(new ConstPathAccessor<>(64, "DevDetail", "URI", "MaxSegLen"));
+
+        AtomicInteger index = new AtomicInteger(1);
+        mDevDetail.add(new ConstPathAccessor<>(EAP.EAP_TTLS, ExtWiFiPath,
+                "EAPMethodList", index, "EAPType"));
+        mDevDetail.add(new ConstPathAccessor<>(mapInnerType(NonEAPType.MSCHAPv2), ExtWiFiPath,
+                "EAPMethodList", index, "InnerMethod"));
+
+        index.incrementAndGet();
+        mDevDetail.add(new ConstPathAccessor<>(EAP.EAP_TTLS, ExtWiFiPath,
+                "EAPMethodList", index, "EAPType"));
+        mDevDetail.add(new ConstPathAccessor<>(mapInnerType(NonEAPType.PAP), ExtWiFiPath,
+                "EAPMethodList", index, "InnerMethod"));
+
+        index.incrementAndGet();
+        mDevDetail.add(new ConstPathAccessor<>(EAP.EAP_TTLS, ExtWiFiPath,
+                "EAPMethodList", index, "EAPType"));
+        mDevDetail.add(new ConstPathAccessor<>(mapInnerType(NonEAPType.MSCHAP), ExtWiFiPath,
+                "EAPMethodList", index, "InnerMethod"));
+
+        index.incrementAndGet();
+        mDevDetail.add(new ConstPathAccessor<>(EAP.EAP_TLS, ExtWiFiPath,
+                "EAPMethodList", index, "EAPType"));
+        index.incrementAndGet();
+        mDevDetail.add(new ConstPathAccessor<>(EAP.EAP_AKA, ExtWiFiPath,
+                "EAPMethodList", index, "EAPType"));
+        index.incrementAndGet();
+        mDevDetail.add(new ConstPathAccessor<>(EAP.EAP_AKAPrim, ExtWiFiPath,
+                "EAPMethodList", index, "EAPType"));
+        index.incrementAndGet();
+        mDevDetail.add(new ConstPathAccessor<>(EAP.EAP_SIM, ExtWiFiPath,
+                "EAPMethodList", index, "EAPType"));
+
+        mDevDetail.add(new ConstPathAccessor<>("FALSE", ExtWiFiPath, "ManufacturingCertificate"));
+        mDevDetail.add(new ConstPathAccessor<>(mImsi, ExtWiFiPath, "IMSI"));
+        mDevDetail.add(new ConstPathAccessor<>(mImei, ExtWiFiPath, "IMEI_MEID"));
+        mDevDetail.add(new PathAccessor(ExtWiFiPath, "Wi-FiMACAddress") {
+            @Override
+            protected String getValue() {
+                return getMAC();
+            }
+        });
+    }
+
+    private static void buildNode(PathAccessor pathAccessor, int depth, OMAConstructed parent)
+            throws IOException {
+        String[] path = pathAccessor.getPath();
+        String name = path[depth];
+        if (depth < path.length - 1) {
+            OMAConstructed node = (OMAConstructed) parent.getChild(name);
+            if (node == null) {
+                node = (OMAConstructed) parent.addChild(name, RTProps.get(name),
+                        null, null);
+            }
+            buildNode(pathAccessor, depth + 1, node);
+        } else if (pathAccessor.getValue() != null) {
+            parent.addChild(name, null, pathAccessor.getValue().toString(), null);
+        }
+    }
+
+    public String getMAC() {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        return wifiManager != null ?
+                String.format("%012x",
+                        Utils.parseMac(wifiManager.getConnectionInfo().getMacAddress())) :
+                null;
+    }
+
+    public String getImei() {
+        return mImei;
+    }
+
+    public byte[] getMeid() {
+        return Arrays.copyOf(mImei.getBytes(StandardCharsets.ISO_8859_1), IMEI_Length);
+    }
+
+    public String getDevID() {
+        return mDevID;
+    }
+
+    public MOTree getMO(String urn) {
+        try {
+            switch (urn) {
+                case OMAConstants.DevInfoURN:
+                    if (mDevInfoTree == null) {
+                        OMAConstructed root = new OMAConstructed(null, "DevInfo", urn);
+                        for (PathAccessor pathAccessor : mDevInfo) {
+                            buildNode(pathAccessor, 1, root);
+                        }
+                        mDevInfoTree = MOTree.buildMgmtTree(OMAConstants.DevInfoURN,
+                                OMAConstants.OMAVersion, root);
+                    }
+                    return mDevInfoTree;
+                case OMAConstants.DevDetailURN:
+                    if (mDevDetailTree == null) {
+                        OMAConstructed root = new OMAConstructed(null, "DevDetail", urn);
+                        for (PathAccessor pathAccessor : mDevDetail) {
+                            buildNode(pathAccessor, 1, root);
+                        }
+                        mDevDetailTree = MOTree.buildMgmtTree(OMAConstants.DevDetailURN,
+                                OMAConstants.OMAVersion, root);
+                    }
+                    return mDevDetailTree;
+                default:
+                    throw new IllegalArgumentException(urn);
+            }
+        } catch (IOException ioe) {
+            Log.e(OSUManager.TAG, "Caught exception building OMA Tree: " + ioe, ioe);
+            return null;
+        }
+
+        /*
+        switch (urn) {
+            case DevInfoURN: return DevInfo;
+            case DevDetailURN: return DevDetail;
+            default: throw new IllegalArgumentException(urn);
+        }
+        */
+    }
+
+    // TODO: For now, assume the device supports LTE.
+    private static boolean isPhoneTypeLTE() {
+        return true;
+    }
+
+    private static String getHwV() {
+        try {
+            return SystemProperties.get("ro.hardware", "Unknown")
+                    + "." + SystemProperties.get("ro.revision", "Unknown");
+        } catch (RuntimeException e) {
+            return "Unknown";
+        }
+    }
+
+    private static String getDeviceType() {
+        String devicetype = SystemProperties.get("ro.build.characteristics");
+        if ((((TextUtils.isEmpty(devicetype)) || (!devicetype.equals("tablet"))))) {
+            devicetype = "phone";
+        }
+        return devicetype;
+    }
+
+    private static String getVersion(Context context, boolean swv) {
+        String version;
+        try {
+            if (!isSprint(context) && swv) {
+                return "Android " + SystemProperties.get("ro.build.version.release");
+            } else {
+                version = SystemProperties.get("ro.build.version.full");
+                if (null == version || version.equals("")) {
+                    return SystemProperties.get("ro.build.id", null) + "~"
+                            + SystemProperties.get("ro.build.config.version", null) + "~"
+                            + SystemProperties.get("gsm.version.baseband", null) + "~"
+                            + SystemProperties.get("ro.gsm.flexversion", null);
+                }
+            }
+        } catch (RuntimeException e) {
+            return "Unknown";
+        }
+        return version;
+    }
+
+    private static boolean isSprint(Context context) {
+        TelephonyManager tm = (TelephonyManager) context
+                .getSystemService(Context.TELEPHONY_SERVICE);
+        String simOperator = tm.getSimOperator();
+        String imsi = tm.getSubscriberId();
+        /* Use MEID for sprint */
+        if ("310120".equals(simOperator) || (imsi != null && imsi.startsWith("310120"))) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private static String getLocale(Context context) {
+        String strLang = readValueFromFile(context, "Lang");
+        if (strLang == null) {
+            strLang = Locale.getDefault().toString();
+        }
+        return strLang;
+    }
+
+    private static String getProperty(Context context, String key, String propKey, String dflt) {
+        String strMan = readValueFromFile(context, key);
+        if (strMan == null) {
+            strMan = SystemProperties.get(propKey, dflt);
+        }
+        return strMan;
+    }
+
+    private static String readValueFromFile(Context context, String propName) {
+        String ret = null;
+        // use preference instead of the system property
+        SharedPreferences prefs = context.getSharedPreferences("dmconfig", 0);
+        if (prefs.contains(propName)) {
+            ret = prefs.getString(propName, "");
+            if (ret.length() == 0) {
+                ret = null;
+            }
+        }
+        return ret;
+    }
+
+    private static final String DevDetail =
+            "<MgmtTree>" +
+                    "<VerDTD>1.2</VerDTD>" +
+                    "<Node>" +
+                    "<NodeName>DevDetail</NodeName>" +
+                    "<RTProperties>" +
+                    "<Type>" +
+                    "<DDFName>urn:oma:mo:oma-dm-devdetail:1.0</DDFName>" +
+                    "</Type>" +
+                    "</RTProperties>" +
+                    "<Node>" +
+                    "<NodeName>Ext</NodeName>" +
+                    "<Node>" +
+                    "<NodeName>org.wi-fi</NodeName>" +
+                    "<RTProperties>" +
+                    "<Type>" +
+                    "<DDFName>" +
+                    "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext :1.0" +
+                    "</DDFName>" +
+                    "</Type>" +
+                    "</RTProperties>" +
+                    "<Node>" +
+                    "<NodeName>Wi-Fi</NodeName>" +
+                    "<Node>" +
+                    "<NodeName>EAPMethodList</NodeName>" +
+                    "<Node>" +
+                    "<NodeName>Method01</NodeName>" +
+                    "<!-- EAP-TTLS/MS-CHAPv2 -->" +
+                    "<Node>" +
+                    "<NodeName>EAPType</NodeName>" +
+                    "<Value>21</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>InnerMethod</NodeName>" +
+                    "<Value>MS-CHAP-V2</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Method02</NodeName>" +
+                    "<!-- EAP-TLS -->" +
+                    "<Node>" +
+                    "<NodeName>EAPType</NodeName>" +
+                    "<Value>13</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Method03</NodeName>" +
+                    "<!-- EAP-SIM -->" +
+                    "<Node>" +
+                    "<NodeName>EAPType</NodeName>" +
+                    "<Value>18</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Method04</NodeName>" +
+                    "<!-- EAP-AKA -->" +
+                    "<Node>" +
+                    "<NodeName>EAPType</NodeName>" +
+                    "<Value>23</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Method05</NodeName>" +
+                    "<!-- EAP-AKA' -->" +
+                    "<Node>" +
+                    "<NodeName>EAPType</NodeName>" +
+                    "<Value>50</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Method06</NodeName>" +
+                    "<!-- Supported method (EAP-TTLS/PAP) not mandated by Hotspot2.0-->" +
+                    "<Node>" +
+                    "<NodeName>EAPType</NodeName>" +
+                    "<Value>21</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>InnerMethod</NodeName>" +
+                    "<Value>PAP</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Method07</NodeName>" +
+                    "<!-- Supported method (PEAP/EAP-GTC) not mandated by Hotspot 2.0-->" +
+                    "<Node>" +
+                    "<NodeName>EAPType</NodeName>" +
+                    "<Value>25</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>InnerEAPType</NodeName>" +
+                    "<Value>6</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>SPCertificate</NodeName>" +
+                    "<Node>" +
+                    "<NodeName>Cert01</NodeName>" +
+                    "<Node>" +
+                    "<NodeName>CertificateIssuerName</NodeName>" +
+                    "<Value>CN=RuckusCA</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>ManufacturingCertificate</NodeName>" +
+                    "<Value>FALSE</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Wi-FiMACAddress</NodeName>" +
+                    "<Value>001d2e112233</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>ClientTriggerRedirectURI</NodeName>" +
+                    "<Value>http://127.0.0.1:12345/index.htm</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Ops</NodeName>" +
+                    "<Node>" +
+                    "<NodeName>launchBrowserToURI</NodeName>" +
+                    "<Value></Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>negotiateClientCertTLS</NodeName>" +
+                    "<Value></Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>getCertificate</NodeName>" +
+                    "<Value></Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<!-- End of Wi-Fi node -->" +
+                    "</Node>" +
+                    "<!-- End of org.wi-fi node -->" +
+                    "</Node>" +
+                    "<!-- End of Ext node -->" +
+                    "<Node>" +
+                    "<NodeName>URI</NodeName>" +
+                    "<Node>" +
+                    "<NodeName>MaxDepth</NodeName>" +
+                    "<Value>32</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>MaxTotLen</NodeName>" +
+                    "<Value>2048</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>MaxSegLen</NodeName>" +
+                    "<Value>64</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>DevType</NodeName>" +
+                    "<Value>Smartphone</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>OEM</NodeName>" +
+                    "<Value>ACME</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>FwV</NodeName>" +
+                    "<Value>1.2.100.5</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>SwV</NodeName>" +
+                    "<Value>9.11.130</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>HwV</NodeName>" +
+                    "<Value>1.0</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>LrgObj</NodeName>" +
+                    "<Value>TRUE</Value>" +
+                    "</Node>" +
+                    "</Node>" +
+                    "</MgmtTree>";
+
+
+    private static final String DevInfo =
+            "<MgmtTree>" +
+                    "<VerDTD>1.2</VerDTD>" +
+                    "<Node>" +
+                    "<NodeName>DevInfo</NodeName>" +
+                    "<RTProperties>" +
+                    "<Type>" +
+                    "<DDFName>urn:oma:mo:oma-dm-devinfo:1.0" +
+                    "</DDFName>" +
+                    "</Type>" +
+                    "</RTProperties>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>DevID</NodeName>" +
+                    "<Path>DevInfo</Path>" +
+                    "<Value>urn:acme:00-11-22-33-44-55</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Man</NodeName>" +
+                    "<Path>DevInfo</Path>" +
+                    "<Value>ACME</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Mod</NodeName>" +
+                    "<Path>DevInfo</Path>" +
+                    "<Value>HS2.0-01</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>DmV</NodeName>" +
+                    "<Path>DevInfo</Path>" +
+                    "<Value>1.2</Value>" +
+                    "</Node>" +
+                    "<Node>" +
+                    "<NodeName>Lang</NodeName>" +
+                    "<Path>DevInfo</Path>" +
+                    "<Value>en-US</Value>" +
+                    "</Node>" +
+                    "</MgmtTree>";
+}
diff --git a/packages/Osu/src/com/android/hotspot2/PasspointMatch.java b/packages/Osu/src/com/android/hotspot2/PasspointMatch.java
new file mode 100644
index 0000000..8330283
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/PasspointMatch.java
@@ -0,0 +1,9 @@
+package com.android.hotspot2;
+
+public enum PasspointMatch {
+    HomeProvider,
+    RoamingProvider,
+    Incomplete,
+    None,
+    Declined
+}
diff --git a/packages/Osu/src/com/android/hotspot2/Utils.java b/packages/Osu/src/com/android/hotspot2/Utils.java
new file mode 100644
index 0000000..100b967
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/Utils.java
@@ -0,0 +1,300 @@
+package com.android.hotspot2;
+
+import com.android.anqp.Constants;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TimeZone;
+
+import static com.android.anqp.Constants.BYTE_MASK;
+import static com.android.anqp.Constants.NIBBLE_MASK;
+
+public abstract class Utils {
+
+    public static final long UNSET_TIME = -1;
+
+    private static final int EUI48Length = 6;
+    private static final int EUI64Length = 8;
+    private static final long EUI48Mask = 0xffffffffffffL;
+    private static final String[] PLMNText = {"org", "3gppnetwork", "mcc*", "mnc*", "wlan"};
+
+    public static List<String> splitDomain(String domain) {
+
+        if (domain.endsWith("."))
+            domain = domain.substring(0, domain.length() - 1);
+        int at = domain.indexOf('@');
+        if (at >= 0)
+            domain = domain.substring(at + 1);
+
+        String[] labels = domain.toLowerCase().split("\\.");
+        LinkedList<String> labelList = new LinkedList<String>();
+        for (String label : labels) {
+            labelList.addFirst(label);
+        }
+
+        return labelList;
+    }
+
+    public static long parseMac(String s) {
+
+        long mac = 0;
+        int count = 0;
+        for (int n = 0; n < s.length(); n++) {
+            int nibble = Utils.fromHex(s.charAt(n), true);  // Set lenient to not blow up on ':'
+            if (nibble >= 0) {                              // ... and use only legit hex.
+                mac = (mac << 4) | nibble;
+                count++;
+            }
+        }
+        if (count < 12 || (count & 1) == 1) {
+            throw new IllegalArgumentException("Bad MAC address: '" + s + "'");
+        }
+        return mac;
+    }
+
+    public static String macToString(long mac) {
+        int len = (mac & ~EUI48Mask) != 0 ? EUI64Length : EUI48Length;
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (int n = (len - 1) * Byte.SIZE; n >= 0; n -= Byte.SIZE) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(':');
+            }
+            sb.append(String.format("%02x", (mac >>> n) & Constants.BYTE_MASK));
+        }
+        return sb.toString();
+    }
+
+    public static String getMccMnc(List<String> domain) {
+        if (domain.size() != PLMNText.length) {
+            return null;
+        }
+
+        for (int n = 0; n < PLMNText.length; n++) {
+            String expect = PLMNText[n];
+            int len = expect.endsWith("*") ? expect.length() - 1 : expect.length();
+            if (!domain.get(n).regionMatches(0, expect, 0, len)) {
+                return null;
+            }
+        }
+
+        String prefix = domain.get(2).substring(3) + domain.get(3).substring(3);
+        for (int n = 0; n < prefix.length(); n++) {
+            char ch = prefix.charAt(n);
+            if (ch < '0' || ch > '9') {
+                return null;
+            }
+        }
+        return prefix;
+    }
+
+    public static String bssidsToString(Collection<Long> bssids) {
+        StringBuilder sb = new StringBuilder();
+        for (Long bssid : bssids) {
+            sb.append(String.format(" %012x", bssid));
+        }
+        return sb.toString();
+    }
+
+    public static String roamingConsortiumsToString(long[] ois) {
+        if (ois == null) {
+            return "null";
+        }
+        List<Long> list = new ArrayList<Long>(ois.length);
+        for (long oi : ois) {
+            list.add(oi);
+        }
+        return roamingConsortiumsToString(list);
+    }
+
+    public static String roamingConsortiumsToString(Collection<Long> ois) {
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (long oi : ois) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(", ");
+            }
+            if (Long.numberOfLeadingZeros(oi) > 40) {
+                sb.append(String.format("%06x", oi));
+            } else {
+                sb.append(String.format("%010x", oi));
+            }
+        }
+        return sb.toString();
+    }
+
+    public static String toUnicodeEscapedString(String s) {
+        StringBuilder sb = new StringBuilder(s.length());
+        for (int n = 0; n < s.length(); n++) {
+            char ch = s.charAt(n);
+            if (ch >= ' ' && ch < 127) {
+                sb.append(ch);
+            } else {
+                sb.append("\\u").append(String.format("%04x", (int) ch));
+            }
+        }
+        return sb.toString();
+    }
+
+    public static String toHexString(byte[] data) {
+        if (data == null) {
+            return "null";
+        }
+        StringBuilder sb = new StringBuilder(data.length * 3);
+
+        boolean first = true;
+        for (byte b : data) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(' ');
+            }
+            sb.append(String.format("%02x", b & BYTE_MASK));
+        }
+        return sb.toString();
+    }
+
+    public static String toHex(byte[] octets) {
+        StringBuilder sb = new StringBuilder(octets.length * 2);
+        for (byte o : octets) {
+            sb.append(String.format("%02x", o & BYTE_MASK));
+        }
+        return sb.toString();
+    }
+
+    public static byte[] hexToBytes(String text) {
+        if ((text.length() & 1) == 1) {
+            throw new NumberFormatException("Odd length hex string: " + text.length());
+        }
+        byte[] data = new byte[text.length() >> 1];
+        int position = 0;
+        for (int n = 0; n < text.length(); n += 2) {
+            data[position] =
+                    (byte) (((fromHex(text.charAt(n), false) & NIBBLE_MASK) << 4) |
+                            (fromHex(text.charAt(n + 1), false) & NIBBLE_MASK));
+            position++;
+        }
+        return data;
+    }
+
+    public static int fromHex(char ch, boolean lenient) throws NumberFormatException {
+        if (ch <= '9' && ch >= '0') {
+            return ch - '0';
+        } else if (ch >= 'a' && ch <= 'f') {
+            return ch + 10 - 'a';
+        } else if (ch <= 'F' && ch >= 'A') {
+            return ch + 10 - 'A';
+        } else if (lenient) {
+            return -1;
+        } else {
+            throw new NumberFormatException("Bad hex-character: " + ch);
+        }
+    }
+
+    private static char toAscii(int b) {
+        return b >= ' ' && b < 0x7f ? (char) b : '.';
+    }
+
+    static boolean isDecimal(String s) {
+        for (int n = 0; n < s.length(); n++) {
+            char ch = s.charAt(n);
+            if (ch < '0' || ch > '9') {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static <T extends Comparable> int compare(Comparable<T> c1, T c2) {
+        if (c1 == null) {
+            return c2 == null ? 0 : -1;
+        } else if (c2 == null) {
+            return 1;
+        } else {
+            return c1.compareTo(c2);
+        }
+    }
+
+    public static String bytesToBingoCard(ByteBuffer data, int len) {
+        ByteBuffer dup = data.duplicate();
+        dup.limit(dup.position() + len);
+        return bytesToBingoCard(dup);
+    }
+
+    public static String bytesToBingoCard(ByteBuffer data) {
+        ByteBuffer dup = data.duplicate();
+        StringBuilder sbx = new StringBuilder();
+        while (dup.hasRemaining()) {
+            sbx.append(String.format("%02x ", dup.get() & BYTE_MASK));
+        }
+        dup = data.duplicate();
+        sbx.append(' ');
+        while (dup.hasRemaining()) {
+            sbx.append(String.format("%c", toAscii(dup.get() & BYTE_MASK)));
+        }
+        return sbx.toString();
+    }
+
+    public static String toHMS(long millis) {
+        long time = millis >= 0 ? millis : -millis;
+        long tmp = time / 1000L;
+        long ms = time - tmp * 1000L;
+
+        time = tmp;
+        tmp /= 60L;
+        long s = time - tmp * 60L;
+
+        time = tmp;
+        tmp /= 60L;
+        long m = time - tmp * 60L;
+
+        return String.format("%s%d:%02d:%02d.%03d", millis < 0 ? "-" : "", tmp, m, s, ms);
+    }
+
+    public static String toUTCString(long ms) {
+        if (ms < 0) {
+            return "unset";
+        }
+        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+        c.setTimeInMillis(ms);
+        return String.format("%4d/%02d/%02d %2d:%02d:%02dZ",
+                c.get(Calendar.YEAR),
+                c.get(Calendar.MONTH) + 1,
+                c.get(Calendar.DAY_OF_MONTH),
+                c.get(Calendar.HOUR_OF_DAY),
+                c.get(Calendar.MINUTE),
+                c.get(Calendar.SECOND));
+    }
+
+    public static String unquote(String s) {
+        if (s == null) {
+            return null;
+        } else if (s.length() > 1 && s.startsWith("\"") && s.endsWith("\"")) {
+            return s.substring(1, s.length() - 1);
+        } else {
+            return s;
+        }
+    }
+
+
+    public static void delay(long ms) {
+        long until = System.currentTimeMillis() + ms;
+        for (; ; ) {
+            long remainder = until - System.currentTimeMillis();
+            if (remainder <= 0) {
+                break;
+            }
+            try {
+                Thread.sleep(remainder);
+            } catch (InterruptedException ie) { /**/ }
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/WifiNetworkAdapter.java b/packages/Osu/src/com/android/hotspot2/WifiNetworkAdapter.java
new file mode 100644
index 0000000..518e64e
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/WifiNetworkAdapter.java
@@ -0,0 +1,388 @@
+package com.android.hotspot2;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.CaptivePortal;
+import android.net.ConnectivityManager;
+import android.net.ICaptivePortal;
+import android.net.Network;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.util.Log;
+
+import com.android.configparse.ConfigBuilder;
+import com.android.hotspot2.omadm.MOManager;
+import com.android.hotspot2.omadm.MOTree;
+import com.android.hotspot2.omadm.OMAConstants;
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.OMAParser;
+import com.android.hotspot2.osu.OSUCertType;
+import com.android.hotspot2.osu.OSUInfo;
+import com.android.hotspot2.osu.OSUManager;
+import com.android.hotspot2.osu.commands.MOData;
+import com.android.hotspot2.pps.HomeSP;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class WifiNetworkAdapter {
+    private final Context mContext;
+    private final OSUManager mOSUManager;
+    private final Map<String, PasspointConfig> mPasspointConfigs = new HashMap<>();
+
+    private static class PasspointConfig {
+        private final WifiConfiguration mWifiConfiguration;
+        private final MOTree mMOTree;
+        private final HomeSP mHomeSP;
+
+        private PasspointConfig(WifiConfiguration config) throws IOException, SAXException {
+            mWifiConfiguration = config;
+            OMAParser omaParser = new OMAParser();
+            mMOTree = omaParser.parse(config.getMoTree(), OMAConstants.PPS_URN);
+            List<HomeSP> spList = MOManager.buildSPs(mMOTree);
+            if (spList.size() != 1) {
+                throw new OMAException("Expected exactly one HomeSP, got " + spList.size());
+            }
+            mHomeSP = spList.iterator().next();
+        }
+
+        public WifiConfiguration getWifiConfiguration() {
+            return mWifiConfiguration;
+        }
+
+        public HomeSP getHomeSP() {
+            return mHomeSP;
+        }
+
+        public MOTree getmMOTree() {
+            return mMOTree;
+        }
+    }
+
+    public WifiNetworkAdapter(Context context, OSUManager osuManager) {
+        mOSUManager = osuManager;
+        mContext = context;
+    }
+
+    public void initialize() {
+        loadAllSps();
+    }
+
+    public void networkConfigChange(WifiConfiguration configuration) {
+        loadAllSps();
+    }
+
+    private void loadAllSps() {
+        Log.d(OSUManager.TAG, "Loading all SPs");
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        for (WifiConfiguration config : wifiManager.getPrivilegedConfiguredNetworks()) {
+            String moTree = config.getMoTree();
+            if (moTree != null) {
+                try {
+                    mPasspointConfigs.put(config.FQDN, new PasspointConfig(config));
+                } catch (IOException | SAXException e) {
+                    Log.w(OSUManager.TAG, "Failed to parse MO: " + e);
+                }
+            }
+        }
+    }
+
+    public Collection<HomeSP> getLoadedSPs() {
+        List<HomeSP> homeSPs = new ArrayList<>();
+        for (PasspointConfig config : mPasspointConfigs.values()) {
+            homeSPs.add(config.getHomeSP());
+        }
+        return homeSPs;
+    }
+
+    public MOTree getMOTree(HomeSP homeSP) {
+        PasspointConfig config = mPasspointConfigs.get(homeSP.getFQDN());
+        return config != null ? config.getmMOTree() : null;
+    }
+
+    public void launchBrowser(URL target, Network network, URL endRedirect) {
+        Log.d(OSUManager.TAG, "Browser to " + target + ", land at " + endRedirect);
+
+        final Intent intent = new Intent(
+                ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK, network);
+        intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
+                new CaptivePortal(new ICaptivePortal.Stub() {
+                    @Override
+                    public void appResponse(int response) {
+                    }
+                }));
+        //intent.setData(Uri.parse(target.toString()));     !!! Doesn't work!
+        intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, target.toString());
+        intent.setFlags(
+                Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(intent);
+    }
+
+    public HomeSP addSP(MOTree instanceTree) throws IOException, SAXException {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        String xml = instanceTree.toXml();
+        wifiManager.addPasspointManagementObject(xml);
+        return MOManager.buildSP(xml);
+    }
+
+    public void removeSP(String fqdn) throws IOException {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+    }
+
+    public HomeSP modifySP(HomeSP homeSP, Collection<MOData> mods)
+            throws IOException {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        return null;
+    }
+
+    public Network getCurrentNetwork() {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        return wifiManager.getCurrentNetwork();
+    }
+
+    public WifiConfiguration getActiveWifiConfig() {
+        WifiInfo wifiInfo = getConnectionInfo();
+        if (wifiInfo == null) {
+            return null;
+        }
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        for (WifiConfiguration config : wifiManager.getConfiguredNetworks()) {
+            if (config.networkId == wifiInfo.getNetworkId()) {
+                return config;
+            }
+        }
+        return null;
+    }
+
+    public WifiInfo getConnectionInfo() {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        return wifiManager.getConnectionInfo();
+    }
+
+    public PasspointMatch matchProviderWithCurrentNetwork(String fqdn) {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        int ordinal = wifiManager.matchProviderWithCurrentNetwork(fqdn);
+        return ordinal >= 0 && ordinal < PasspointMatch.values().length ?
+                PasspointMatch.values()[ordinal] : null;
+    }
+
+    public WifiConfiguration getWifiConfig(HomeSP homeSP) {
+        PasspointConfig passpointConfig = mPasspointConfigs.get(homeSP.getFQDN());
+        return passpointConfig != null ? passpointConfig.getWifiConfiguration() : null;
+    }
+
+    public WifiConfiguration getActivePasspointNetwork() {
+        PasspointConfig passpointConfig = getActivePasspointConfig();
+        return passpointConfig != null ? passpointConfig.getWifiConfiguration() : null;
+    }
+
+    private PasspointConfig getActivePasspointConfig() {
+        WifiInfo wifiInfo = getConnectionInfo();
+        if (wifiInfo == null) {
+            return null;
+        }
+
+        for (PasspointConfig passpointConfig : mPasspointConfigs.values()) {
+            if (passpointConfig.getWifiConfiguration().networkId == wifiInfo.getNetworkId()) {
+                return passpointConfig;
+            }
+        }
+        return null;
+    }
+
+    public HomeSP getCurrentSP() {
+        PasspointConfig passpointConfig = getActivePasspointConfig();
+        return passpointConfig != null ? passpointConfig.getHomeSP() : null;
+    }
+
+    public void doIconQuery(long bssid, String fileName) {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        Log.d("ZXZ", String.format("Icon query for %012x '%s'", bssid, fileName));
+        wifiManager.queryPasspointIcon(bssid, fileName);
+    }
+
+    public Integer addNetwork(HomeSP homeSP, Map<OSUCertType, List<X509Certificate>> certs,
+                              PrivateKey privateKey, Network osuNetwork)
+            throws IOException, GeneralSecurityException {
+
+        List<X509Certificate> aaaTrust = certs.get(OSUCertType.AAA);
+        if (aaaTrust.isEmpty()) {
+            aaaTrust = certs.get(OSUCertType.CA);   // Get the CAs from the EST flow.
+        }
+
+        WifiConfiguration config = ConfigBuilder.buildConfig(homeSP,
+                aaaTrust.iterator().next(),
+                certs.get(OSUCertType.Client), privateKey);
+
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        int nwkId = wifiManager.addNetwork(config);
+        boolean saved = false;
+        if (nwkId >= 0) {
+            saved = wifiManager.saveConfiguration();
+        }
+        Log.d(OSUManager.TAG, "Wifi configuration " + nwkId +
+                " " + (saved ? "saved" : "not saved"));
+
+        if (saved) {
+            reconnect(osuNetwork, nwkId);
+            return nwkId;
+        } else {
+            return null;
+        }
+    }
+
+    public void updateNetwork(HomeSP homeSP, X509Certificate caCert,
+                              List<X509Certificate> clientCerts, PrivateKey privateKey)
+            throws IOException, GeneralSecurityException {
+
+        WifiConfiguration config = getWifiConfig(homeSP);
+        if (config == null) {
+            throw new IOException("Failed to find matching network config");
+        }
+        Log.d(OSUManager.TAG, "Found matching config " + config.networkId + ", updating");
+
+        WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;
+        WifiConfiguration newConfig = ConfigBuilder.buildConfig(homeSP,
+                caCert != null ? caCert : enterpriseConfig.getCaCertificate(),
+                clientCerts, privateKey);
+        newConfig.networkId = config.networkId;
+
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        wifiManager.save(newConfig, null);
+        wifiManager.saveConfiguration();
+    }
+
+    /**
+     * Connect to an OSU provisioning network. The connection should not bring down other existing
+     * connection and the network should not be made the default network since the connection
+     * is solely for sign up and is neither intended for nor likely provides access to any
+     * generic resources.
+     *
+     * @param osuInfo The OSU info object that defines the parameters for the network. An OSU
+     *                network is either an open network, or, if the OSU NAI is set, an "OSEN"
+     *                network, which is an anonymous EAP-TLS network with special keys.
+     * @param info    An opaque string that is passed on to any user notification. The string is used
+     *                for the name of the service provider.
+     * @return an Integer holding the network-id of the just added network configuration, or null
+     * if the network existed prior to this call (was not added by the OSU infrastructure).
+     * The value will be used at the end of the OSU flow to delete the network as applicable.
+     * @throws IOException Issues:
+     *                     1. The network id is not returned. addNetwork cannot be called from here since the method
+     *                     runs in the context of the app and doesn't have the appropriate permission.
+     *                     2. The connection is not immediately usable if the network was not previously selected
+     *                     manually.
+     */
+    public Integer connect(OSUInfo osuInfo, final String info) throws IOException {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = '"' + osuInfo.getSSID() + '"';
+        if (osuInfo.getOSUBssid() != 0) {
+            config.BSSID = Utils.macToString(osuInfo.getOSUBssid());
+            Log.d(OSUManager.TAG, String.format("Setting BSSID of '%s' to %012x",
+                    osuInfo.getSSID(), osuInfo.getOSUBssid()));
+        }
+
+        if (osuInfo.getOSUProvider().getOsuNai() == null) {
+            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        } else {
+            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OSEN);
+            config.allowedProtocols.set(WifiConfiguration.Protocol.OSEN);
+            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GTK_NOT_USED);
+            config.enterpriseConfig = new WifiEnterpriseConfig();
+            config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.UNAUTH_TLS);
+            config.enterpriseConfig.setIdentity(osuInfo.getOSUProvider().getOsuNai());
+            // !!! OSEN CA Cert???
+        }
+
+        int networkId = wifiManager.addNetwork(config);
+        if (wifiManager.enableNetwork(networkId, true)) {
+            return networkId;
+        } else {
+            return null;
+        }
+
+        /* sequence of addNetwork(), enableNetwork(), saveConfiguration() and reconnect()
+        wifiManager.connect(config, new WifiManager.ActionListener() {
+            @Override
+            public void onSuccess() {
+                // Connection event comes from network change intent registered in initialize
+            }
+
+            @Override
+            public void onFailure(int reason) {
+                mOSUManager.notifyUser(OSUOperationStatus.ProvisioningFailure,
+                        "Cannot connect to OSU network: " + reason, info);
+            }
+        });
+        return null;
+
+        /*
+        try {
+            int nwkID = wifiManager.addOrUpdateOSUNetwork(config);
+            if (nwkID == WifiConfiguration.INVALID_NETWORK_ID) {
+                throw new IOException("Failed to add OSU network");
+            }
+            wifiManager.enableNetwork(nwkID, false);
+            wifiManager.reconnect();
+            return nwkID;
+        }
+        catch (SecurityException se) {
+            Log.d("ZXZ", "Blah: " + se, se);
+            wifiManager.connect(config, new WifiManager.ActionListener() {
+                @Override
+                public void onSuccess() {
+                    // Connection event comes from network change intent registered in initialize
+                }
+
+                @Override
+                public void onFailure(int reason) {
+                    mOSUManager.notifyUser(OSUOperationStatus.ProvisioningFailure,
+                            "Cannot connect to OSU network: " + reason, info);
+                }
+            });
+            return null;
+        }
+        */
+    }
+
+    private void reconnect(Network osuNetwork, int newNwkId) {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        if (osuNetwork != null) {
+            wifiManager.disableNetwork(osuNetwork.netId);
+        }
+        if (newNwkId != WifiConfiguration.INVALID_NETWORK_ID) {
+            wifiManager.enableNetwork(newNwkId, true);
+        }
+    }
+
+    public void deleteNetwork(int id) {
+        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        wifiManager.disableNetwork(id);
+        wifiManager.forget(id, null);
+    }
+
+    /**
+     * Set the re-authentication hold off time for the current network
+     *
+     * @param holdoff hold off time in milliseconds
+     * @param ess     set if the hold off pertains to an ESS rather than a BSS
+     */
+    public void setHoldoffTime(long holdoff, boolean ess) {
+
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1Boolean.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Boolean.java
new file mode 100644
index 0000000..18af3b8
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Boolean.java
@@ -0,0 +1,31 @@
+package com.android.hotspot2.asn1;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+
+public class Asn1Boolean extends Asn1Object {
+    private final boolean mBoolean;
+
+    public Asn1Boolean(int tag, Asn1Class asn1Class, int length, ByteBuffer data)
+            throws DecodeException {
+        super(tag, asn1Class, false, length);
+        if (length != 1) {
+            throw new DecodeException("Boolean length != 1: " + length, data.position());
+        }
+        mBoolean = data.get() != 0;
+    }
+
+    public boolean getValue() {
+        return mBoolean;
+    }
+
+    @Override
+    public Collection<Asn1Object> getChildren() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "=" + Boolean.toString(mBoolean);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1Class.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Class.java
new file mode 100644
index 0000000..8a4d8a8
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Class.java
@@ -0,0 +1,5 @@
+package com.android.hotspot2.asn1;
+
+public enum Asn1Class {
+    Universal, Application, Context, Private
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1Constructed.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Constructed.java
new file mode 100644
index 0000000..69b65dc
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Constructed.java
@@ -0,0 +1,53 @@
+package com.android.hotspot2.asn1;
+
+import java.nio.ByteBuffer;
+import java.util.*;
+
+public class Asn1Constructed extends Asn1Object {
+    private final int mTagPosition;
+    private final List<Asn1Object> mChildren;
+
+    public Asn1Constructed(int tag, Asn1Class asn1Class, int length,
+                           ByteBuffer payload, int tagPosition) {
+        super(tag, asn1Class, true, length, payload);
+        mTagPosition = tagPosition;
+        mChildren = new ArrayList<>();
+    }
+
+    public void addChild(Asn1Object object) {
+        mChildren.add(object);
+    }
+
+    @Override
+    public Collection<Asn1Object> getChildren() {
+        return Collections.unmodifiableCollection(mChildren);
+    }
+
+    public ByteBuffer getEncoding() {
+        return getPayload(mTagPosition);
+    }
+
+    private void toString(int level, StringBuilder sb) {
+        sb.append(indent(level)).append(super.toString()).append(":\n");
+        for (Asn1Object child : mChildren) {
+            if (child.isConstructed()) {
+                ((Asn1Constructed) child).toString(level + 1, sb);
+            } else {
+                sb.append(indent(level + 1)).append(child.toString()).append('\n');
+            }
+        }
+    }
+
+    public static String indent(int level) {
+        char[] indent = new char[level * 2];
+        Arrays.fill(indent, ' ');
+        return new String(indent);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        toString(0, sb);
+        return sb.toString();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1Decoder.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Decoder.java
new file mode 100644
index 0000000..53452e7
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Decoder.java
@@ -0,0 +1,211 @@
+package com.android.hotspot2.asn1;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Asn1Decoder {
+    public static final int TAG_UNIVZERO = 0x00;
+    public static final int TAG_BOOLEAN = 0x01;
+    public static final int TAG_INTEGER = 0x02;
+    public static final int TAG_BITSTRING = 0x03;
+    public static final int TAG_OCTET_STRING = 0x04;
+    public static final int TAG_NULL = 0x05;
+    public static final int TAG_OID = 0x06;
+    public static final int TAG_ObjectDescriptor = 0x07;
+    public static final int TAG_EXTERNAL = 0x08;
+    public static final int TAG_REAL = 0x09;
+    public static final int TAG_ENUMERATED = 0x0a;
+    public static final int TAG_UTF8String = 0x0c;      // * (*) are X.509 DirectoryString's
+    public static final int TAG_RelativeOID = 0x0d;
+    public static final int TAG_SEQ = 0x10;             //   30 if constructed
+    public static final int TAG_SET = 0x11;
+    public static final int TAG_NumericString = 0x12;   //   [UNIVERSAL 18]
+    public static final int TAG_PrintableString = 0x13; // * [UNIVERSAL 19]
+    public static final int TAG_T61String = 0x14;       // * TeletexString [UNIVERSAL 20]
+    public static final int TAG_VideotexString = 0x15;  //   [UNIVERSAL 21]
+    public static final int TAG_IA5String = 0x16;       //   [UNIVERSAL 22]
+    public static final int TAG_UTCTime = 0x17;
+    public static final int TAG_GeneralizedTime = 0x18;
+    public static final int TAG_GraphicString = 0x19;   //   [UNIVERSAL 25]
+    public static final int TAG_VisibleString = 0x1a;   //   ISO64String [UNIVERSAL 26]
+    public static final int TAG_GeneralString = 0x1b;   //   [UNIVERSAL 27]
+    public static final int TAG_UniversalString = 0x1c; // * [UNIVERSAL 28]
+    public static final int TAG_BMPString = 0x1e;       // * [UNIVERSAL 30]
+
+    public static final int IntOverflow = 0xffff0000;
+    public static final int MoreBit = 0x80;
+    public static final int MoreData = 0x7f;
+    public static final int ConstructedBit = 0x20;
+    public static final int ClassShift = 6;
+    public static final int ClassMask = 0x3;
+    public static final int MoreWidth = 7;
+    public static final int ByteWidth = 8;
+    public static final int ByteMask = 0xff;
+    public static final int ContinuationTag = 31;
+
+    public static final int IndefiniteLength = -1;
+
+    private static final Map<Integer, Asn1Tag> sTagMap = new HashMap<>();
+
+    static {
+        sTagMap.put(TAG_UNIVZERO, Asn1Tag.UNIVZERO);
+        sTagMap.put(TAG_BOOLEAN, Asn1Tag.BOOLEAN);
+        sTagMap.put(TAG_INTEGER, Asn1Tag.INTEGER);
+        sTagMap.put(TAG_BITSTRING, Asn1Tag.BITSTRING);
+        sTagMap.put(TAG_OCTET_STRING, Asn1Tag.OCTET_STRING);
+        sTagMap.put(TAG_NULL, Asn1Tag.NULL);
+        sTagMap.put(TAG_OID, Asn1Tag.OID);
+        sTagMap.put(TAG_ObjectDescriptor, Asn1Tag.ObjectDescriptor);
+        sTagMap.put(TAG_EXTERNAL, Asn1Tag.EXTERNAL);
+        sTagMap.put(TAG_REAL, Asn1Tag.REAL);
+        sTagMap.put(TAG_ENUMERATED, Asn1Tag.ENUMERATED);
+        sTagMap.put(TAG_UTF8String, Asn1Tag.UTF8String);
+        sTagMap.put(TAG_RelativeOID, Asn1Tag.RelativeOID);
+        sTagMap.put(TAG_SEQ, Asn1Tag.SEQUENCE);
+        sTagMap.put(TAG_SET, Asn1Tag.SET);
+        sTagMap.put(TAG_NumericString, Asn1Tag.NumericString);
+        sTagMap.put(TAG_PrintableString, Asn1Tag.PrintableString);
+        sTagMap.put(TAG_T61String, Asn1Tag.T61String);
+        sTagMap.put(TAG_VideotexString, Asn1Tag.VideotexString);
+        sTagMap.put(TAG_IA5String, Asn1Tag.IA5String);
+        sTagMap.put(TAG_UTCTime, Asn1Tag.UTCTime);
+        sTagMap.put(TAG_GeneralizedTime, Asn1Tag.GeneralizedTime);
+        sTagMap.put(TAG_GraphicString, Asn1Tag.GraphicString);
+        sTagMap.put(TAG_VisibleString, Asn1Tag.VisibleString);
+        sTagMap.put(TAG_GeneralString, Asn1Tag.GeneralString);
+        sTagMap.put(TAG_UniversalString, Asn1Tag.UniversalString);
+        sTagMap.put(TAG_BMPString, Asn1Tag.BMPString);
+    }
+
+    public static Asn1Tag mapTag(int tag) {
+        return sTagMap.get(tag);
+    }
+
+    public static Collection<Asn1Object> decode(ByteBuffer data) throws DecodeException {
+        Asn1Constructed root =
+                new Asn1Constructed(0, null, data.remaining(), data, data.position());
+        decode(0, root);
+        return root.getChildren();
+    }
+
+    private static void decode(int level, Asn1Constructed parent) throws DecodeException {
+        ByteBuffer data = parent.getPayload();
+        while (data.hasRemaining()) {
+            int tagPosition = data.position();
+            int propMask = data.get(tagPosition) & ByteMask;
+            if (propMask == 0 && parent.isIndefiniteLength() && data.get(tagPosition + 1) == 0) {
+                parent.setEndOfData(tagPosition);
+                return;
+            }
+            Asn1Class asn1Class = Asn1Class.values()[(propMask >> ClassShift) & ClassMask];
+            boolean constructed = (propMask & ConstructedBit) != 0;
+
+            int tag = decodeTag(data);
+            int length = decodeLength(data);
+
+            if (constructed) {
+                ByteBuffer payload = peelOff(data, length);
+                Asn1Constructed root =
+                        new Asn1Constructed(tag, asn1Class, length, payload, tagPosition);
+                decode(level + 1, root);
+                if (length == IndefiniteLength) {
+                    data.position(root.getEndOfData() + 2);     // advance past '00'
+                }
+                parent.addChild(root);
+            } else {
+                if (asn1Class != Asn1Class.Universal) {
+                    parent.addChild(new Asn1Octets(tag, asn1Class, length, data));
+                } else {
+                    parent.addChild(buildScalar(tag, asn1Class, length, data));
+                }
+            }
+        }
+    }
+
+    private static ByteBuffer peelOff(ByteBuffer base, int length) {
+        ByteBuffer copy = base.duplicate();
+        if (length == IndefiniteLength) {
+            return copy;
+        }
+        copy.limit(copy.position() + length);
+        base.position(base.position() + length);
+        return copy;
+    }
+
+    private static Asn1Object buildScalar(int tag, Asn1Class asn1Class, int length, ByteBuffer data)
+            throws DecodeException {
+        switch (tag) {
+            case TAG_BOOLEAN:
+                return new Asn1Boolean(tag, asn1Class, length, data);
+            case TAG_INTEGER:
+            case TAG_ENUMERATED:
+                return new Asn1Integer(tag, asn1Class, length, data);
+            case TAG_BITSTRING:
+                int bitResidual = data.get() & ByteMask;
+                return new Asn1Octets(tag, asn1Class, length, data, bitResidual);
+            case TAG_OCTET_STRING:
+                return new Asn1Octets(tag, asn1Class, length, data);
+            case TAG_OID:
+                return new Asn1Oid(tag, asn1Class, length, data);
+            case TAG_UTF8String:
+            case TAG_NumericString:
+            case TAG_PrintableString:
+            case TAG_T61String:
+            case TAG_VideotexString:
+            case TAG_IA5String:
+            case TAG_GraphicString:
+            case TAG_VisibleString:
+            case TAG_GeneralString:
+            case TAG_UniversalString:
+            case TAG_BMPString:
+                return new Asn1String(tag, asn1Class, length, data);
+            case TAG_GeneralizedTime:
+            case TAG_UTCTime:
+                // Should really be a dedicated time object
+                return new Asn1String(tag, asn1Class, length, data);
+            default:
+                return new Asn1Octets(tag, asn1Class, length, data);
+        }
+    }
+
+    private static int decodeTag(ByteBuffer data) throws DecodeException {
+        int tag;
+        byte tag0 = data.get();
+
+        if ((tag = (tag0 & ContinuationTag)) == ContinuationTag) {
+            int tagByte;
+            tag = 0;
+            while (((tagByte = data.get() & ByteMask) & MoreBit) != 0) {
+                tag = (tag << MoreWidth) | (tagByte & MoreData);
+                if ((tag & IntOverflow) != 0)
+                    throw new DecodeException("Tag overflow", data.position());
+            }
+            tag = (tag << MoreWidth) | tagByte;
+        }
+        return tag;
+    }
+
+    private static int decodeLength(ByteBuffer data) throws DecodeException {
+        int length;
+        int lenlen = data.get() & ByteMask;
+
+        if ((lenlen & MoreBit) == 0)    // One byte encoding
+            length = lenlen;
+        else {
+            lenlen &= MoreData;
+            if (lenlen == 0) {
+                return IndefiniteLength;
+            }
+            length = 0;
+            while (lenlen-- > 0) {
+                length = (length << ByteWidth) | (data.get() & ByteMask);
+                if ((length & IntOverflow) != 0 && lenlen > 0)
+                    throw new DecodeException("Length overflow", data.position());
+            }
+        }
+        return length;
+    }
+
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1ID.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1ID.java
new file mode 100644
index 0000000..452d85c
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1ID.java
@@ -0,0 +1,19 @@
+package com.android.hotspot2.asn1;
+
+public class Asn1ID {
+    private final int mTag;
+    private final Asn1Class mClass;
+
+    public Asn1ID(int tag, Asn1Class asn1Class) {
+        mTag = tag;
+        mClass = asn1Class;
+    }
+
+    public int getTag() {
+        return mTag;
+    }
+
+    public Asn1Class getAsn1Class() {
+        return mClass;
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1Integer.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Integer.java
new file mode 100644
index 0000000..5180a4d
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Integer.java
@@ -0,0 +1,56 @@
+package com.android.hotspot2.asn1;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.util.Collection;
+
+public class Asn1Integer extends Asn1Object {
+    private static final int SignBit = 0x80;
+
+    private final long mValue;
+    private final BigInteger mBigValue;
+
+    public Asn1Integer(int tag, Asn1Class asn1Class, int length, ByteBuffer data) {
+        super(tag, asn1Class, false, length);
+
+        if (length <= 8) {
+            long value = (data.get(data.position()) & SignBit) != 0 ? -1 : 0;
+            for (int n = 0; n < length; n++) {
+                value = (value << Byte.SIZE) | data.get();
+            }
+            mValue = value;
+            mBigValue = null;
+        } else {
+            byte[] payload = new byte[length];
+            data.get(payload);
+            mValue = 0;
+            mBigValue = new BigInteger(payload);
+        }
+    }
+
+    public boolean isBigValue() {
+        return mBigValue != null;
+    }
+
+    public long getValue() {
+        return mValue;
+    }
+
+    public BigInteger getBigValue() {
+        return mBigValue;
+    }
+
+    @Override
+    public Collection<Asn1Object> getChildren() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String toString() {
+        if (isBigValue()) {
+            return super.toString() + '=' + mBigValue.toString(16);
+        } else {
+            return super.toString() + '=' + mValue;
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1Object.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Object.java
new file mode 100644
index 0000000..8137583
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Object.java
@@ -0,0 +1,88 @@
+package com.android.hotspot2.asn1;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+
+public abstract class Asn1Object {
+    private final int mTag;
+    private final Asn1Class mClass;
+    private final boolean mConstructed;
+    private final int mLength;
+    private final ByteBuffer mPayload;
+
+    protected Asn1Object(int tag, Asn1Class asn1Class, boolean constructed, int length) {
+        this(tag, asn1Class, constructed, length, null);
+    }
+
+    protected Asn1Object(int tag, Asn1Class asn1Class, boolean constructed,
+                         int length, ByteBuffer payload) {
+        mTag = tag;
+        mClass = asn1Class;
+        mConstructed = constructed;
+        mLength = length;
+        mPayload = payload != null ? payload.duplicate() : null;
+    }
+
+    public int getTag() {
+        return mTag;
+    }
+
+    public Asn1Class getAsn1Class() {
+        return mClass;
+    }
+
+    public boolean isConstructed() {
+        return mConstructed;
+    }
+
+    public boolean isIndefiniteLength() {
+        return mLength == Asn1Decoder.IndefiniteLength;
+    }
+
+    public int getLength() {
+        return mLength;
+    }
+
+    public ByteBuffer getPayload() {
+        return mPayload != null ? mPayload.duplicate() : null;
+    }
+
+    protected ByteBuffer getPayload(int position) {
+        if (mPayload == null) {
+            return null;
+        }
+        ByteBuffer encoding = mPayload.duplicate();
+        encoding.position(position);
+        return encoding;
+    }
+
+    protected void setEndOfData(int position) {
+        mPayload.limit(position);
+    }
+
+    protected int getEndOfData() {
+        return mPayload.limit();
+    }
+
+    public boolean matches(Asn1ID id) {
+        return mTag == id.getTag() && mClass == id.getAsn1Class();
+    }
+
+    public String toSimpleString() {
+        Asn1Tag tag = mClass == Asn1Class.Universal ? Asn1Decoder.mapTag(mTag) : null;
+        if (tag != null) {
+            return tag.name();
+        } else if (mClass == Asn1Class.Universal) {
+            return String.format("[%d]", mTag);
+        } else {
+            return String.format("[%s %d]", mClass, mTag);
+        }
+    }
+
+    public abstract Collection<Asn1Object> getChildren();
+
+    @Override
+    public String toString() {
+        return toSimpleString();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1Octets.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Octets.java
new file mode 100644
index 0000000..1e19953
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Octets.java
@@ -0,0 +1,47 @@
+package com.android.hotspot2.asn1;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+
+public class Asn1Octets extends Asn1Object {
+    private final byte[] mOctets;
+    private final int mBitResidual;
+
+    public Asn1Octets(int tag, Asn1Class asn1Class, int length, ByteBuffer data) {
+        super(tag, asn1Class, false, length);
+        mOctets = new byte[length];
+        data.get(mOctets);
+        mBitResidual = -1;
+    }
+
+    public Asn1Octets(int tag, Asn1Class asn1Class, int length, ByteBuffer data, int bitResidual) {
+        super(tag, asn1Class, false, length);
+        mOctets = new byte[length - 1];
+        data.get(mOctets);
+        mBitResidual = bitResidual;
+    }
+
+    public byte[] getOctets() {
+        return mOctets;
+    }
+
+    @Override
+    public Collection<Asn1Object> getChildren() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : mOctets) {
+            sb.append(String.format(" %02x", b & Asn1Decoder.ByteMask));
+        }
+        if (mBitResidual >= 0) {
+            return super.toString() + '=' + sb + '/' + mBitResidual;
+        } else if (getTag() == Asn1Decoder.TAG_NULL && getLength() == 0) {
+            return super.toString();
+        } else {
+            return super.toString() + '=' + sb;
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1Oid.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Oid.java
new file mode 100644
index 0000000..50f0553
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Oid.java
@@ -0,0 +1,212 @@
+package com.android.hotspot2.asn1;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Asn1Oid extends Asn1Object {
+    public static final int OidMaxOctet1 = 2;
+    public static final int OidOctet1Modulus = 40;
+
+    private final List<Long> mArcs;
+    private final int mHashcode;
+
+    private static final Map<Asn1Oid, String> sOidMap = new HashMap<>();
+
+    public Asn1Oid(int tag, Asn1Class asn1Class, int length, ByteBuffer data)
+            throws DecodeException {
+        super(tag, asn1Class, false, length);
+
+        if (length == 0)
+            throw new DecodeException("oid-encoding length is zero", data.position());
+
+        mArcs = new ArrayList<>();
+
+        ByteBuffer payload = data.duplicate();
+        payload.limit(payload.position() + length);
+        data.position(data.position() + length);
+
+        byte current = payload.get();
+        long seg01 = current & Asn1Decoder.ByteMask;
+        long segValue = seg01 / OidOctet1Modulus;
+        int hashcode = (int) segValue;
+        mArcs.add(segValue);
+        segValue = seg01 - segValue * OidOctet1Modulus;
+        hashcode = hashcode * 31 + (int) segValue;
+        mArcs.add(segValue);
+
+        current = 0;
+        segValue = 0L;
+
+        while (payload.hasRemaining()) {
+            current = payload.get();
+            segValue |= current & Asn1Decoder.MoreData;
+            if ((current & Asn1Decoder.MoreBit) == 0) {
+                hashcode = hashcode * 31 + (int) segValue;
+                mArcs.add(segValue);
+                segValue = 0L;
+            } else
+                segValue <<= Asn1Decoder.MoreWidth;
+        }
+        if ((current & Asn1Decoder.MoreBit) != 0)
+            throw new DecodeException("Illegal (end of) oid-encoding", payload.position());
+        mHashcode = hashcode;
+    }
+
+    public Asn1Oid(Long... arcs) {
+        super(Asn1Decoder.TAG_OID, Asn1Class.Universal, false, -1);
+        mArcs = Arrays.asList(arcs);
+        int hashcode = 0;
+        for (long arc : arcs) {
+            hashcode = hashcode * 31 + (int) arc;
+        }
+        mHashcode = hashcode;
+    }
+
+    @Override
+    public int hashCode() {
+        return mHashcode;
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        return !(thatObject == null || thatObject.getClass() != Asn1Oid.class) &&
+                mArcs.equals(((Asn1Oid) thatObject).mArcs);
+    }
+
+    public String toOIDString() {
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (long arc : mArcs) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append('.');
+            }
+            sb.append(arc);
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(toOIDString());
+        String name = sOidMap.get(this);
+        if (name != null) {
+            sb.append(" (").append(name).append(')');
+        }
+        return super.toString() + '=' + sb.toString();
+    }
+
+    @Override
+    public Collection<Asn1Object> getChildren() {
+        throw new UnsupportedOperationException();
+    }
+
+    public static final Asn1Oid PKCS7Data = new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 7L, 1L);
+    public static final Asn1Oid PKCS7SignedData = new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 7L, 2L);
+    // encoded as an IA5STRING type
+    public static final Asn1Oid OidMacAddress = new Asn1Oid(1L, 3L, 6L, 1L, 1L, 1L, 1L, 22L);
+    // encoded as an IA5STRING type
+    public static final Asn1Oid OidImei = new Asn1Oid(1L, 3L, 6L, 1L, 4L, 1L, 40808L, 1L, 1L, 3L);
+    // encoded as a BITSTRING type
+    public static final Asn1Oid OidMeid = new Asn1Oid(1L, 3L, 6L, 1L, 4L, 1L, 40808L, 1L, 1L, 4L);
+    // encoded as a PRINTABLESTRING type
+    public static final Asn1Oid OidDevId = new Asn1Oid(1L, 3L, 6L, 1L, 4L, 1L, 40808L, 1L, 1L, 5L);
+
+    //sOidMap.put(new Asn1Oid(1L, 2L, 840L, 10040L, 4L, 1L), "algo_id_dsa");
+    //sOidMap.put(new Asn1Oid(1L, 2L, 840L, 10040L, 4L, 3L), "algo_id_dsawithsha1");
+    //sOidMap.put(new Asn1Oid(1L, 2L, 840L, 10045L, 2L, 1L), "algo_id_ecPublicKey");
+    //sOidMap.put(new Asn1Oid(1L, 2L, 840L, 10045L, 4L, 3L, 3L), "eccdaWithSHA384");
+    //sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 1L), "algo_id_rsaEncryption");
+    //sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 2L), "algo_id_md2WithRSAEncryption");
+    //sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 4L), "algo_id_md5WithRSAEncryption");
+    //sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 5L), "algo_id_sha1WithRSAEncryption");
+    //sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 11L),
+    // "algo_id_sha256WithRSAEncryption");
+
+    static {
+        sOidMap.put(new Asn1Oid(0L, 0L), "NullOid");
+        sOidMap.put(new Asn1Oid(0L, 9L, 2342L, 19200300L, 100L, 1L, 25L), "domComp");
+
+        sOidMap.put(OidMacAddress, "mac-address");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 10040L, 4L, 1L), "algo_id_dsa");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 10040L, 4L, 3L), "algo_id_dsawithsha1");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 10045L, 2L, 1L), "algo_id_ecPublicKey");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 10045L, 4L, 3L, 3L), "eccdaWithSHA384");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 10046L, 2L, 1L), "algo_id_dhpublicnumber");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 1L), "algo_id_rsaEncryption");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 2L), "algo_id_md2WithRSAEncryption");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 4L), "algo_id_md5WithRSAEncryption");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 5L),
+                "algo_id_sha1WithRSAEncryption");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 11L),
+                "algo_id_sha256WithRSAEncryption");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 7L), "pkcs7");
+        sOidMap.put(PKCS7Data, "pkcs7-data");
+        sOidMap.put(PKCS7SignedData, "pkcs7-signedData");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 9L, 1L), "emailAddress");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 9L, 7L), "challengePassword");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 9L, 14L), "extensionRequest");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 3L, 2L), "algo_id_RC2_CBC");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 3L, 4L), "algo_id_RC4_ENC");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 3L, 7L), "algo_id_DES_EDE3_CBC");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 3L, 9L), "algo_id_RC5_CBC_PAD");
+        sOidMap.put(new Asn1Oid(1L, 2L, 840L, 113549L, 3L, 10L), "algo_id_desCDMF");
+        sOidMap.put(new Asn1Oid(1L, 3L, 6L, 1L, 4L, 1L, 40808L, 1L, 1L, 2L), "id-kp-HS2.0Auth");
+        sOidMap.put(OidImei, "imei");
+        sOidMap.put(OidMeid, "meid");
+        sOidMap.put(OidDevId, "DevId");
+        sOidMap.put(new Asn1Oid(1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 1L),
+                "certAuthorityInfoAccessSyntax");
+        sOidMap.put(new Asn1Oid(1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 11L),
+                "certSubjectInfoAccessSyntax");
+        sOidMap.put(new Asn1Oid(1L, 3L, 14L, 3L, 2L, 26L), "algo_id_SHA1");
+        sOidMap.put(new Asn1Oid(1L, 3L, 132L, 0L, 34L), "secp384r1");
+
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 3L), "x500_CN");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 4L), "x500_SN");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 5L), "x500_serialNum");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 6L), "x500_C");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 7L), "x500_L");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 8L), "x500_ST");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 9L), "x500_STREET");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 10L), "x500_O");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 11L), "x500_OU");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 12L), "x500_title");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 13L), "x500_description");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 17L), "x500_postalCode");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 18L), "x500_poBox");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 20L), "x500_phone");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 41L), "x500_name");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 42L), "x500_givenName");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 44L), "x500_genQual");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 43L), "x500_initials");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 46L), "x500_dnQualifier");
+        sOidMap.put(new Asn1Oid(2L, 5L, 4L, 65L), "x500_pseudonym");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 9L), "certSubjectDirectoryAttributes");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 14L), "certSubjectKeyIdentifier ");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 15L), "certKeyUsage");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 16L), "certPrivateKeyUsagePeriod");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 17L), "certSubjectAltName");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 18L), "certIssuerAltName");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 19L), "certBasicConstraints");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 30L), "certNameConstraints");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 31L), "certCRLDistributionPoints");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 32L), "certificatePolicies");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 33L), "certPolicyMappings");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 35L), "certAuthorityKeyIdentifier ");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 36L), "certPolicyConstraints");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 37L), "certExtKeyUsageSyntax");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 46L), "certFreshestCRL");
+        sOidMap.put(new Asn1Oid(2L, 5L, 29L, 54L), "certInhibitAnyPolicy");
+        sOidMap.put(new Asn1Oid(2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 2L), "algo_id_aes128");
+        sOidMap.put(new Asn1Oid(2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 22L), "algo_id_aes192");
+        sOidMap.put(new Asn1Oid(2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 42L), "algo_id_aes256");
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1String.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1String.java
new file mode 100644
index 0000000..37ed2b2
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1String.java
@@ -0,0 +1,34 @@
+package com.android.hotspot2.asn1;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+
+public class Asn1String extends Asn1Object {
+    private final String mString;
+
+    public Asn1String(int tag, Asn1Class asn1Class, int length, ByteBuffer data) {
+        super(tag, asn1Class, false, length);
+
+        byte[] octets = new byte[length];
+        data.get(octets);
+        Charset charset = tag == Asn1Decoder.TAG_UTF8String
+                ? StandardCharsets.UTF_8 : StandardCharsets.ISO_8859_1;
+        mString = new String(octets, charset);
+    }
+
+    public String getString() {
+        return mString;
+    }
+
+    @Override
+    public Collection<Asn1Object> getChildren() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "='" + mString + '\'';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/Asn1Tag.java b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Tag.java
new file mode 100644
index 0000000..8129481
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/Asn1Tag.java
@@ -0,0 +1,31 @@
+package com.android.hotspot2.asn1;
+
+public enum Asn1Tag {
+    UNIVZERO,
+    BOOLEAN,
+    INTEGER,
+    BITSTRING,
+    OCTET_STRING,
+    NULL,
+    OID,
+    ObjectDescriptor,
+    EXTERNAL,
+    REAL,
+    ENUMERATED,
+    UTF8String,
+    RelativeOID,
+    SEQUENCE,
+    SET,
+    NumericString,
+    PrintableString,
+    T61String,
+    VideotexString,
+    IA5String,
+    UTCTime,
+    GeneralizedTime,
+    GraphicString,
+    VisibleString,
+    GeneralString,
+    UniversalString,
+    BMPString
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/DecodeException.java b/packages/Osu/src/com/android/hotspot2/asn1/DecodeException.java
new file mode 100644
index 0000000..1f10ee4
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/DecodeException.java
@@ -0,0 +1,17 @@
+package com.android.hotspot2.asn1;
+
+import java.io.IOException;
+
+public class DecodeException extends IOException {
+    private final int mOffset;
+
+    public DecodeException(String message, int offset) {
+        super(message);
+        mOffset = offset;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + " at " + mOffset;
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/asn1/OidMappings.java b/packages/Osu/src/com/android/hotspot2/asn1/OidMappings.java
new file mode 100644
index 0000000..01a6fd6
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/asn1/OidMappings.java
@@ -0,0 +1,197 @@
+package com.android.hotspot2.asn1;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class OidMappings {
+    public static class SigEntry {
+        private final String mSigAlgo;
+        private final Asn1Oid mKeyAlgo;
+
+        private SigEntry(String sigAlgo, Asn1Oid keyAlgo) {
+            mSigAlgo = sigAlgo;
+            mKeyAlgo = keyAlgo;
+        }
+
+        public String getSigAlgo() {
+            return mSigAlgo;
+        }
+
+        public Asn1Oid getKeyAlgo() {
+            return mKeyAlgo;
+        }
+    }
+
+    public static final String IdPeLogotype = "1.3.6.1.5.5.7.1.12";
+    public static final String IdCeSubjectAltName = "2.5.29.17";
+
+    private static final Map<Asn1Oid, String> sCryptoMapping = new HashMap<>();
+    private static final Map<Asn1Oid, String> sNameMapping = new HashMap<>();
+    private static final Set<Asn1Oid> sIDMapping = new HashSet<>();
+    private static final Map<Asn1Oid, SigEntry> sSigAlgos = new HashMap<>();
+
+    // DSA
+    private static final Asn1Oid sAlgo_DSA = new Asn1Oid(1L, 2L, 840L, 10040L, 4L, 1L);
+    private static final Asn1Oid sAlgo_SHA1withDSA = new Asn1Oid(1L, 2L, 840L, 10040L, 4L, 3L);
+
+    // RSA
+    public static final Asn1Oid sAlgo_RSA = new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 1L);
+    private static final Asn1Oid sAlgo_MD2withRSA = new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 2L);
+    private static final Asn1Oid sAlgo_MD5withRSA = new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 4L);
+    private static final Asn1Oid sAlgo_SHA1withRSA = new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 5L);
+    private static final Asn1Oid sAlgo_SHA224withRSA =
+            new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 14L);   // n/a
+    private static final Asn1Oid sAlgo_SHA256withRSA =
+            new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 11L);
+    private static final Asn1Oid sAlgo_SHA384withRSA =
+            new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 12L);
+    private static final Asn1Oid sAlgo_SHA512withRSA =
+            new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 1L, 13L);
+
+    // ECC
+    public static final Asn1Oid sAlgo_EC = new Asn1Oid(1L, 2L, 840L, 10045L, 2L, 1L);
+    private static final Asn1Oid sAlgo_SHA1withECDSA = new Asn1Oid(1L, 2L, 840L, 10045L, 4L, 1L);
+    private static final Asn1Oid sAlgo_SHA224withECDSA =
+            new Asn1Oid(1L, 2L, 840L, 10045L, 4L, 3L, 1L);     // n/a
+    private static final Asn1Oid sAlgo_SHA256withECDSA =
+            new Asn1Oid(1L, 2L, 840L, 10045L, 4L, 3L, 2L);
+    private static final Asn1Oid sAlgo_SHA384withECDSA =
+            new Asn1Oid(1L, 2L, 840L, 10045L, 4L, 3L, 3L);
+    private static final Asn1Oid sAlgo_SHA512withECDSA =
+            new Asn1Oid(1L, 2L, 840L, 10045L, 4L, 3L, 4L);
+
+    private static final Asn1Oid sAlgo_MD2 = new Asn1Oid(1L, 2L, 840L, 113549L, 2L, 2L);
+    private static final Asn1Oid sAlgo_MD5 = new Asn1Oid(1L, 2L, 840L, 113549L, 2L, 5L);
+    private static final Asn1Oid sAlgo_SHA1 = new Asn1Oid(1L, 3L, 14L, 3L, 2L, 26L);
+    private static final Asn1Oid sAlgo_SHA256 =
+            new Asn1Oid(2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 1L);
+    private static final Asn1Oid sAlgo_SHA384 =
+            new Asn1Oid(2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 2L);
+    private static final Asn1Oid sAlgo_SHA512 =
+            new Asn1Oid(2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 3L);
+
+    // HS2.0 stuff:
+    public static final Asn1Oid sPkcs9AtChallengePassword =
+            new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 9L, 7L);
+    public static final Asn1Oid sExtensionRequest = new Asn1Oid(1L, 2L, 840L, 113549L, 1L, 9L, 14L);
+
+    public static final Asn1Oid sMAC = new Asn1Oid(1L, 3L, 6L, 1L, 1L, 1L, 1L, 22L);
+    public static final Asn1Oid sIMEI = new Asn1Oid(1L, 3L, 6L, 1L, 4L, 1L, 40808L, 1L, 1L, 3L);
+    public static final Asn1Oid sMEID = new Asn1Oid(1L, 3L, 6L, 1L, 4L, 1L, 40808L, 1L, 1L, 4L);
+    public static final Asn1Oid sDevID = new Asn1Oid(1L, 3L, 6L, 1L, 4L, 1L, 40808L, 1L, 1L, 5L);
+
+    public static final Asn1Oid sIdWfaHotspotFriendlyName =
+            new Asn1Oid(1L, 3L, 6L, 1L, 4L, 1L, 40808L, 1L, 1L, 1L);
+
+    static {
+        sCryptoMapping.put(sAlgo_DSA, "DSA");
+        sCryptoMapping.put(sAlgo_RSA, "RSA");
+        sCryptoMapping.put(sAlgo_EC, "EC");
+
+        sSigAlgos.put(sAlgo_SHA1withDSA, new SigEntry("SHA1withDSA", sAlgo_DSA));
+
+        sSigAlgos.put(sAlgo_MD2withRSA, new SigEntry("MD2withRSA", sAlgo_RSA));
+        sSigAlgos.put(sAlgo_MD5withRSA, new SigEntry("MD5withRSA", sAlgo_RSA));
+        sSigAlgos.put(sAlgo_SHA1withRSA, new SigEntry("SHA1withRSA", sAlgo_RSA));
+        sSigAlgos.put(sAlgo_SHA224withRSA, new SigEntry(null, sAlgo_RSA));
+        sSigAlgos.put(sAlgo_SHA256withRSA, new SigEntry("SHA256withRSA", sAlgo_RSA));
+        sSigAlgos.put(sAlgo_SHA384withRSA, new SigEntry("SHA384withRSA", sAlgo_RSA));
+        sSigAlgos.put(sAlgo_SHA512withRSA, new SigEntry("SHA512withRSA", sAlgo_RSA));
+
+        sSigAlgos.put(sAlgo_SHA1withECDSA, new SigEntry("SHA1withECDSA", sAlgo_EC));
+        sSigAlgos.put(sAlgo_SHA224withECDSA, new SigEntry(null, sAlgo_EC));
+        sSigAlgos.put(sAlgo_SHA256withECDSA, new SigEntry("SHA256withECDSA", sAlgo_EC));
+        sSigAlgos.put(sAlgo_SHA384withECDSA, new SigEntry("SHA384withECDSA", sAlgo_EC));
+        sSigAlgos.put(sAlgo_SHA512withECDSA, new SigEntry("SHA512withECDSA", sAlgo_EC));
+
+        sIDMapping.add(sMAC);
+        sIDMapping.add(sIMEI);
+        sIDMapping.add(sMEID);
+        sIDMapping.add(sDevID);
+
+        for (Map.Entry<Asn1Oid, String> entry : sCryptoMapping.entrySet()) {
+            sNameMapping.put(entry.getKey(), entry.getValue());
+        }
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 1L), "sect163k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 2L), "sect163r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 3L), "sect239k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 4L), "sect113r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 5L), "sect113r2");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 6L), "secp112r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 7L), "secp112r2");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 8L), "secp160r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 9L), "secp160k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 10L), "secp256k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 15L), "sect163r2");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 16L), "sect283k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 17L), "sect283r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 22L), "sect131r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 23L), "sect131r2");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 24L), "sect193r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 25L), "sect193r2");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 26L), "sect233k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 27L), "sect233r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 28L), "secp128r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 29L), "secp128r2");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 30L), "secp160r2");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 31L), "secp192k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 32L), "secp224k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 33L), "secp224r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 34L), "secp384r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 35L), "secp521r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 36L), "sect409k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 37L), "sect409r1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 38L), "sect571k1");
+        sNameMapping.put(new Asn1Oid(1L, 3L, 132L, 0L, 39L), "sect571r1");
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 1L, 1L), "secp192r1");
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 1L, 7L), "secp256r1");
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 1L, 2L), "prime192v2");    // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 1L, 3L), "prime192v3");    // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 1L, 4L), "prime239v1");    // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 1L, 5L), "prime239v2");    // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 1L, 6L), "prime239v3");    // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 0L, 5L), "c2tnb191v1");    // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 0L, 6L), "c2tnb191v2");    // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 0L, 7L), "c2tnb191v3");    // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 0L, 11L), "c2tnb239v1");   // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 0L, 12L), "c2tnb239v2");   // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 0L, 13L), "c2tnb239v3");   // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 0L, 18L), "c2tnb359v1");   // X9.62
+        sNameMapping.put(new Asn1Oid(1L, 2L, 840L, 10045L, 3L, 0L, 20L), "c2tnb431r1");   // X9.62
+
+        sNameMapping.put(sAlgo_MD2, "MD2");
+        sNameMapping.put(sAlgo_MD5, "MD5");
+        sNameMapping.put(sAlgo_SHA1, "SHA-1");
+        sNameMapping.put(sAlgo_SHA256, "SHA-256");
+        sNameMapping.put(sAlgo_SHA384, "SHA-384");
+        sNameMapping.put(sAlgo_SHA512, "SHA-512");
+    }
+
+    public static SigEntry getSigEntry(Asn1Oid oid) {
+        return sSigAlgos.get(oid);
+    }
+
+    public static String getCryptoID(Asn1Oid oid) {
+        return sCryptoMapping.get(oid);
+    }
+
+    public static String getJCEName(Asn1Oid oid) {
+        return sNameMapping.get(oid);
+    }
+
+    public static String getSigAlgoName(Asn1Oid oid) {
+        SigEntry sigEntry = sSigAlgos.get(oid);
+        return sigEntry != null ? sigEntry.getSigAlgo() : null;
+    }
+
+    public static String getKeyAlgoName(Asn1Oid oid) {
+        SigEntry sigEntry = sSigAlgos.get(oid);
+        return sigEntry != null ? sNameMapping.get(sigEntry.getKeyAlgo()) : null;
+    }
+
+    public static boolean isIDAttribute(Asn1Oid oid) {
+        return sIDMapping.contains(oid);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/est/ESTHandler.java b/packages/Osu/src/com/android/hotspot2/est/ESTHandler.java
new file mode 100644
index 0000000..b305f4b
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/est/ESTHandler.java
@@ -0,0 +1,500 @@
+package com.android.hotspot2.est;
+
+import android.net.Network;
+import android.util.Base64;
+import android.util.Log;
+
+import com.android.hotspot2.OMADMAdapter;
+import com.android.hotspot2.asn1.Asn1Class;
+import com.android.hotspot2.asn1.Asn1Constructed;
+import com.android.hotspot2.asn1.Asn1Decoder;
+import com.android.hotspot2.asn1.Asn1ID;
+import com.android.hotspot2.asn1.Asn1Integer;
+import com.android.hotspot2.asn1.Asn1Object;
+import com.android.hotspot2.asn1.Asn1Oid;
+import com.android.hotspot2.asn1.OidMappings;
+import com.android.hotspot2.osu.HTTPHandler;
+import com.android.hotspot2.osu.OSUSocketFactory;
+import com.android.hotspot2.osu.commands.GetCertData;
+import com.android.hotspot2.pps.HomeSP;
+import com.android.hotspot2.utils.HTTPMessage;
+import com.android.hotspot2.utils.HTTPResponse;
+import com.android.org.bouncycastle.asn1.ASN1Encodable;
+import com.android.org.bouncycastle.asn1.ASN1EncodableVector;
+import com.android.org.bouncycastle.asn1.ASN1Set;
+import com.android.org.bouncycastle.asn1.DERBitString;
+import com.android.org.bouncycastle.asn1.DEREncodableVector;
+import com.android.org.bouncycastle.asn1.DERIA5String;
+import com.android.org.bouncycastle.asn1.DERObjectIdentifier;
+import com.android.org.bouncycastle.asn1.DERPrintableString;
+import com.android.org.bouncycastle.asn1.DERSet;
+import com.android.org.bouncycastle.asn1.x509.Attribute;
+import com.android.org.bouncycastle.jce.PKCS10CertificationRequest;
+import com.android.org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.KeyManager;
+import javax.security.auth.x500.X500Principal;
+
+//import com.android.org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+public class ESTHandler implements AutoCloseable {
+    private static final String TAG = "HS2EST";
+    private static final int MinRSAKeySize = 2048;
+
+    private static final String CACERT_PATH = "/cacerts";
+    private static final String CSR_PATH = "/csrattrs";
+    private static final String SIMPLE_ENROLL_PATH = "/simpleenroll";
+    private static final String SIMPLE_REENROLL_PATH = "/simplereenroll";
+
+    private final URL mURL;
+    private final String mUser;
+    private final byte[] mPassword;
+    private final OSUSocketFactory mSocketFactory;
+    private final OMADMAdapter mOMADMAdapter;
+
+    private final List<X509Certificate> mCACerts = new ArrayList<>();
+    private final List<X509Certificate> mClientCerts = new ArrayList<>();
+    private PrivateKey mClientKey;
+
+    public ESTHandler(GetCertData certData, Network network, OMADMAdapter omadmAdapter,
+                      KeyManager km, KeyStore ks, HomeSP homeSP, int flowType)
+            throws IOException, GeneralSecurityException {
+        mURL = new URL(certData.getServer());
+        mUser = certData.getUserName();
+        mPassword = certData.getPassword();
+        mSocketFactory = OSUSocketFactory.getSocketFactory(ks, homeSP, flowType,
+                network, mURL, km, true);
+        mOMADMAdapter = omadmAdapter;
+    }
+
+    @Override
+    public void close() throws IOException {
+    }
+
+    public List<X509Certificate> getCACerts() {
+        return mCACerts;
+    }
+
+    public List<X509Certificate> getClientCerts() {
+        return mClientCerts;
+    }
+
+    public PrivateKey getClientKey() {
+        return mClientKey;
+    }
+
+    private static String indent(int amount) {
+        char[] indent = new char[amount * 2];
+        Arrays.fill(indent, ' ');
+        return new String(indent);
+    }
+
+    public void execute(boolean reenroll) throws IOException, GeneralSecurityException {
+        URL caURL = new URL(mURL.getProtocol(), mURL.getHost(), mURL.getPort(),
+                mURL.getFile() + CACERT_PATH);
+
+        HTTPResponse response;
+        try (HTTPHandler httpHandler = new HTTPHandler(StandardCharsets.ISO_8859_1, mSocketFactory,
+                mUser, mPassword)) {
+            response = httpHandler.doGetHTTP(caURL);
+
+            if (!"application/pkcs7-mime".equals(response.getHeaders().
+                    get(HTTPMessage.ContentTypeHeader))) {
+                throw new IOException("Unexpected Content-Type: " +
+                        response.getHeaders().get(HTTPMessage.ContentTypeHeader));
+            }
+            ByteBuffer octetBuffer = response.getBinaryPayload();
+            Collection<Asn1Object> pkcs7Content1 = Asn1Decoder.decode(octetBuffer);
+            for (Asn1Object asn1Object : pkcs7Content1) {
+                Log.d(TAG, "---");
+                Log.d(TAG, asn1Object.toString());
+            }
+            Log.d(TAG, CACERT_PATH);
+
+            mCACerts.addAll(unpackPkcs7(octetBuffer));
+            for (X509Certificate certificate : mCACerts) {
+                Log.d(TAG, "CA-Cert: " + certificate.getSubjectX500Principal());
+            }
+
+            /*
+            byte[] octets = new byte[octetBuffer.remaining()];
+            octetBuffer.duplicate().get(octets);
+            for (byte b : octets) {
+                System.out.printf("%02x ", b & 0xff);
+            }
+            Log.d(TAG, );
+            */
+
+            /* + BC
+            try {
+                byte[] octets = new byte[octetBuffer.remaining()];
+                octetBuffer.duplicate().get(octets);
+                ASN1InputStream asnin = new ASN1InputStream(octets);
+                for (int n = 0; n < 100; n++) {
+                    ASN1Primitive object = asnin.readObject();
+                    if (object == null) {
+                        break;
+                    }
+                    parseObject(object, 0);
+                }
+            }
+            catch (Throwable t) {
+                t.printStackTrace();
+            }
+
+            Collection<Asn1Object> pkcs7Content = Asn1Decoder.decode(octetBuffer);
+            for (Asn1Object asn1Object : pkcs7Content) {
+                Log.d(TAG, asn1Object);
+            }
+
+            if (pkcs7Content.size() != 1) {
+                throw new IOException("Unexpected pkcs 7 container: " + pkcs7Content.size());
+            }
+
+            Asn1Constructed pkcs7Root = (Asn1Constructed) pkcs7Content.iterator().next();
+            Iterator<Asn1ID> certPath = Arrays.asList(Pkcs7CertPath).iterator();
+            Asn1Object certObject = pkcs7Root.findObject(certPath);
+            if (certObject == null || certPath.hasNext()) {
+                throw new IOException("Failed to find cert; returned object " + certObject +
+                        ", path " + (certPath.hasNext() ? "short" : "exhausted"));
+            }
+
+            ByteBuffer certOctets = certObject.getPayload();
+            if (certOctets == null) {
+                throw new IOException("No cert payload in: " + certObject);
+            }
+
+            byte[] certBytes = new byte[certOctets.remaining()];
+            certOctets.get(certBytes);
+
+            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
+            Log.d(TAG, "EST Cert: " + cert);
+            */
+
+            URL csrURL = new URL(mURL.getProtocol(), mURL.getHost(), mURL.getPort(),
+                    mURL.getFile() + CSR_PATH);
+            response = httpHandler.doGetHTTP(csrURL);
+
+            octetBuffer = response.getBinaryPayload();
+            byte[] csrData = buildCSR(octetBuffer, mOMADMAdapter, httpHandler);
+
+        /**/
+            Collection<Asn1Object> o = Asn1Decoder.decode(ByteBuffer.wrap(csrData));
+            Log.d(TAG, "CSR:");
+            Log.d(TAG, o.iterator().next().toString());
+            Log.d(TAG, "End CSR.");
+        /**/
+
+            URL enrollURL = new URL(mURL.getProtocol(), mURL.getHost(), mURL.getPort(),
+                    mURL.getFile() + (reenroll ? SIMPLE_REENROLL_PATH : SIMPLE_ENROLL_PATH));
+            String data = Base64.encodeToString(csrData, Base64.DEFAULT);
+            octetBuffer = httpHandler.exchangeBinary(enrollURL, data, "application/pkcs10");
+
+            Collection<Asn1Object> pkcs7Content2 = Asn1Decoder.decode(octetBuffer);
+            for (Asn1Object asn1Object : pkcs7Content2) {
+                Log.d(TAG, "---");
+                Log.d(TAG, asn1Object.toString());
+            }
+            mClientCerts.addAll(unpackPkcs7(octetBuffer));
+            for (X509Certificate cert : mClientCerts) {
+                Log.d(TAG, cert.toString());
+            }
+        }
+    }
+
+    private static final Asn1ID sSEQUENCE = new Asn1ID(Asn1Decoder.TAG_SEQ, Asn1Class.Universal);
+    private static final Asn1ID sCTXT0 = new Asn1ID(0, Asn1Class.Context);
+    private static final int PKCS7DataVersion = 1;
+    private static final int PKCS7SignedDataVersion = 3;
+
+    private static List<X509Certificate> unpackPkcs7(ByteBuffer pkcs7)
+            throws IOException, GeneralSecurityException {
+        Collection<Asn1Object> pkcs7Content = Asn1Decoder.decode(pkcs7);
+
+        if (pkcs7Content.size() != 1) {
+            throw new IOException("Unexpected pkcs 7 container: " + pkcs7Content.size());
+        }
+
+        Asn1Object data = pkcs7Content.iterator().next();
+        if (!data.isConstructed() || !data.matches(sSEQUENCE)) {
+            throw new IOException("Expected SEQ OF, got " + data.toSimpleString());
+        } else if (data.getChildren().size() != 2) {
+            throw new IOException("Expected content info to have two children, got " +
+                    data.getChildren().size());
+        }
+
+        Iterator<Asn1Object> children = data.getChildren().iterator();
+        Asn1Object contentType = children.next();
+        if (!contentType.equals(Asn1Oid.PKCS7SignedData)) {
+            throw new IOException("Content not PKCS7 signed data");
+        }
+        Asn1Object content = children.next();
+        if (!content.isConstructed() || !content.matches(sCTXT0)) {
+            throw new IOException("Expected [CONTEXT 0] with one child, got " +
+                    content.toSimpleString() + ", " + content.getChildren().size());
+        }
+
+        Asn1Object signedData = content.getChildren().iterator().next();
+        Map<Integer, Asn1Object> itemMap = new HashMap<>();
+        for (Asn1Object item : signedData.getChildren()) {
+            if (itemMap.put(item.getTag(), item) != null && item.getTag() != Asn1Decoder.TAG_SET) {
+                throw new IOException("Duplicate item in SignedData: " + item.toSimpleString());
+            }
+        }
+
+        Asn1Object versionObject = itemMap.get(Asn1Decoder.TAG_INTEGER);
+        if (versionObject == null || !(versionObject instanceof Asn1Integer)) {
+            throw new IOException("Bad or missing PKCS7 version: " + versionObject);
+        }
+        int pkcs7version = (int) ((Asn1Integer) versionObject).getValue();
+        Asn1Object innerContentInfo = itemMap.get(Asn1Decoder.TAG_SEQ);
+        if (innerContentInfo == null ||
+                !innerContentInfo.isConstructed() ||
+                !innerContentInfo.matches(sSEQUENCE) ||
+                innerContentInfo.getChildren().size() != 1) {
+            throw new IOException("Bad or missing PKCS7 contentInfo");
+        }
+        Asn1Object contentID = innerContentInfo.getChildren().iterator().next();
+        if (pkcs7version == PKCS7DataVersion && !contentID.equals(Asn1Oid.PKCS7Data) ||
+                pkcs7version == PKCS7SignedDataVersion && !contentID.equals(Asn1Oid.PKCS7SignedData)) {
+            throw new IOException("Inner PKCS7 content (" + contentID +
+                    ") not expected for version " + pkcs7version);
+        }
+        Asn1Object certWrapper = itemMap.get(0);
+        if (certWrapper == null || !certWrapper.isConstructed() || !certWrapper.matches(sCTXT0)) {
+            throw new IOException("Expected [CONTEXT 0], got: " + certWrapper);
+        }
+
+        List<X509Certificate> certList = new ArrayList<>(certWrapper.getChildren().size());
+        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+        for (Asn1Object certObject : certWrapper.getChildren()) {
+            ByteBuffer certOctets = ((Asn1Constructed) certObject).getEncoding();
+            if (certOctets == null) {
+                throw new IOException("No cert payload in: " + certObject);
+            }
+            byte[] certBytes = new byte[certOctets.remaining()];
+            certOctets.get(certBytes);
+
+            certList.add((X509Certificate) certFactory.
+                    generateCertificate(new ByteArrayInputStream(certBytes)));
+        }
+        return certList;
+    }
+
+    private byte[] buildCSR(ByteBuffer octetBuffer, OMADMAdapter omadmAdapter,
+                            HTTPHandler httpHandler) throws IOException, GeneralSecurityException {
+
+        //Security.addProvider(new BouncyCastleProvider());
+
+        Log.d(TAG, "/csrattrs:");
+        /*
+        byte[] octets = new byte[octetBuffer.remaining()];
+        octetBuffer.duplicate().get(octets);
+        for (byte b : octets) {
+            System.out.printf("%02x ", b & 0xff);
+        }
+        */
+        Collection<Asn1Object> csrs = Asn1Decoder.decode(octetBuffer);
+        for (Asn1Object asn1Object : csrs) {
+            Log.d(TAG, asn1Object.toString());
+        }
+
+        if (csrs.size() != 1) {
+            throw new IOException("Unexpected object count in CSR attributes response: " +
+                    csrs.size());
+        }
+        Asn1Object sequence = csrs.iterator().next();
+        if (sequence.getClass() != Asn1Constructed.class) {
+            throw new IOException("Unexpected CSR attribute container: " + sequence);
+        }
+
+        String keyAlgo = null;
+        Asn1Oid keyAlgoOID = null;
+        String sigAlgo = null;
+        String curveName = null;
+        Asn1Oid pubCrypto = null;
+        int keySize = -1;
+        Map<Asn1Oid, ASN1Encodable> idAttributes = new HashMap<>();
+
+        for (Asn1Object child : sequence.getChildren()) {
+            if (child.getTag() == Asn1Decoder.TAG_OID) {
+                Asn1Oid oid = (Asn1Oid) child;
+                OidMappings.SigEntry sigEntry = OidMappings.getSigEntry(oid);
+                if (sigEntry != null) {
+                    sigAlgo = sigEntry.getSigAlgo();
+                    keyAlgoOID = sigEntry.getKeyAlgo();
+                    keyAlgo = OidMappings.getJCEName(keyAlgoOID);
+                } else if (oid.equals(OidMappings.sPkcs9AtChallengePassword)) {
+                    byte[] tlsUnique = httpHandler.getTLSUnique();
+                    if (tlsUnique != null) {
+                        idAttributes.put(oid, new DERPrintableString(
+                                Base64.encodeToString(tlsUnique, Base64.DEFAULT)));
+                    } else {
+                        Log.w(TAG, "Cannot retrieve TLS unique channel binding");
+                    }
+                }
+            } else if (child.getTag() == Asn1Decoder.TAG_SEQ) {
+                Asn1Oid oid = null;
+                Set<Asn1Oid> oidValues = new HashSet<>();
+                List<Asn1Object> values = new ArrayList<>();
+
+                for (Asn1Object attributeSeq : child.getChildren()) {
+                    if (attributeSeq.getTag() == Asn1Decoder.TAG_OID) {
+                        oid = (Asn1Oid) attributeSeq;
+                    } else if (attributeSeq.getTag() == Asn1Decoder.TAG_SET) {
+                        for (Asn1Object value : attributeSeq.getChildren()) {
+                            if (value.getTag() == Asn1Decoder.TAG_OID) {
+                                oidValues.add((Asn1Oid) value);
+                            } else {
+                                values.add(value);
+                            }
+                        }
+                    }
+                }
+                if (oid == null) {
+                    throw new IOException("Invalid attribute, no OID");
+                }
+                if (oid.equals(OidMappings.sExtensionRequest)) {
+                    for (Asn1Oid subOid : oidValues) {
+                        if (OidMappings.isIDAttribute(subOid)) {
+                            if (subOid.equals(OidMappings.sMAC)) {
+                                idAttributes.put(subOid, new DERIA5String(omadmAdapter.getMAC()));
+                            } else if (subOid.equals(OidMappings.sIMEI)) {
+                                idAttributes.put(subOid, new DERIA5String(omadmAdapter.getImei()));
+                            } else if (subOid.equals(OidMappings.sMEID)) {
+                                idAttributes.put(subOid, new DERBitString(omadmAdapter.getMeid()));
+                            } else if (subOid.equals(OidMappings.sDevID)) {
+                                idAttributes.put(subOid,
+                                        new DERPrintableString(omadmAdapter.getDevID()));
+                            }
+                        }
+                    }
+                } else if (OidMappings.getCryptoID(oid) != null) {
+                    pubCrypto = oid;
+                    if (!values.isEmpty()) {
+                        for (Asn1Object value : values) {
+                            if (value.getTag() == Asn1Decoder.TAG_INTEGER) {
+                                keySize = (int) ((Asn1Integer) value).getValue();
+                            }
+                        }
+                    }
+                    if (oid.equals(OidMappings.sAlgo_EC)) {
+                        if (oidValues.isEmpty()) {
+                            throw new IOException("No ECC curve name provided");
+                        }
+                        for (Asn1Oid value : oidValues) {
+                            curveName = OidMappings.getJCEName(value);
+                            if (curveName != null) {
+                                break;
+                            }
+                        }
+                        if (curveName == null) {
+                            throw new IOException("Found no ECC curve for " + oidValues);
+                        }
+                    }
+                }
+            }
+        }
+
+        if (keyAlgoOID == null) {
+            throw new IOException("No public key algorithm specified");
+        }
+        if (pubCrypto != null && !pubCrypto.equals(keyAlgoOID)) {
+            throw new IOException("Mismatching key algorithms");
+        }
+
+        if (keyAlgoOID.equals(OidMappings.sAlgo_RSA)) {
+            if (keySize < MinRSAKeySize) {
+                if (keySize >= 0) {
+                    Log.i(TAG, "Upgrading suggested RSA key size from " +
+                            keySize + " to " + MinRSAKeySize);
+                }
+                keySize = MinRSAKeySize;
+            }
+        }
+
+        Log.d(TAG, String.format("pub key '%s', signature '%s', ECC curve '%s', id-atts %s",
+                keyAlgo, sigAlgo, curveName, idAttributes));
+
+        /*
+          Ruckus:
+            SEQUENCE:
+              OID=1.2.840.113549.1.1.11 (algo_id_sha256WithRSAEncryption)
+
+          RFC-7030:
+            SEQUENCE:
+              OID=1.2.840.113549.1.9.7 (challengePassword)
+              SEQUENCE:
+                OID=1.2.840.10045.2.1 (algo_id_ecPublicKey)
+                SET:
+                  OID=1.3.132.0.34 (secp384r1)
+              SEQUENCE:
+                OID=1.2.840.113549.1.9.14 (extensionRequest)
+                SET:
+                  OID=1.3.6.1.1.1.1.22 (mac-address)
+              OID=1.2.840.10045.4.3.3 (eccdaWithSHA384)
+
+              1L, 3L, 6L, 1L, 1L, 1L, 1L, 22
+         */
+
+        // ECC Does not appear to be supported currently
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgo);
+        if (curveName != null) {
+            AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(keyAlgo);
+            algorithmParameters.init(new ECNamedCurveGenParameterSpec(curveName));
+            kpg.initialize(algorithmParameters
+                    .getParameterSpec(ECNamedCurveGenParameterSpec.class));
+        } else {
+            kpg.initialize(keySize);
+        }
+        KeyPair kp = kpg.generateKeyPair();
+
+        X500Principal subject = new X500Principal("CN=Android, O=Google, C=US");
+
+        mClientKey = kp.getPrivate();
+
+        // !!! Map the idAttributes into an ASN1Set of values to pass to
+        // the PKCS10CertificationRequest - this code is using outdated BC classes and
+        // has *not* been tested.
+        ASN1Set attributes;
+        if (!idAttributes.isEmpty()) {
+            ASN1EncodableVector payload = new DEREncodableVector();
+            for (Map.Entry<Asn1Oid, ASN1Encodable> entry : idAttributes.entrySet()) {
+                DERObjectIdentifier type = new DERObjectIdentifier(entry.getKey().toOIDString());
+                ASN1Set values = new DERSet(entry.getValue());
+                Attribute attribute = new Attribute(type, values);
+                payload.add(attribute);
+            }
+            attributes = new DERSet(payload);
+        } else {
+            attributes = null;
+        }
+
+        return new PKCS10CertificationRequest(sigAlgo, subject, kp.getPublic(),
+                attributes, mClientKey).getEncoded();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/MOManager.java b/packages/Osu/src/com/android/hotspot2/omadm/MOManager.java
new file mode 100644
index 0000000..6a748cd
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/MOManager.java
@@ -0,0 +1,992 @@
+package com.android.hotspot2.omadm;
+
+import android.util.Base64;
+import android.util.Log;
+
+import com.android.anqp.eap.EAP;
+import com.android.anqp.eap.EAPMethod;
+import com.android.anqp.eap.ExpandedEAPMethod;
+import com.android.anqp.eap.InnerAuthEAP;
+import com.android.anqp.eap.NonEAPInnerAuth;
+import com.android.hotspot2.IMSIParameter;
+import com.android.hotspot2.Utils;
+import com.android.hotspot2.osu.OSUManager;
+import com.android.hotspot2.osu.commands.MOData;
+import com.android.hotspot2.pps.Credential;
+import com.android.hotspot2.pps.HomeSP;
+import com.android.hotspot2.pps.Policy;
+import com.android.hotspot2.pps.SubscriptionParameters;
+import com.android.hotspot2.pps.UpdateInfo;
+
+import org.xml.sax.SAXException;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+
+/**
+ * Handles provisioning of PerProviderSubscription data.
+ */
+public class MOManager {
+
+    public static final String TAG_AAAServerTrustRoot = "AAAServerTrustRoot";
+    public static final String TAG_AbleToShare = "AbleToShare";
+    public static final String TAG_CertificateType = "CertificateType";
+    public static final String TAG_CertSHA256Fingerprint = "CertSHA256Fingerprint";
+    public static final String TAG_CertURL = "CertURL";
+    public static final String TAG_CheckAAAServerCertStatus = "CheckAAAServerCertStatus";
+    public static final String TAG_Country = "Country";
+    public static final String TAG_CreationDate = "CreationDate";
+    public static final String TAG_Credential = "Credential";
+    public static final String TAG_CredentialPriority = "CredentialPriority";
+    public static final String TAG_DataLimit = "DataLimit";
+    public static final String TAG_DigitalCertificate = "DigitalCertificate";
+    public static final String TAG_DLBandwidth = "DLBandwidth";
+    public static final String TAG_EAPMethod = "EAPMethod";
+    public static final String TAG_EAPType = "EAPType";
+    public static final String TAG_ExpirationDate = "ExpirationDate";
+    public static final String TAG_Extension = "Extension";
+    public static final String TAG_FQDN = "FQDN";
+    public static final String TAG_FQDN_Match = "FQDN_Match";
+    public static final String TAG_FriendlyName = "FriendlyName";
+    public static final String TAG_HESSID = "HESSID";
+    public static final String TAG_HomeOI = "HomeOI";
+    public static final String TAG_HomeOIList = "HomeOIList";
+    public static final String TAG_HomeOIRequired = "HomeOIRequired";
+    public static final String TAG_HomeSP = "HomeSP";
+    public static final String TAG_IconURL = "IconURL";
+    public static final String TAG_IMSI = "IMSI";
+    public static final String TAG_InnerEAPType = "InnerEAPType";
+    public static final String TAG_InnerMethod = "InnerMethod";
+    public static final String TAG_InnerVendorID = "InnerVendorID";
+    public static final String TAG_InnerVendorType = "InnerVendorType";
+    public static final String TAG_IPProtocol = "IPProtocol";
+    public static final String TAG_MachineManaged = "MachineManaged";
+    public static final String TAG_MaximumBSSLoadValue = "MaximumBSSLoadValue";
+    public static final String TAG_MinBackhaulThreshold = "MinBackhaulThreshold";
+    public static final String TAG_NetworkID = "NetworkID";
+    public static final String TAG_NetworkType = "NetworkType";
+    public static final String TAG_Other = "Other";
+    public static final String TAG_OtherHomePartners = "OtherHomePartners";
+    public static final String TAG_Password = "Password";
+    public static final String TAG_PerProviderSubscription = "PerProviderSubscription";
+    public static final String TAG_Policy = "Policy";
+    public static final String TAG_PolicyUpdate = "PolicyUpdate";
+    public static final String TAG_PortNumber = "PortNumber";
+    public static final String TAG_PreferredRoamingPartnerList = "PreferredRoamingPartnerList";
+    public static final String TAG_Priority = "Priority";
+    public static final String TAG_Realm = "Realm";
+    public static final String TAG_RequiredProtoPortTuple = "RequiredProtoPortTuple";
+    public static final String TAG_Restriction = "Restriction";
+    public static final String TAG_RoamingConsortiumOI = "RoamingConsortiumOI";
+    public static final String TAG_SIM = "SIM";
+    public static final String TAG_SoftTokenApp = "SoftTokenApp";
+    public static final String TAG_SPExclusionList = "SPExclusionList";
+    public static final String TAG_SSID = "SSID";
+    public static final String TAG_StartDate = "StartDate";
+    public static final String TAG_SubscriptionParameters = "SubscriptionParameters";
+    public static final String TAG_SubscriptionUpdate = "SubscriptionUpdate";
+    public static final String TAG_TimeLimit = "TimeLimit";
+    public static final String TAG_TrustRoot = "TrustRoot";
+    public static final String TAG_TypeOfSubscription = "TypeOfSubscription";
+    public static final String TAG_ULBandwidth = "ULBandwidth";
+    public static final String TAG_UpdateIdentifier = "UpdateIdentifier";
+    public static final String TAG_UpdateInterval = "UpdateInterval";
+    public static final String TAG_UpdateMethod = "UpdateMethod";
+    public static final String TAG_URI = "URI";
+    public static final String TAG_UsageLimits = "UsageLimits";
+    public static final String TAG_UsageTimePeriod = "UsageTimePeriod";
+    public static final String TAG_Username = "Username";
+    public static final String TAG_UsernamePassword = "UsernamePassword";
+    public static final String TAG_VendorId = "VendorId";
+    public static final String TAG_VendorType = "VendorType";
+
+    public static final long IntervalFactor = 60000L;  // All MO intervals are in minutes
+
+    private static final DateFormat DTFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+
+    private static final Map<String, Map<String, Object>> sSelectionMap;
+
+    static {
+        DTFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+        sSelectionMap = new HashMap<>();
+
+        setSelections(TAG_FQDN_Match,
+                "exactmatch", Boolean.FALSE,
+                "includesubdomains", Boolean.TRUE);
+        setSelections(TAG_UpdateMethod,
+                "oma-dm-clientinitiated", Boolean.FALSE,
+                "spp-clientinitiated", Boolean.TRUE);
+        setSelections(TAG_Restriction,
+                "homesp", UpdateInfo.UpdateRestriction.HomeSP,
+                "roamingpartner", UpdateInfo.UpdateRestriction.RoamingPartner,
+                "unrestricted", UpdateInfo.UpdateRestriction.Unrestricted);
+    }
+
+    private static void setSelections(String key, Object... pairs) {
+        Map<String, Object> kvp = new HashMap<>();
+        sSelectionMap.put(key, kvp);
+        for (int n = 0; n < pairs.length; n += 2) {
+            kvp.put(pairs[n].toString(), pairs[n + 1]);
+        }
+    }
+
+    private final File mPpsFile;
+    private final boolean mEnabled;
+    private final Map<String, HomeSP> mSPs;
+
+    public MOManager(File ppsFile, boolean hs2enabled) {
+        mPpsFile = ppsFile;
+        mEnabled = hs2enabled;
+        mSPs = new HashMap<>();
+    }
+
+    public File getPpsFile() {
+        return mPpsFile;
+    }
+
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    public boolean isConfigured() {
+        return mEnabled && !mSPs.isEmpty();
+    }
+
+    public Map<String, HomeSP> getLoadedSPs() {
+        return Collections.unmodifiableMap(mSPs);
+    }
+
+    public List<HomeSP> loadAllSPs() throws IOException {
+
+        if (!mEnabled || !mPpsFile.exists()) {
+            return Collections.emptyList();
+        }
+
+        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(mPpsFile))) {
+            MOTree moTree = MOTree.unmarshal(in);
+            mSPs.clear();
+            if (moTree == null) {
+                return Collections.emptyList();     // Empty file
+            }
+
+            List<HomeSP> sps = buildSPs(moTree);
+            if (sps != null) {
+                for (HomeSP sp : sps) {
+                    if (mSPs.put(sp.getFQDN(), sp) != null) {
+                        throw new OMAException("Multiple SPs for FQDN '" + sp.getFQDN() + "'");
+                    } else {
+                        Log.d(OSUManager.TAG, "retrieved " + sp.getFQDN() + " from PPS");
+                    }
+                }
+                return sps;
+
+            } else {
+                throw new OMAException("Failed to build HomeSP");
+            }
+        }
+    }
+
+    public static HomeSP buildSP(String xml) throws IOException, SAXException {
+        OMAParser omaParser = new OMAParser();
+        MOTree tree = omaParser.parse(xml, OMAConstants.PPS_URN);
+        List<HomeSP> spList = buildSPs(tree);
+        if (spList.size() != 1) {
+            throw new OMAException("Expected exactly one HomeSP, got " + spList.size());
+        }
+        return spList.iterator().next();
+    }
+
+    public HomeSP addSP(String xml, OSUManager osuManager) throws IOException, SAXException {
+        OMAParser omaParser = new OMAParser();
+        return addSP(omaParser.parse(xml, OMAConstants.PPS_URN), osuManager);
+    }
+
+    private static final List<String> FQDNPath = Arrays.asList(TAG_HomeSP, TAG_FQDN);
+
+    /**
+     * R1 *only* addSP method.
+     *
+     * @param homeSP
+     * @throws IOException
+     */
+    public void addSP(HomeSP homeSP, OSUManager osuManager) throws IOException {
+        if (!mEnabled) {
+            throw new IOException("HS2.0 not enabled on this device");
+        }
+        if (mSPs.containsKey(homeSP.getFQDN())) {
+            Log.d(OSUManager.TAG, "HS20 profile for " +
+                    homeSP.getFQDN() + " already exists");
+            return;
+        }
+        Log.d(OSUManager.TAG, "Adding new HS20 profile for " + homeSP.getFQDN());
+
+        OMAConstructed dummyRoot = new OMAConstructed(null, TAG_PerProviderSubscription, null);
+        buildHomeSPTree(homeSP, dummyRoot, mSPs.size() + 1);
+        try {
+            addSP(dummyRoot, osuManager);
+        } catch (FileNotFoundException fnfe) {
+            MOTree tree =
+                    MOTree.buildMgmtTree(OMAConstants.PPS_URN, OMAConstants.OMAVersion, dummyRoot);
+            // No file to load a pre-build MO tree from, create a new one and save it.
+            //MOTree tree = new MOTree(OMAConstants.PPS_URN, OMAConstants.OMAVersion, dummyRoot);
+            writeMO(tree, mPpsFile, osuManager);
+        }
+        mSPs.put(homeSP.getFQDN(), homeSP);
+    }
+
+    public HomeSP addSP(MOTree instanceTree, OSUManager osuManager) throws IOException {
+        List<HomeSP> spList = buildSPs(instanceTree);
+        if (spList.size() != 1) {
+            throw new OMAException("Expected exactly one HomeSP, got " + spList.size());
+        }
+
+        HomeSP sp = spList.iterator().next();
+        String fqdn = sp.getFQDN();
+        if (mSPs.put(fqdn, sp) != null) {
+            throw new OMAException("SP " + fqdn + " already exists");
+        }
+
+        OMAConstructed pps = (OMAConstructed) instanceTree.getRoot().
+                getChild(TAG_PerProviderSubscription);
+
+        try {
+            addSP(pps, osuManager);
+        } catch (FileNotFoundException fnfe) {
+            MOTree tree = new MOTree(instanceTree.getUrn(), instanceTree.getDtdRev(),
+                    instanceTree.getRoot());
+            writeMO(tree, mPpsFile, osuManager);
+        }
+
+        return sp;
+    }
+
+    /**
+     * Add an SP sub-tree. mo must be PPS with an immediate instance child (e.g. Cred01) and an
+     * optional UpdateIdentifier,
+     *
+     * @param mo The new MO
+     * @throws IOException
+     */
+    private void addSP(OMANode mo, OSUManager osuManager) throws IOException {
+        MOTree moTree;
+        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(mPpsFile))) {
+            moTree = MOTree.unmarshal(in);
+            moTree.getRoot().addChild(mo);
+
+                /*
+            OMAConstructed ppsRoot = (OMAConstructed)
+                    moTree.getRoot().addChild(TAG_PerProviderSubscription, "", null, null);
+            for (OMANode child : mo.getChildren()) {
+                ppsRoot.addChild(child);
+                if (!child.isLeaf()) {
+                    moTree.getRoot().addChild(child);
+                }
+                else if (child.getName().equals(TAG_UpdateIdentifier)) {
+                    OMANode currentUD = moTree.getRoot().getChild(TAG_UpdateIdentifier);
+                    if (currentUD != null) {
+                        moTree.getRoot().replaceNode(currentUD, child);
+                    }
+                    else {
+                        moTree.getRoot().addChild(child);
+                    }
+                }
+            }
+                */
+        }
+        writeMO(moTree, mPpsFile, osuManager);
+    }
+
+    private static OMAConstructed findTargetTree(MOTree moTree, String fqdn) throws OMAException {
+        OMANode pps = moTree.getRoot();
+        for (OMANode node : pps.getChildren()) {
+            OMANode instance = null;
+            if (node.getName().equals(TAG_PerProviderSubscription)) {
+                instance = getInstanceNode((OMAConstructed) node);
+            } else if (!node.isLeaf()) {
+                instance = node;
+            }
+            if (instance != null) {
+                String nodeFqdn = getString(instance.getListValue(FQDNPath.iterator()));
+                if (fqdn.equalsIgnoreCase(nodeFqdn)) {
+                    return (OMAConstructed) node;
+                    // targetTree is rooted at the PPS
+                }
+            }
+        }
+        return null;
+    }
+
+    private static OMAConstructed getInstanceNode(OMAConstructed root) throws OMAException {
+        for (OMANode child : root.getChildren()) {
+            if (!child.isLeaf()) {
+                return (OMAConstructed) child;
+            }
+        }
+        throw new OMAException("Cannot find instance node");
+    }
+
+    public HomeSP modifySP(HomeSP homeSP, Collection<MOData> mods, OSUManager osuManager)
+            throws IOException {
+
+        Log.d(OSUManager.TAG, "modifying SP: " + mods);
+        MOTree moTree;
+        int ppsMods = 0;
+        int updateIdentifier = 0;
+        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(mPpsFile))) {
+            moTree = MOTree.unmarshal(in);
+            // moTree is PPS/?/provider-data
+
+            OMAConstructed targetTree = findTargetTree(moTree, homeSP.getFQDN());
+            if (targetTree == null) {
+                throw new IOException("Failed to find PPS tree for " + homeSP.getFQDN());
+            }
+            OMAConstructed instance = getInstanceNode(targetTree);
+
+            for (MOData mod : mods) {
+                LinkedList<String> tailPath =
+                        getTailPath(mod.getBaseURI(), TAG_PerProviderSubscription);
+                OMAConstructed modRoot = mod.getMOTree().getRoot();
+                // modRoot is the MgmtTree with the actual object as a direct child
+                // (e.g. Credential)
+
+                if (tailPath.getFirst().equals(TAG_UpdateIdentifier)) {
+                    updateIdentifier = getInteger(modRoot.getChildren().iterator().next());
+                    OMANode oldUdi = targetTree.getChild(TAG_UpdateIdentifier);
+                    if (getInteger(oldUdi) != updateIdentifier) {
+                        ppsMods++;
+                    }
+                    if (oldUdi != null) {
+                        targetTree.replaceNode(oldUdi, modRoot.getChild(TAG_UpdateIdentifier));
+                    } else {
+                        targetTree.addChild(modRoot.getChild(TAG_UpdateIdentifier));
+                    }
+                } else {
+                    tailPath.removeFirst();     // Drop the instance
+                    OMANode current = instance.getListValue(tailPath.iterator());
+                    if (current == null) {
+                        throw new IOException("No previous node for " + tailPath + " in " +
+                                homeSP.getFQDN());
+                    }
+                    for (OMANode newNode : modRoot.getChildren()) {
+                        // newNode is something like Credential
+                        // current is the same existing node
+                        OMANode old = current.getParent().replaceNode(current, newNode);
+                        ppsMods++;
+                    }
+                }
+            }
+        }
+        writeMO(moTree, mPpsFile, osuManager);
+
+        if (ppsMods == 0) {
+            return null;    // HomeSP not modified.
+        }
+
+        // Return a new rebuilt HomeSP
+        List<HomeSP> sps = buildSPs(moTree);
+        if (sps != null) {
+            for (HomeSP sp : sps) {
+                if (sp.getFQDN().equals(homeSP.getFQDN())) {
+                    return sp;
+                }
+            }
+        } else {
+            throw new OMAException("Failed to build HomeSP");
+        }
+        return null;
+    }
+
+    private static LinkedList<String> getTailPath(String pathString, String rootName)
+            throws IOException {
+        String[] path = pathString.split("/");
+        int pathIndex;
+        for (pathIndex = 0; pathIndex < path.length; pathIndex++) {
+            if (path[pathIndex].equalsIgnoreCase(rootName)) {
+                pathIndex++;
+                break;
+            }
+        }
+        if (pathIndex >= path.length) {
+            throw new IOException("Bad node-path: " + pathString);
+        }
+        LinkedList<String> tailPath = new LinkedList<>();
+        while (pathIndex < path.length) {
+            tailPath.add(path[pathIndex]);
+            pathIndex++;
+        }
+        return tailPath;
+    }
+
+    public HomeSP getHomeSP(String fqdn) {
+        return mSPs.get(fqdn);
+    }
+
+    public void removeSP(String fqdn, OSUManager osuManager) throws IOException {
+        if (mSPs.remove(fqdn) == null) {
+            Log.d(OSUManager.TAG, "No HS20 profile to delete for " + fqdn);
+            return;
+        }
+
+        Log.d(OSUManager.TAG, "Deleting HS20 profile for " + fqdn);
+
+        MOTree moTree;
+        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(mPpsFile))) {
+            moTree = MOTree.unmarshal(in);
+            OMAConstructed tbd = findTargetTree(moTree, fqdn);
+            if (tbd == null) {
+                throw new IOException("Node " + fqdn + " doesn't exist in MO tree");
+            }
+            OMAConstructed pps = moTree.getRoot();
+            OMANode removed = pps.removeNode("?", tbd);
+            if (removed == null) {
+                throw new IOException("Failed to remove " + fqdn + " out of MO tree");
+            }
+        }
+        writeMO(moTree, mPpsFile, osuManager);
+        osuManager.spDeleted(fqdn);
+    }
+
+    public MOTree getMOTree(HomeSP homeSP) throws IOException {
+        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(mPpsFile))) {
+            MOTree moTree = MOTree.unmarshal(in);
+            OMAConstructed target = findTargetTree(moTree, homeSP.getFQDN());
+            if (target == null) {
+                throw new IOException("Can't find " + homeSP.getFQDN() + " in MO tree");
+            }
+            return MOTree.buildMgmtTree(OMAConstants.PPS_URN, OMAConstants.OMAVersion, target);
+        }
+    }
+
+    private static void writeMO(MOTree moTree, File f, OSUManager osuManager) throws IOException {
+        try (BufferedOutputStream out =
+                     new BufferedOutputStream(new FileOutputStream(f, false))) {
+            moTree.marshal(out);
+            out.flush();
+        }
+    }
+
+    private static String fqdnList(Collection<HomeSP> sps) {
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (HomeSP sp : sps) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(", ");
+            }
+            sb.append(sp.getFQDN());
+        }
+        return sb.toString();
+    }
+
+    private static OMANode buildHomeSPTree(HomeSP homeSP, OMAConstructed root, int instanceID)
+            throws IOException {
+        OMANode providerSubNode = root.addChild(getInstanceString(instanceID),
+                null, null, null);
+
+        // The HomeSP:
+        OMANode homeSpNode = providerSubNode.addChild(TAG_HomeSP, null, null, null);
+        if (!homeSP.getSSIDs().isEmpty()) {
+            OMAConstructed nwkIDNode =
+                    (OMAConstructed) homeSpNode.addChild(TAG_NetworkID, null, null, null);
+            int instance = 0;
+            for (Map.Entry<String, Long> entry : homeSP.getSSIDs().entrySet()) {
+                OMAConstructed inode =
+                        (OMAConstructed) nwkIDNode
+                                .addChild(getInstanceString(instance++), null, null, null);
+                inode.addChild(TAG_SSID, null, entry.getKey(), null);
+                if (entry.getValue() != null) {
+                    inode.addChild(TAG_HESSID, null,
+                            String.format("%012x", entry.getValue()), null);
+                }
+            }
+        }
+
+        homeSpNode.addChild(TAG_FriendlyName, null, homeSP.getFriendlyName(), null);
+
+        if (homeSP.getIconURL() != null) {
+            homeSpNode.addChild(TAG_IconURL, null, homeSP.getIconURL(), null);
+        }
+
+        homeSpNode.addChild(TAG_FQDN, null, homeSP.getFQDN(), null);
+
+        if (!homeSP.getMatchAllOIs().isEmpty() || !homeSP.getMatchAnyOIs().isEmpty()) {
+            OMAConstructed homeOIList =
+                    (OMAConstructed) homeSpNode.addChild(TAG_HomeOIList, null, null, null);
+
+            int instance = 0;
+            for (Long oi : homeSP.getMatchAllOIs()) {
+                OMAConstructed inode =
+                        (OMAConstructed) homeOIList.addChild(getInstanceString(instance++),
+                                null, null, null);
+                inode.addChild(TAG_HomeOI, null, String.format("%x", oi), null);
+                inode.addChild(TAG_HomeOIRequired, null, "TRUE", null);
+            }
+            for (Long oi : homeSP.getMatchAnyOIs()) {
+                OMAConstructed inode =
+                        (OMAConstructed) homeOIList.addChild(getInstanceString(instance++),
+                                null, null, null);
+                inode.addChild(TAG_HomeOI, null, String.format("%x", oi), null);
+                inode.addChild(TAG_HomeOIRequired, null, "FALSE", null);
+            }
+        }
+
+        if (!homeSP.getOtherHomePartners().isEmpty()) {
+            OMAConstructed otherPartners =
+                    (OMAConstructed) homeSpNode.addChild(TAG_OtherHomePartners, null, null, null);
+            int instance = 0;
+            for (String fqdn : homeSP.getOtherHomePartners()) {
+                OMAConstructed inode =
+                        (OMAConstructed) otherPartners.addChild(getInstanceString(instance++),
+                                null, null, null);
+                inode.addChild(TAG_FQDN, null, fqdn, null);
+            }
+        }
+
+        if (!homeSP.getRoamingConsortiums().isEmpty()) {
+            homeSpNode.addChild(TAG_RoamingConsortiumOI, null,
+                    getRCList(homeSP.getRoamingConsortiums()), null);
+        }
+
+        // The Credential:
+        OMANode credentialNode = providerSubNode.addChild(TAG_Credential, null, null, null);
+        Credential cred = homeSP.getCredential();
+        EAPMethod method = cred.getEAPMethod();
+
+        if (cred.getCtime() > 0) {
+            credentialNode.addChild(TAG_CreationDate,
+                    null, DTFormat.format(new Date(cred.getCtime())), null);
+        }
+        if (cred.getExpTime() > 0) {
+            credentialNode.addChild(TAG_ExpirationDate,
+                    null, DTFormat.format(new Date(cred.getExpTime())), null);
+        }
+
+        if (method.getEAPMethodID() == EAP.EAPMethodID.EAP_SIM
+                || method.getEAPMethodID() == EAP.EAPMethodID.EAP_AKA
+                || method.getEAPMethodID() == EAP.EAPMethodID.EAP_AKAPrim) {
+
+            OMANode simNode = credentialNode.addChild(TAG_SIM, null, null, null);
+            simNode.addChild(TAG_IMSI, null, cred.getImsi().toString(), null);
+            simNode.addChild(TAG_EAPType, null,
+                    Integer.toString(EAP.mapEAPMethod(method.getEAPMethodID())), null);
+
+        } else if (method.getEAPMethodID() == EAP.EAPMethodID.EAP_TTLS) {
+
+            OMANode unpNode = credentialNode.addChild(TAG_UsernamePassword, null, null, null);
+            unpNode.addChild(TAG_Username, null, cred.getUserName(), null);
+            unpNode.addChild(TAG_Password, null,
+                    Base64.encodeToString(cred.getPassword().getBytes(StandardCharsets.UTF_8),
+                            Base64.DEFAULT), null);
+            OMANode eapNode = unpNode.addChild(TAG_EAPMethod, null, null, null);
+            eapNode.addChild(TAG_EAPType, null,
+                    Integer.toString(EAP.mapEAPMethod(method.getEAPMethodID())), null);
+            eapNode.addChild(TAG_InnerMethod, null,
+                    ((NonEAPInnerAuth) method.getAuthParam()).getOMAtype(), null);
+
+        } else if (method.getEAPMethodID() == EAP.EAPMethodID.EAP_TLS) {
+
+            OMANode certNode = credentialNode.addChild(TAG_DigitalCertificate, null, null, null);
+            certNode.addChild(TAG_CertificateType, null, Credential.CertTypeX509, null);
+            certNode.addChild(TAG_CertSHA256Fingerprint, null,
+                    Utils.toHex(cred.getFingerPrint()), null);
+
+        } else {
+            throw new OMAException("Invalid credential on " + homeSP.getFQDN());
+        }
+
+        credentialNode.addChild(TAG_Realm, null, cred.getRealm(), null);
+
+        // !!! Note: This node defines CRL checking through OSCP, I suspect we won't be able
+        // to do that so it is commented out:
+        //credentialNode.addChild(TAG_CheckAAAServerCertStatus, null, "TRUE", null);
+        return providerSubNode;
+    }
+
+    private static String getInstanceString(int instance) {
+        return "r1i" + instance;
+    }
+
+    private static String getRCList(Collection<Long> rcs) {
+        StringBuilder builder = new StringBuilder();
+        boolean first = true;
+        for (Long roamingConsortium : rcs) {
+            if (first) {
+                first = false;
+            } else {
+                builder.append(',');
+            }
+            builder.append(String.format("%x", roamingConsortium));
+        }
+        return builder.toString();
+    }
+
+    public static List<HomeSP> buildSPs(MOTree moTree) throws OMAException {
+        OMAConstructed spList;
+        List<HomeSP> homeSPs = new ArrayList<>();
+        if (moTree.getRoot().getName().equals(TAG_PerProviderSubscription)) {
+            // The old PPS file was rooted at PPS instead of MgmtTree to conserve space
+            spList = moTree.getRoot();
+
+            if (spList == null) {
+                return homeSPs;
+            }
+
+            for (OMANode node : spList.getChildren()) {
+                if (!node.isLeaf()) {
+                    homeSPs.add(buildHomeSP(node, 0));
+                }
+            }
+        } else {
+            for (OMANode ppsRoot : moTree.getRoot().getChildren()) {
+                if (ppsRoot.getName().equals(TAG_PerProviderSubscription)) {
+                    Integer updateIdentifier = null;
+                    OMANode instance = null;
+                    for (OMANode child : ppsRoot.getChildren()) {
+                        if (child.getName().equals(TAG_UpdateIdentifier)) {
+                            updateIdentifier = getInteger(child);
+                        } else if (!child.isLeaf()) {
+                            instance = child;
+                        }
+                    }
+                    if (instance == null) {
+                        throw new OMAException("PPS node missing instance node");
+                    }
+                    homeSPs.add(buildHomeSP(instance,
+                            updateIdentifier != null ? updateIdentifier : 0));
+                }
+            }
+        }
+
+        return homeSPs;
+    }
+
+    private static HomeSP buildHomeSP(OMANode ppsRoot, int updateIdentifier) throws OMAException {
+        OMANode spRoot = ppsRoot.getChild(TAG_HomeSP);
+
+        String fqdn = spRoot.getScalarValue(Arrays.asList(TAG_FQDN).iterator());
+        String friendlyName = spRoot.getScalarValue(Arrays.asList(TAG_FriendlyName).iterator());
+        String iconURL = spRoot.getScalarValue(Arrays.asList(TAG_IconURL).iterator());
+
+        HashSet<Long> roamingConsortiums = new HashSet<>();
+        String oiString = spRoot.getScalarValue(Arrays.asList(TAG_RoamingConsortiumOI).iterator());
+        if (oiString != null) {
+            for (String oi : oiString.split(",")) {
+                roamingConsortiums.add(Long.parseLong(oi.trim(), 16));
+            }
+        }
+
+        Map<String, Long> ssids = new HashMap<>();
+
+        OMANode ssidListNode = spRoot.getListValue(Arrays.asList(TAG_NetworkID).iterator());
+        if (ssidListNode != null) {
+            for (OMANode ssidRoot : ssidListNode.getChildren()) {
+                OMANode hessidNode = ssidRoot.getChild(TAG_HESSID);
+                ssids.put(ssidRoot.getChild(TAG_SSID).getValue(), getMac(hessidNode));
+            }
+        }
+
+        Set<Long> matchAnyOIs = new HashSet<>();
+        List<Long> matchAllOIs = new ArrayList<>();
+        OMANode homeOIListNode = spRoot.getListValue(Arrays.asList(TAG_HomeOIList).iterator());
+        if (homeOIListNode != null) {
+            for (OMANode homeOIRoot : homeOIListNode.getChildren()) {
+                String homeOI = homeOIRoot.getChild(TAG_HomeOI).getValue();
+                if (Boolean.parseBoolean(homeOIRoot.getChild(TAG_HomeOIRequired).getValue())) {
+                    matchAllOIs.add(Long.parseLong(homeOI, 16));
+                } else {
+                    matchAnyOIs.add(Long.parseLong(homeOI, 16));
+                }
+            }
+        }
+
+        Set<String> otherHomePartners = new HashSet<>();
+        OMANode otherListNode =
+                spRoot.getListValue(Arrays.asList(TAG_OtherHomePartners).iterator());
+        if (otherListNode != null) {
+            for (OMANode fqdnNode : otherListNode.getChildren()) {
+                otherHomePartners.add(fqdnNode.getChild(TAG_FQDN).getValue());
+            }
+        }
+
+        Credential credential = buildCredential(ppsRoot.getChild(TAG_Credential));
+
+        OMANode policyNode = ppsRoot.getChild(TAG_Policy);
+        Policy policy = policyNode != null ? new Policy(policyNode) : null;
+
+        Map<String, String> aaaTrustRoots;
+        OMANode aaaRootNode = ppsRoot.getChild(TAG_AAAServerTrustRoot);
+        if (aaaRootNode == null) {
+            aaaTrustRoots = null;
+        } else {
+            aaaTrustRoots = new HashMap<>(aaaRootNode.getChildren().size());
+            for (OMANode child : aaaRootNode.getChildren()) {
+                aaaTrustRoots.put(getString(child, TAG_CertURL),
+                        getString(child, TAG_CertSHA256Fingerprint));
+            }
+        }
+
+        OMANode updateNode = ppsRoot.getChild(TAG_SubscriptionUpdate);
+        UpdateInfo subscriptionUpdate = updateNode != null ? new UpdateInfo(updateNode) : null;
+        OMANode subNode = ppsRoot.getChild(TAG_SubscriptionParameters);
+        SubscriptionParameters subscriptionParameters = subNode != null ?
+                new SubscriptionParameters(subNode) : null;
+
+        return new HomeSP(ssids, fqdn, roamingConsortiums, otherHomePartners,
+                matchAnyOIs, matchAllOIs, friendlyName, iconURL, credential,
+                policy, getInteger(ppsRoot.getChild(TAG_CredentialPriority), 0),
+                aaaTrustRoots, subscriptionUpdate, subscriptionParameters, updateIdentifier);
+    }
+
+    private static Credential buildCredential(OMANode credNode) throws OMAException {
+        long ctime = getTime(credNode.getChild(TAG_CreationDate));
+        long expTime = getTime(credNode.getChild(TAG_ExpirationDate));
+        String realm = getString(credNode.getChild(TAG_Realm));
+        boolean checkAAACert = getBoolean(credNode.getChild(TAG_CheckAAAServerCertStatus));
+
+        OMANode unNode = credNode.getChild(TAG_UsernamePassword);
+        OMANode certNode = credNode.getChild(TAG_DigitalCertificate);
+        OMANode simNode = credNode.getChild(TAG_SIM);
+
+        int alternatives = 0;
+        alternatives += unNode != null ? 1 : 0;
+        alternatives += certNode != null ? 1 : 0;
+        alternatives += simNode != null ? 1 : 0;
+        if (alternatives != 1) {
+            throw new OMAException("Expected exactly one credential type, got " + alternatives);
+        }
+
+        if (unNode != null) {
+            String userName = getString(unNode.getChild(TAG_Username));
+            String password = getString(unNode.getChild(TAG_Password));
+            boolean machineManaged = getBoolean(unNode.getChild(TAG_MachineManaged));
+            String softTokenApp = getString(unNode.getChild(TAG_SoftTokenApp));
+            boolean ableToShare = getBoolean(unNode.getChild(TAG_AbleToShare));
+
+            OMANode eapMethodNode = unNode.getChild(TAG_EAPMethod);
+            int eapID = getInteger(eapMethodNode.getChild(TAG_EAPType));
+
+            EAP.EAPMethodID eapMethodID = EAP.mapEAPMethod(eapID);
+            if (eapMethodID == null) {
+                throw new OMAException("Unknown EAP method: " + eapID);
+            }
+
+            Long vid = getOptionalInteger(eapMethodNode.getChild(TAG_VendorId));
+            Long vtype = getOptionalInteger(eapMethodNode.getChild(TAG_VendorType));
+            Long innerEAPType = getOptionalInteger(eapMethodNode.getChild(TAG_InnerEAPType));
+            EAP.EAPMethodID innerEAPMethod = null;
+            if (innerEAPType != null) {
+                innerEAPMethod = EAP.mapEAPMethod(innerEAPType.intValue());
+                if (innerEAPMethod == null) {
+                    throw new OMAException("Bad inner EAP method: " + innerEAPType);
+                }
+            }
+
+            Long innerVid = getOptionalInteger(eapMethodNode.getChild(TAG_InnerVendorID));
+            Long innerVtype = getOptionalInteger(eapMethodNode.getChild(TAG_InnerVendorType));
+            String innerNonEAPMethod = getString(eapMethodNode.getChild(TAG_InnerMethod));
+
+            EAPMethod eapMethod;
+            if (innerEAPMethod != null) {
+                eapMethod = new EAPMethod(eapMethodID, new InnerAuthEAP(innerEAPMethod));
+            } else if (vid != null) {
+                eapMethod = new EAPMethod(eapMethodID,
+                        new ExpandedEAPMethod(EAP.AuthInfoID.ExpandedEAPMethod,
+                                vid.intValue(), vtype));
+            } else if (innerVid != null) {
+                eapMethod =
+                        new EAPMethod(eapMethodID, new ExpandedEAPMethod(EAP.AuthInfoID
+                                .ExpandedInnerEAPMethod, innerVid.intValue(), innerVtype));
+            } else if (innerNonEAPMethod != null) {
+                eapMethod = new EAPMethod(eapMethodID, new NonEAPInnerAuth(innerNonEAPMethod));
+            } else {
+                throw new OMAException("Incomplete set of EAP parameters");
+            }
+
+            return new Credential(ctime, expTime, realm, checkAAACert, eapMethod, userName,
+                    password, machineManaged, softTokenApp, ableToShare);
+        }
+        if (certNode != null) {
+            try {
+                String certTypeString = getString(certNode.getChild(TAG_CertificateType));
+                byte[] fingerPrint = getOctets(certNode.getChild(TAG_CertSHA256Fingerprint));
+
+                EAPMethod eapMethod = new EAPMethod(EAP.EAPMethodID.EAP_TLS, null);
+
+                return new Credential(ctime, expTime, realm, checkAAACert, eapMethod,
+                        Credential.mapCertType(certTypeString), fingerPrint);
+            } catch (NumberFormatException nfe) {
+                throw new OMAException("Bad hex string: " + nfe.toString());
+            }
+        }
+        if (simNode != null) {
+            try {
+                IMSIParameter imsi = new IMSIParameter(getString(simNode.getChild(TAG_IMSI)));
+
+                EAPMethod eapMethod =
+                        new EAPMethod(EAP.mapEAPMethod(getInteger(simNode.getChild(TAG_EAPType))),
+                                null);
+
+                return new Credential(ctime, expTime, realm, checkAAACert, eapMethod, imsi);
+            } catch (IOException ioe) {
+                throw new OMAException("Failed to parse IMSI: " + ioe);
+            }
+        }
+        throw new OMAException("Missing credential parameters");
+    }
+
+    public static OMANode getChild(OMANode node, String key) throws OMAException {
+        OMANode child = node.getChild(key);
+        if (child == null) {
+            throw new OMAException("No such node: " + key);
+        }
+        return child;
+    }
+
+    public static String getString(OMANode node, String key) throws OMAException {
+        OMANode child = node.getChild(key);
+        if (child == null) {
+            throw new OMAException("Missing value for " + key);
+        } else if (!child.isLeaf()) {
+            throw new OMAException(key + " is not a leaf node");
+        }
+        return child.getValue();
+    }
+
+    public static long getLong(OMANode node, String key, Long dflt) throws OMAException {
+        OMANode child = node.getChild(key);
+        if (child == null) {
+            if (dflt != null) {
+                return dflt;
+            } else {
+                throw new OMAException("Missing value for " + key);
+            }
+        } else {
+            if (!child.isLeaf()) {
+                throw new OMAException(key + " is not a leaf node");
+            }
+            String value = child.getValue();
+            try {
+                long result = Long.parseLong(value);
+                if (result < 0) {
+                    throw new OMAException("Negative value for " + key);
+                }
+                return result;
+            } catch (NumberFormatException nfe) {
+                throw new OMAException("Value for " + key + " is non-numeric: " + value);
+            }
+        }
+    }
+
+    public static <T> T getSelection(OMANode node, String key) throws OMAException {
+        OMANode child = node.getChild(key);
+        if (child == null) {
+            throw new OMAException("Missing value for " + key);
+        } else if (!child.isLeaf()) {
+            throw new OMAException(key + " is not a leaf node");
+        }
+        return getSelection(key, child.getValue());
+    }
+
+    public static <T> T getSelection(String key, String value) throws OMAException {
+        if (value == null) {
+            throw new OMAException("No value for " + key);
+        }
+        Map<String, Object> kvp = sSelectionMap.get(key);
+        T result = (T) kvp.get(value.toLowerCase());
+        if (result == null) {
+            throw new OMAException("Invalid value '" + value + "' for " + key);
+        }
+        return result;
+    }
+
+    private static boolean getBoolean(OMANode boolNode) {
+        return boolNode != null && Boolean.parseBoolean(boolNode.getValue());
+    }
+
+    public static String getString(OMANode stringNode) {
+        return stringNode != null ? stringNode.getValue() : null;
+    }
+
+    private static int getInteger(OMANode intNode, int dflt) throws OMAException {
+        if (intNode == null) {
+            return dflt;
+        }
+        return getInteger(intNode);
+    }
+
+    private static int getInteger(OMANode intNode) throws OMAException {
+        if (intNode == null) {
+            throw new OMAException("Missing integer value");
+        }
+        try {
+            return Integer.parseInt(intNode.getValue());
+        } catch (NumberFormatException nfe) {
+            throw new OMAException("Invalid integer: " + intNode.getValue());
+        }
+    }
+
+    private static Long getMac(OMANode macNode) throws OMAException {
+        if (macNode == null) {
+            return null;
+        }
+        try {
+            return Long.parseLong(macNode.getValue(), 16);
+        } catch (NumberFormatException nfe) {
+            throw new OMAException("Invalid MAC: " + macNode.getValue());
+        }
+    }
+
+    private static Long getOptionalInteger(OMANode intNode) throws OMAException {
+        if (intNode == null) {
+            return null;
+        }
+        try {
+            return Long.parseLong(intNode.getValue());
+        } catch (NumberFormatException nfe) {
+            throw new OMAException("Invalid integer: " + intNode.getValue());
+        }
+    }
+
+    public static long getTime(OMANode timeNode) throws OMAException {
+        if (timeNode == null) {
+            return Utils.UNSET_TIME;
+        }
+        String timeText = timeNode.getValue();
+        try {
+            Date date = DTFormat.parse(timeText);
+            return date.getTime();
+        } catch (ParseException pe) {
+            throw new OMAException("Badly formatted time: " + timeText);
+        }
+    }
+
+    private static byte[] getOctets(OMANode octetNode) throws OMAException {
+        if (octetNode == null) {
+            throw new OMAException("Missing byte value");
+        }
+        return Utils.hexToBytes(octetNode.getValue());
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/MOTree.java b/packages/Osu/src/com/android/hotspot2/omadm/MOTree.java
new file mode 100644
index 0000000..93beaf4
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/MOTree.java
@@ -0,0 +1,269 @@
+package com.android.hotspot2.omadm;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class MOTree {
+    public static final String MgmtTreeTag = "MgmtTree";
+
+    public static final String NodeTag = "Node";
+    public static final String NodeNameTag = "NodeName";
+    public static final String PathTag = "Path";
+    public static final String ValueTag = "Value";
+    public static final String RTPropTag = "RTProperties";
+    public static final String TypeTag = "Type";
+    public static final String DDFNameTag = "DDFName";
+
+    private final String mUrn;
+    private final String mDtdRev;
+    private final OMAConstructed mRoot;
+
+    public MOTree(XMLNode node, String urn) throws IOException, SAXException {
+        Iterator<XMLNode> children = node.getChildren().iterator();
+
+        String dtdRev = null;
+
+        while (children.hasNext()) {
+            XMLNode child = children.next();
+            if (child.getTag().equals(OMAConstants.SyncMLVersionTag)) {
+                dtdRev = child.getText();
+                children.remove();
+                break;
+            }
+        }
+
+        mUrn = urn;
+        mDtdRev = dtdRev;
+
+        mRoot = new MgmtTreeRoot(node, dtdRev);
+
+        for (XMLNode child : node.getChildren()) {
+            buildNode(mRoot, child);
+        }
+    }
+
+    public MOTree(String urn, String rev, OMAConstructed root) throws IOException {
+        mUrn = urn;
+        mDtdRev = rev;
+        mRoot = root;
+    }
+
+    public static MOTree buildMgmtTree(String urn, String rev, OMAConstructed root)
+            throws IOException {
+        OMAConstructed realRoot;
+        switch (urn) {
+            case OMAConstants.PPS_URN:
+            case OMAConstants.DevInfoURN:
+            case OMAConstants.DevDetailURN:
+            case OMAConstants.DevDetailXURN:
+                realRoot = new OMAConstructed(null, MgmtTreeTag, urn, "xmlns", OMAConstants.SyncML);
+                realRoot.addChild(root);
+                return new MOTree(urn, rev, realRoot);
+            default:
+                return new MOTree(urn, rev, root);
+        }
+    }
+
+    public static boolean hasMgmtTreeTag(String text) {
+        for (int n = 0; n < text.length(); n++) {
+            char ch = text.charAt(n);
+            if (ch > ' ') {
+                return text.regionMatches(true, n, '<' + MgmtTreeTag + '>',
+                        0, MgmtTreeTag.length() + 2);
+            }
+        }
+        return false;
+    }
+
+    private static class NodeData {
+        private final String mName;
+        private String mPath;
+        private String mValue;
+
+        private NodeData(String name) {
+            mName = name;
+        }
+
+        private void setPath(String path) {
+            mPath = path;
+        }
+
+        private void setValue(String value) {
+            mValue = value;
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        public String getPath() {
+            return mPath;
+        }
+
+        public String getValue() {
+            return mValue;
+        }
+    }
+
+    private static void buildNode(OMANode parent, XMLNode node) throws IOException {
+        if (!node.getTag().equals(NodeTag))
+            throw new IOException("Node is a '" + node.getTag() + "' instead of a 'Node'");
+
+        Map<String, XMLNode> checkMap = new HashMap<>(3);
+        String context = null;
+        List<NodeData> values = new ArrayList<>();
+        List<XMLNode> children = new ArrayList<>();
+
+        NodeData curValue = null;
+
+        for (XMLNode child : node.getChildren()) {
+            XMLNode old = checkMap.put(child.getTag(), child);
+
+            switch (child.getTag()) {
+                case NodeNameTag:
+                    if (curValue != null)
+                        throw new IOException(NodeNameTag + " not expected");
+                    curValue = new NodeData(child.getText());
+
+                    break;
+                case PathTag:
+                    if (curValue == null || curValue.getPath() != null)
+                        throw new IOException(PathTag + " not expected");
+                    curValue.setPath(child.getText());
+
+                    break;
+                case ValueTag:
+                    if (!children.isEmpty())
+                        throw new IOException(ValueTag + " in constructed node");
+                    if (curValue == null || curValue.getValue() != null)
+                        throw new IOException(ValueTag + " not expected");
+                    curValue.setValue(child.getText());
+                    values.add(curValue);
+                    curValue = null;
+
+                    break;
+                case RTPropTag:
+                    if (old != null)
+                        throw new IOException("Duplicate " + RTPropTag);
+                    XMLNode typeNode = getNextNode(child, TypeTag);
+                    XMLNode ddfName = getNextNode(typeNode, DDFNameTag);
+                    context = ddfName.getText();
+                    if (context == null)
+                        throw new IOException("No text in " + DDFNameTag);
+
+                    break;
+                case NodeTag:
+                    if (!values.isEmpty())
+                        throw new IOException("Scalar node " + node.getText() + " has Node child");
+                    children.add(child);
+
+                    break;
+            }
+        }
+
+        if (values.isEmpty()) {
+            if (curValue == null)
+                throw new IOException("Missing name");
+
+            OMANode subNode = parent.addChild(curValue.getName(),
+                    context, null, curValue.getPath());
+
+            for (XMLNode child : children) {
+                buildNode(subNode, child);
+            }
+        } else {
+            if (!children.isEmpty())
+                throw new IOException("Got both sub nodes and value(s)");
+
+            for (NodeData nodeData : values) {
+                parent.addChild(nodeData.getName(), context,
+                        nodeData.getValue(), nodeData.getPath());
+            }
+        }
+    }
+
+    private static XMLNode getNextNode(XMLNode node, String tag) throws IOException {
+        if (node == null)
+            throw new IOException("No node for " + tag);
+        if (node.getChildren().size() != 1)
+            throw new IOException("Expected " + node.getTag() + " to have exactly one child");
+        XMLNode child = node.getChildren().iterator().next();
+        if (!child.getTag().equals(tag))
+            throw new IOException("Expected " + node.getTag() + " to have child '" + tag +
+                    "' instead of '" + child.getTag() + "'");
+        return child;
+    }
+
+    public String getUrn() {
+        return mUrn;
+    }
+
+    public String getDtdRev() {
+        return mDtdRev;
+    }
+
+    public OMAConstructed getRoot() {
+        return mRoot;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("MO Tree v").append(mDtdRev).append(", urn ").append(mUrn).append(")\n");
+        sb.append(mRoot);
+
+        return sb.toString();
+    }
+
+    public void marshal(OutputStream out) throws IOException {
+        out.write("tree ".getBytes(StandardCharsets.UTF_8));
+        OMAConstants.serializeString(mDtdRev, out);
+        out.write(String.format("(%s)\n", mUrn).getBytes(StandardCharsets.UTF_8));
+        mRoot.marshal(out, 0);
+    }
+
+    public static MOTree unmarshal(InputStream in) throws IOException {
+        boolean strip = true;
+        StringBuilder tree = new StringBuilder();
+        for (; ; ) {
+            int octet = in.read();
+            if (octet < 0) {
+                return null;
+            } else if (octet > ' ') {
+                tree.append((char) octet);
+                strip = false;
+            } else if (!strip) {
+                break;
+            }
+        }
+        if (!tree.toString().equals("tree")) {
+            throw new IOException("Not a tree: " + tree);
+        }
+
+        String version = OMAConstants.deserializeString(in);
+        int next = in.read();
+        if (next != '(') {
+            throw new IOException("Expected URN in tree definition");
+        }
+        String urn = OMAConstants.readURN(in);
+
+        OMAConstructed root = OMANode.unmarshal(in);
+
+        return new MOTree(urn, version, root);
+    }
+
+    public String toXml() {
+        StringBuilder sb = new StringBuilder();
+        mRoot.toXml(sb);
+        return sb.toString();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/MgmtTreeRoot.java b/packages/Osu/src/com/android/hotspot2/omadm/MgmtTreeRoot.java
new file mode 100644
index 0000000..97fb7cd
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/MgmtTreeRoot.java
@@ -0,0 +1,32 @@
+package com.android.hotspot2.omadm;
+
+import java.util.Map;
+
+public class MgmtTreeRoot extends OMAConstructed {
+    private final String mDtdRev;
+
+    public MgmtTreeRoot(XMLNode node, String dtdRev) {
+        super(null, MOTree.MgmtTreeTag, null, new MultiValueMap<OMANode>(),
+                node.getTextualAttributes());
+        mDtdRev = dtdRev;
+    }
+
+    @Override
+    public void toXml(StringBuilder sb) {
+        sb.append('<').append(MOTree.MgmtTreeTag);
+        if (getAttributes() != null && !getAttributes().isEmpty()) {
+            for (Map.Entry<String, String> avp : getAttributes().entrySet()) {
+                sb.append(' ').append(avp.getKey()).append("=\"")
+                        .append(avp.getValue()).append('"');
+            }
+        }
+        sb.append(">\n");
+
+        sb.append('<').append(OMAConstants.SyncMLVersionTag).append('>').append(mDtdRev)
+                .append("</").append(OMAConstants.SyncMLVersionTag).append(">\n");
+        for (OMANode child : getChildren()) {
+            child.toXml(sb);
+        }
+        sb.append("</").append(MOTree.MgmtTreeTag).append(">\n");
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/MultiValueMap.java b/packages/Osu/src/com/android/hotspot2/omadm/MultiValueMap.java
new file mode 100644
index 0000000..ead0dbc
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/MultiValueMap.java
@@ -0,0 +1,117 @@
+package com.android.hotspot2.omadm;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MultiValueMap<T> {
+    private final Map<String, ArrayList<T>> mMap = new LinkedHashMap<>();
+
+    public void put(String key, T value) {
+        key = key.toLowerCase();
+        ArrayList<T> values = mMap.get(key);
+        if (values == null) {
+            values = new ArrayList<>();
+            mMap.put(key, values);
+        }
+        values.add(value);
+    }
+
+    public T get(String key) {
+        key = key.toLowerCase();
+        List<T> values = mMap.get(key);
+        if (values == null) {
+            return null;
+        } else if (values.size() == 1) {
+            return values.get(0);
+        } else {
+            throw new IllegalArgumentException("Cannot do get on multi-value");
+        }
+    }
+
+    public T replace(String key, T oldValue, T newValue) {
+        key = key.toLowerCase();
+        List<T> values = mMap.get(key);
+        if (values == null) {
+            return null;
+        }
+
+        for (int n = 0; n < values.size(); n++) {
+            T value = values.get(n);
+            if (value == oldValue) {
+                values.set(n, newValue);
+                return value;
+            }
+        }
+        return null;
+    }
+
+    public T remove(String key, T value) {
+        key = key.toLowerCase();
+        List<T> values = mMap.get(key);
+        if (values == null) {
+            return null;
+        }
+
+        T result = null;
+        Iterator<T> valueIterator = values.iterator();
+        while (valueIterator.hasNext()) {
+            if (valueIterator.next() == value) {
+                valueIterator.remove();
+                result = value;
+                break;
+            }
+        }
+        if (values.isEmpty()) {
+            mMap.remove(key);
+        }
+        return result;
+    }
+
+    public T remove(T value) {
+        T result = null;
+        Iterator<Map.Entry<String, ArrayList<T>>> iterator = mMap.entrySet().iterator();
+        while (iterator.hasNext()) {
+            ArrayList<T> values = iterator.next().getValue();
+            Iterator<T> valueIterator = values.iterator();
+            while (valueIterator.hasNext()) {
+                if (valueIterator.next() == value) {
+                    valueIterator.remove();
+                    result = value;
+                    break;
+                }
+            }
+            if (result != null) {
+                if (values.isEmpty()) {
+                    iterator.remove();
+                }
+                break;
+            }
+        }
+        return result;
+    }
+
+    public Collection<T> values() {
+        List<T> allValues = new ArrayList<>(mMap.size());
+        for (List<T> values : mMap.values()) {
+            for (T value : values) {
+                allValues.add(value);
+            }
+        }
+        return allValues;
+    }
+
+    public T getSingletonValue() {
+        if (mMap.size() != 1) {
+            throw new IllegalArgumentException("Map is not a single entry map");
+        }
+        List<T> values = mMap.values().iterator().next();
+        if (values.size() != 1) {
+            throw new IllegalArgumentException("Map is not a single entry map");
+        }
+        return values.iterator().next();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/NodeAttribute.java b/packages/Osu/src/com/android/hotspot2/omadm/NodeAttribute.java
new file mode 100644
index 0000000..e4a08b3
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/NodeAttribute.java
@@ -0,0 +1,30 @@
+package com.android.hotspot2.omadm;
+
+public class NodeAttribute {
+    private final String mName;
+    private final String mType;
+    private final String mValue;
+
+    public NodeAttribute(String name, String type, String value) {
+        mName = name;
+        mType = type;
+        mValue = value;
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public String getValue() {
+        return mValue;
+    }
+
+    public String getType() {
+        return mType;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s (%s) = '%s'", mName, mType, mValue);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/OMAConstants.java b/packages/Osu/src/com/android/hotspot2/omadm/OMAConstants.java
new file mode 100644
index 0000000..92d8ed7
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/OMAConstants.java
@@ -0,0 +1,158 @@
+package com.android.hotspot2.omadm;
+
+import com.android.hotspot2.osu.OSUError;
+import com.android.hotspot2.osu.OSUStatus;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+
+public class OMAConstants {
+    private OMAConstants() {
+    }
+
+    public static final String MOVersion = "1.0";
+    public static final String PPS_URN = "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0";
+    public static final String DevInfoURN = "urn:oma:mo:oma-dm-devinfo:1.0";
+    public static final String DevDetailURN = "urn:oma:mo:oma-dm-devdetail:1.0";
+    public static final String DevDetailXURN = "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0";
+
+    public static final String[] SupportedMO_URNs = {
+            PPS_URN, DevInfoURN, DevDetailURN, DevDetailXURN
+    };
+
+    public static final String SppMOAttribute = "spp:moURN";
+    public static final String TAG_PostDevData = "spp:sppPostDevData";
+    public static final String TAG_SupportedVersions = "spp:supportedSPPVersions";
+    public static final String TAG_SupportedMOs = "spp:supportedMOList";
+    public static final String TAG_UpdateResponse = "spp:sppUpdateResponse";
+    public static final String TAG_MOContainer = "spp:moContainer";
+    public static final String TAG_Version = "spp:sppVersion";
+
+    public static final String TAG_SessionID = "spp:sessionID";
+    public static final String TAG_Status = "spp:sppStatus";
+    public static final String TAG_Error = "spp:sppError";
+
+    public static final String SyncMLVersionTag = "VerDTD";
+    public static final String OMAVersion = "1.2";
+    public static final String SyncML = "syncml:dmddf1.2";
+
+    private static final byte[] INDENT = new byte[1024];
+
+    private static final Map<OSUStatus, String> sStatusStrings = new EnumMap<>(OSUStatus.class);
+    private static final Map<String, OSUStatus> sStatusEnums = new HashMap<>();
+    private static final Map<OSUError, String> sErrorStrings = new EnumMap<>(OSUError.class);
+    private static final Map<String, OSUError> sErrorEnums = new HashMap<>();
+
+    static {
+        sStatusStrings.put(OSUStatus.OK, "OK");
+        sStatusStrings.put(OSUStatus.ProvComplete,
+                "Provisioning complete, request sppUpdateResponse");
+        sStatusStrings.put(OSUStatus.RemediationComplete,
+                "Remediation complete, request sppUpdateResponse");
+        sStatusStrings.put(OSUStatus.UpdateComplete, "Update complete, request sppUpdateResponse");
+        sStatusStrings.put(OSUStatus.ExchangeComplete, "Exchange complete, release TLS connection");
+        sStatusStrings.put(OSUStatus.Unknown, "No update available at this time");
+        sStatusStrings.put(OSUStatus.Error, "Error occurred");
+
+        for (Map.Entry<OSUStatus, String> entry : sStatusStrings.entrySet()) {
+            sStatusEnums.put(entry.getValue().toLowerCase(), entry.getKey());
+        }
+
+        sErrorStrings.put(OSUError.SPPversionNotSupported, "SPP version not supported");
+        sErrorStrings.put(OSUError.MOsNotSupported, "One or more mandatory MOs not supported");
+        sErrorStrings.put(OSUError.CredentialsFailure,
+                "Credentials cannot be provisioned at this time");
+        sErrorStrings.put(OSUError.RemediationFailure,
+                "Remediation cannot be completed at this time");
+        sErrorStrings.put(OSUError.ProvisioningFailed,
+                "Provisioning cannot be completed at this time");
+        sErrorStrings.put(OSUError.ExistingCertificate, "Continue to use existing certificate");
+        sErrorStrings.put(OSUError.CookieInvalid, "Cookie invalid");
+        sErrorStrings.put(OSUError.WebSessionID,
+                "No corresponding web-browser-connection Session ID");
+        sErrorStrings.put(OSUError.PermissionDenied, "Permission denied");
+        sErrorStrings.put(OSUError.CommandFailed, "Command failed");
+        sErrorStrings.put(OSUError.MOaddOrUpdateFailed, "MO addition or update failed");
+        sErrorStrings.put(OSUError.DeviceFull, "Device full");
+        sErrorStrings.put(OSUError.BadTreeURI, "Bad management tree URI");
+        sErrorStrings.put(OSUError.TooLarge, "Requested entity too large");
+        sErrorStrings.put(OSUError.CommandNotAllowed, "Command not allowed");
+        sErrorStrings.put(OSUError.UserAborted, "Command not executed due to user");
+        sErrorStrings.put(OSUError.NotFound, "Not found");
+        sErrorStrings.put(OSUError.Other, "Other");
+
+        for (Map.Entry<OSUError, String> entry : sErrorStrings.entrySet()) {
+            sErrorEnums.put(entry.getValue().toLowerCase(), entry.getKey());
+        }
+        Arrays.fill(INDENT, (byte) ' ');
+    }
+
+    public static String mapStatus(OSUStatus status) {
+        return sStatusStrings.get(status);
+    }
+
+    public static OSUStatus mapStatus(String status) {
+        return sStatusEnums.get(status.toLowerCase());
+    }
+
+    public static String mapError(OSUError error) {
+        return sErrorStrings.get(error);
+    }
+
+    public static OSUError mapError(String error) {
+        return sErrorEnums.get(error.toLowerCase());
+    }
+
+    public static void serializeString(String s, OutputStream out) throws IOException {
+        byte[] octets = s.getBytes(StandardCharsets.UTF_8);
+        byte[] prefix = String.format("%x:", octets.length).getBytes(StandardCharsets.UTF_8);
+        out.write(prefix);
+        out.write(octets);
+    }
+
+    public static void indent(int level, OutputStream out) throws IOException {
+        out.write(INDENT, 0, level);
+    }
+
+    public static String deserializeString(InputStream in) throws IOException {
+        StringBuilder prefix = new StringBuilder();
+        for (; ; ) {
+            byte b = (byte) in.read();
+            if (b == '.')
+                return null;
+            else if (b == ':')
+                break;
+            else if (b > ' ')
+                prefix.append((char) b);
+        }
+        int length = Integer.parseInt(prefix.toString(), 16);
+        byte[] octets = new byte[length];
+        int offset = 0;
+        while (offset < octets.length) {
+            int amount = in.read(octets, offset, octets.length - offset);
+            if (amount <= 0)
+                throw new EOFException();
+            offset += amount;
+        }
+        return new String(octets, StandardCharsets.UTF_8);
+    }
+
+    public static String readURN(InputStream in) throws IOException {
+        StringBuilder urn = new StringBuilder();
+
+        for (; ; ) {
+            byte b = (byte) in.read();
+            if (b == ')')
+                break;
+            urn.append((char) b);
+        }
+        return urn.toString();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/OMAConstructed.java b/packages/Osu/src/com/android/hotspot2/omadm/OMAConstructed.java
new file mode 100644
index 0000000..e5285f2
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/OMAConstructed.java
@@ -0,0 +1,169 @@
+package com.android.hotspot2.omadm;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+public class OMAConstructed extends OMANode {
+    private final MultiValueMap<OMANode> mChildren;
+
+    public OMAConstructed(OMAConstructed parent, String name, String context, String... avps) {
+        this(parent, name, context, new MultiValueMap<OMANode>(), buildAttributes(avps));
+    }
+
+    protected OMAConstructed(OMAConstructed parent, String name, String context,
+                             MultiValueMap<OMANode> children, Map<String, String> avps) {
+        super(parent, name, context, avps);
+        mChildren = children;
+    }
+
+    @Override
+    public OMANode addChild(String name, String context, String value, String pathString)
+            throws IOException {
+        if (pathString == null) {
+            OMANode child = value != null ?
+                    new OMAScalar(this, name, context, value) :
+                    new OMAConstructed(this, name, context);
+            mChildren.put(name, child);
+            return child;
+        } else {
+            OMANode target = this;
+            while (target.getParent() != null)
+                target = target.getParent();
+
+            for (String element : pathString.split("/")) {
+                target = target.getChild(element);
+                if (target == null)
+                    throw new IOException("No child node '" + element + "' in " + getPathString());
+                else if (target.isLeaf())
+                    throw new IOException("Cannot add child to leaf node: " + getPathString());
+            }
+            return target.addChild(name, context, value, null);
+        }
+    }
+
+    @Override
+    public OMAConstructed reparent(OMAConstructed parent) {
+        return new OMAConstructed(parent, getName(), getContext(), mChildren, getAttributes());
+    }
+
+    public void addChild(OMANode child) {
+        mChildren.put(child.getName(), child.reparent(this));
+    }
+
+    public String getScalarValue(Iterator<String> path) throws OMAException {
+        if (!path.hasNext()) {
+            throw new OMAException("Path too short for " + getPathString());
+        }
+        String tag = path.next();
+        OMANode child = mChildren.get(tag);
+        if (child != null) {
+            return child.getScalarValue(path);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public OMANode getListValue(Iterator<String> path) throws OMAException {
+        if (!path.hasNext()) {
+            return null;
+        }
+        String tag = path.next();
+        OMANode child;
+        if (tag.equals("?")) {
+            child = mChildren.getSingletonValue();
+        } else {
+            child = mChildren.get(tag);
+        }
+
+        if (child == null) {
+            return null;
+        } else if (path.hasNext()) {
+            return child.getListValue(path);
+        } else {
+            return child;
+        }
+    }
+
+    @Override
+    public boolean isLeaf() {
+        return false;
+    }
+
+    @Override
+    public Collection<OMANode> getChildren() {
+        return Collections.unmodifiableCollection(mChildren.values());
+    }
+
+    public OMANode getChild(String name) {
+        return mChildren.get(name);
+    }
+
+    public OMANode replaceNode(OMANode oldNode, OMANode newNode) {
+        return mChildren.replace(oldNode.getName(), oldNode, newNode);
+    }
+
+    public OMANode removeNode(String key, OMANode node) {
+        if (key.equals("?")) {
+            return mChildren.remove(node);
+        } else {
+            return mChildren.remove(key, node);
+        }
+    }
+
+    @Override
+    public String getValue() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void toString(StringBuilder sb, int level) {
+        sb.append(getPathString());
+        if (getContext() != null) {
+            sb.append(" (").append(getContext()).append(')');
+        }
+        sb.append('\n');
+
+        for (OMANode node : mChildren.values()) {
+            node.toString(sb, level + 1);
+        }
+    }
+
+    @Override
+    public void marshal(OutputStream out, int level) throws IOException {
+        OMAConstants.indent(level, out);
+        OMAConstants.serializeString(getName(), out);
+        if (getContext() != null) {
+            out.write(String.format("(%s)", getContext()).getBytes(StandardCharsets.UTF_8));
+        }
+        out.write(new byte[]{'+', '\n'});
+
+        for (OMANode child : mChildren.values()) {
+            child.marshal(out, level + 1);
+        }
+        OMAConstants.indent(level, out);
+        out.write(".\n".getBytes(StandardCharsets.UTF_8));
+    }
+
+    @Override
+    public void fillPayload(StringBuilder sb) {
+        if (getContext() != null) {
+            sb.append('<').append(MOTree.RTPropTag).append(">\n");
+            sb.append('<').append(MOTree.TypeTag).append(">\n");
+            sb.append('<').append(MOTree.DDFNameTag).append(">");
+            sb.append(getContext());
+            sb.append("</").append(MOTree.DDFNameTag).append(">\n");
+            sb.append("</").append(MOTree.TypeTag).append(">\n");
+            sb.append("</").append(MOTree.RTPropTag).append(">\n");
+        }
+
+        for (OMANode child : getChildren()) {
+            child.toXml(sb);
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/OMAException.java b/packages/Osu/src/com/android/hotspot2/omadm/OMAException.java
new file mode 100644
index 0000000..33a6e37
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/OMAException.java
@@ -0,0 +1,9 @@
+package com.android.hotspot2.omadm;
+
+import java.io.IOException;
+
+public class OMAException extends IOException {
+    public OMAException(String message) {
+        super(message);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/OMANode.java b/packages/Osu/src/com/android/hotspot2/omadm/OMANode.java
new file mode 100644
index 0000000..a428b2f
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/OMANode.java
@@ -0,0 +1,165 @@
+package com.android.hotspot2.omadm;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public abstract class OMANode {
+    private final OMAConstructed mParent;
+    private final String mName;
+    private final String mContext;
+    private final Map<String, String> mAttributes;
+
+    protected OMANode(OMAConstructed parent, String name, String context,
+                      Map<String, String> avps) {
+        mParent = parent;
+        mName = name;
+        mContext = context;
+        mAttributes = avps;
+    }
+
+    protected static Map<String, String> buildAttributes(String[] avps) {
+        if (avps == null) {
+            return null;
+        }
+        Map<String, String> attributes = new HashMap<>();
+        for (int n = 0; n < avps.length; n += 2) {
+            attributes.put(avps[n], avps[n + 1]);
+        }
+        return attributes;
+    }
+
+    protected Map<String, String> getAttributes() {
+        return mAttributes;
+    }
+
+    public OMAConstructed getParent() {
+        return mParent;
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public String getContext() {
+        return mContext;
+    }
+
+    public List<String> getPath() {
+        LinkedList<String> path = new LinkedList<>();
+        for (OMANode node = this; node != null; node = node.getParent()) {
+            path.addFirst(node.getName());
+        }
+        return path;
+    }
+
+    public String getPathString() {
+        StringBuilder sb = new StringBuilder();
+        for (String element : getPath()) {
+            sb.append('/').append(element);
+        }
+        return sb.toString();
+    }
+
+    public abstract OMANode reparent(OMAConstructed parent);
+
+    public abstract String getScalarValue(Iterator<String> path) throws OMAException;
+
+    public abstract OMANode getListValue(Iterator<String> path) throws OMAException;
+
+    public abstract boolean isLeaf();
+
+    public abstract Collection<OMANode> getChildren();
+
+    public abstract OMANode getChild(String name) throws OMAException;
+
+    public abstract String getValue();
+
+    public abstract OMANode addChild(String name, String context, String value, String path)
+            throws IOException;
+
+    public abstract void marshal(OutputStream out, int level) throws IOException;
+
+    public abstract void toString(StringBuilder sb, int level);
+
+    public abstract void fillPayload(StringBuilder sb);
+
+    public void toXml(StringBuilder sb) {
+        sb.append('<').append(MOTree.NodeTag);
+        if (mAttributes != null && !mAttributes.isEmpty()) {
+            for (Map.Entry<String, String> avp : mAttributes.entrySet()) {
+                sb.append(' ').append(avp.getKey()).append("=\"")
+                        .append(avp.getValue()).append('"');
+            }
+        }
+        sb.append(">\n");
+
+        sb.append('<').append(MOTree.NodeNameTag).append('>');
+        sb.append(getName());
+        sb.append("</").append(MOTree.NodeNameTag).append(">\n");
+
+        fillPayload(sb);
+
+        sb.append("</").append(MOTree.NodeTag).append(">\n");
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        toString(sb, 0);
+        return sb.toString();
+    }
+
+    public static OMAConstructed unmarshal(InputStream in) throws IOException {
+        OMANode node = buildNode(in, null);
+        if (node == null || node.isLeaf()) {
+            throw new IOException("Bad OMA tree");
+        }
+        unmarshal(in, (OMAConstructed) node);
+        return (OMAConstructed) node;
+    }
+
+    private static void unmarshal(InputStream in, OMAConstructed parent) throws IOException {
+        for (; ; ) {
+            OMANode node = buildNode(in, parent);
+            if (node == null) {
+                return;
+            } else if (!node.isLeaf()) {
+                unmarshal(in, (OMAConstructed) node);
+            }
+        }
+    }
+
+    private static OMANode buildNode(InputStream in, OMAConstructed parent) throws IOException {
+        String name = OMAConstants.deserializeString(in);
+        if (name == null) {
+            return null;
+        }
+
+        String urn = null;
+        int next = in.read();
+        if (next == '(') {
+            urn = OMAConstants.readURN(in);
+            next = in.read();
+        }
+
+        if (next == '=') {
+            String value = OMAConstants.deserializeString(in);
+            return parent.addChild(name, urn, value, null);
+        } else if (next == '+') {
+            if (parent != null) {
+                return parent.addChild(name, urn, null, null);
+            } else {
+                return new OMAConstructed(null, name, urn);
+            }
+        } else {
+            throw new IOException("Parse error: expected = or + after node name");
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/OMAParser.java b/packages/Osu/src/com/android/hotspot2/omadm/OMAParser.java
new file mode 100644
index 0000000..21cc19a
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/OMAParser.java
@@ -0,0 +1,69 @@
+package com.android.hotspot2.omadm;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+/**
+ * Parses an OMA-DM XML tree.
+ */
+public class OMAParser extends DefaultHandler {
+    private XMLNode mRoot;
+    private XMLNode mCurrent;
+
+    public OMAParser() {
+        mRoot = null;
+        mCurrent = null;
+    }
+
+    public MOTree parse(String text, String urn) throws IOException, SAXException {
+        try {
+            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+            parser.parse(new InputSource(new StringReader(text)), this);
+            return new MOTree(mRoot, urn);
+        } catch (ParserConfigurationException pce) {
+            throw new SAXException(pce);
+        }
+    }
+
+    @Override
+    public void startElement(String uri, String localName, String qName, Attributes attributes)
+            throws SAXException {
+        XMLNode parent = mCurrent;
+
+        mCurrent = new XMLNode(mCurrent, qName, attributes);
+
+        if (mRoot == null)
+            mRoot = mCurrent;
+        else
+            parent.addChild(mCurrent);
+    }
+
+    @Override
+    public void endElement(String uri, String localName, String qName) throws SAXException {
+        if (!qName.equals(mCurrent.getTag()))
+            throw new SAXException("End tag '" + qName + "' doesn't match current node: " +
+                    mCurrent);
+
+        try {
+            mCurrent.close();
+        } catch (IOException ioe) {
+            throw new SAXException("Failed to close element", ioe);
+        }
+
+        mCurrent = mCurrent.getParent();
+    }
+
+    @Override
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        mCurrent.addText(ch, start, length);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/OMAScalar.java b/packages/Osu/src/com/android/hotspot2/omadm/OMAScalar.java
new file mode 100644
index 0000000..a971ac4
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/OMAScalar.java
@@ -0,0 +1,87 @@
+package com.android.hotspot2.omadm;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+public class OMAScalar extends OMANode {
+    private final String mValue;
+
+    public OMAScalar(OMAConstructed parent, String name, String context, String value,
+                     String ... avps) {
+        this(parent, name, context, value, buildAttributes(avps));
+    }
+
+    public OMAScalar(OMAConstructed parent, String name, String context, String value,
+                     Map<String, String> avps) {
+        super(parent, name, context, avps);
+        mValue = value;
+    }
+
+    @Override
+    public OMAScalar reparent(OMAConstructed parent) {
+        return new OMAScalar(parent, getName(), getContext(), mValue, getAttributes());
+    }
+
+    public String getScalarValue(Iterator<String> path) throws OMAException {
+        return mValue;
+    }
+
+    @Override
+    public OMANode getListValue(Iterator<String> path) throws OMAException {
+        throw new OMAException("Scalar encountered in list path: " + getPathString());
+    }
+
+    @Override
+    public boolean isLeaf() {
+        return true;
+    }
+
+    @Override
+    public Collection<OMANode> getChildren() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getValue() {
+        return mValue;
+    }
+
+    @Override
+    public OMANode getChild(String name) throws OMAException {
+        throw new OMAException("'" + getName() + "' is a scalar node");
+    }
+
+    @Override
+    public OMANode addChild(String name, String context, String value, String path)
+            throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void toString(StringBuilder sb, int level) {
+        sb.append(getPathString()).append('=').append(mValue);
+        if (getContext() != null) {
+            sb.append(" (").append(getContext()).append(')');
+        }
+        sb.append('\n');
+    }
+
+    @Override
+    public void marshal(OutputStream out, int level) throws IOException {
+        OMAConstants.indent(level, out);
+        OMAConstants.serializeString(getName(), out);
+        out.write((byte) '=');
+        OMAConstants.serializeString(getValue(), out);
+        out.write((byte) '\n');
+    }
+
+    @Override
+    public void fillPayload(StringBuilder sb) {
+        sb.append('<').append(MOTree.ValueTag).append('>');
+        sb.append(mValue);
+        sb.append("</").append(MOTree.ValueTag).append(">\n");
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/omadm/XMLNode.java b/packages/Osu/src/com/android/hotspot2/omadm/XMLNode.java
new file mode 100644
index 0000000..b77c820
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/omadm/XMLNode.java
@@ -0,0 +1,240 @@
+package com.android.hotspot2.omadm;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class XMLNode {
+    private final String mTag;
+    private final Map<String, NodeAttribute> mAttributes;
+    private final List<XMLNode> mChildren;
+    private final XMLNode mParent;
+    private MOTree mMO;
+    private StringBuilder mTextBuilder;
+    private String mText;
+
+    private static final String XML_SPECIAL_CHARS = "\"'<>&";
+    private static final Set<Character> XML_SPECIAL = new HashSet<>();
+    private static final String CDATA_OPEN = "<![CDATA[";
+    private static final String CDATA_CLOSE = "]]>";
+
+    static {
+        for (int n = 0; n < XML_SPECIAL_CHARS.length(); n++) {
+            XML_SPECIAL.add(XML_SPECIAL_CHARS.charAt(n));
+        }
+    }
+
+    public XMLNode(XMLNode parent, String tag, Attributes attributes) throws SAXException {
+        mTag = tag;
+
+        mAttributes = new HashMap<>();
+
+        if (attributes.getLength() > 0) {
+            for (int n = 0; n < attributes.getLength(); n++)
+                mAttributes.put(attributes.getQName(n), new NodeAttribute(attributes.getQName(n),
+                        attributes.getType(n), attributes.getValue(n)));
+        }
+
+        mParent = parent;
+        mChildren = new ArrayList<>();
+
+        mTextBuilder = new StringBuilder();
+    }
+
+    public XMLNode(XMLNode parent, String tag, Map<String, String> attributes) {
+        mTag = tag;
+
+        mAttributes = new HashMap<>(attributes == null ? 0 : attributes.size());
+
+        if (attributes != null) {
+            for (Map.Entry<String, String> entry : attributes.entrySet()) {
+                mAttributes.put(entry.getKey(),
+                        new NodeAttribute(entry.getKey(), "", entry.getValue()));
+            }
+        }
+
+        mParent = parent;
+        mChildren = new ArrayList<>();
+
+        mTextBuilder = new StringBuilder();
+    }
+
+    public void setText(String text) {
+        mText = text;
+        mTextBuilder = null;
+    }
+
+    public void addText(char[] chs, int start, int length) {
+        String s = new String(chs, start, length);
+        String trimmed = s.trim();
+        if (trimmed.isEmpty())
+            return;
+
+        if (s.charAt(0) != trimmed.charAt(0))
+            mTextBuilder.append(' ');
+        mTextBuilder.append(trimmed);
+        if (s.charAt(s.length() - 1) != trimmed.charAt(trimmed.length() - 1))
+            mTextBuilder.append(' ');
+    }
+
+    public void addChild(XMLNode child) {
+        mChildren.add(child);
+    }
+
+    public void close() throws IOException, SAXException {
+        String text = mTextBuilder.toString().trim();
+        StringBuilder filtered = new StringBuilder(text.length());
+        for (int n = 0; n < text.length(); n++) {
+            char ch = text.charAt(n);
+            if (ch >= ' ')
+                filtered.append(ch);
+        }
+
+        mText = filtered.toString();
+        mTextBuilder = null;
+
+        if (MOTree.hasMgmtTreeTag(mText)) {
+            try {
+                NodeAttribute urn = mAttributes.get(OMAConstants.SppMOAttribute);
+                OMAParser omaParser = new OMAParser();
+                mMO = omaParser.parse(mText, urn != null ? urn.getValue() : null);
+            } catch (SAXException | IOException e) {
+                mMO = null;
+            }
+        }
+    }
+
+    public String getTag() {
+        return mTag;
+    }
+
+    public String getNameSpace() throws OMAException {
+        String[] nsn = mTag.split(":");
+        if (nsn.length != 2) {
+            throw new OMAException("Non-namespaced tag: '" + mTag + "'");
+        }
+        return nsn[0];
+    }
+
+    public String getStrippedTag() throws OMAException {
+        String[] nsn = mTag.split(":");
+        if (nsn.length != 2) {
+            throw new OMAException("Non-namespaced tag: '" + mTag + "'");
+        }
+        return nsn[1].toLowerCase();
+    }
+
+    public XMLNode getSoleChild() throws OMAException {
+        if (mChildren.size() != 1) {
+            throw new OMAException("Expected exactly one child to " + mTag);
+        }
+        return mChildren.get(0);
+    }
+
+    public XMLNode getParent() {
+        return mParent;
+    }
+
+    public String getText() {
+        return mText;
+    }
+
+    public Map<String, NodeAttribute> getAttributes() {
+        return Collections.unmodifiableMap(mAttributes);
+    }
+
+    public Map<String, String> getTextualAttributes() {
+        Map<String, String> map = new HashMap<>(mAttributes.size());
+        for (Map.Entry<String, NodeAttribute> entry : mAttributes.entrySet()) {
+            map.put(entry.getKey(), entry.getValue().getValue());
+        }
+        return map;
+    }
+
+    public String getAttributeValue(String name) {
+        NodeAttribute nodeAttribute = mAttributes.get(name);
+        return nodeAttribute != null ? nodeAttribute.getValue() : null;
+    }
+
+    public List<XMLNode> getChildren() {
+        return mChildren;
+    }
+
+    public MOTree getMOTree() {
+        return mMO;
+    }
+
+    private void toString(char[] indent, StringBuilder sb) {
+        Arrays.fill(indent, ' ');
+
+        sb.append(indent).append('<').append(mTag);
+        for (Map.Entry<String, NodeAttribute> entry : mAttributes.entrySet()) {
+            sb.append(' ').append(entry.getKey()).append("='")
+                    .append(entry.getValue().getValue()).append('\'');
+        }
+
+        if (mText != null && !mText.isEmpty()) {
+            sb.append('>').append(escapeCdata(mText)).append("</").append(mTag).append(">\n");
+        } else if (mChildren.isEmpty()) {
+            sb.append("/>\n");
+        } else {
+            sb.append(">\n");
+            char[] subIndent = Arrays.copyOf(indent, indent.length + 2);
+            for (XMLNode child : mChildren) {
+                child.toString(subIndent, sb);
+            }
+            sb.append(indent).append("</").append(mTag).append(">\n");
+        }
+    }
+
+    private static String escapeCdata(String text) {
+        if (!escapable(text)) {
+            return text;
+        }
+
+        // Any appearance of ]]> in the text must be split into "]]" | "]]>" | <![CDATA[ | ">"
+        // i.e. "split the sequence by putting a close CDATA and a new open CDATA before the '>'
+        StringBuilder sb = new StringBuilder();
+        sb.append(CDATA_OPEN);
+        int start = 0;
+        for (; ; ) {
+            int etoken = text.indexOf(CDATA_CLOSE);
+            if (etoken >= 0) {
+                sb.append(text.substring(start, etoken + 2)).append(CDATA_CLOSE).append(CDATA_OPEN);
+                start = etoken + 2;
+            } else {
+                if (start < text.length() - 1) {
+                    sb.append(text.substring(start));
+                }
+                break;
+            }
+        }
+        sb.append(CDATA_CLOSE);
+        return sb.toString();
+    }
+
+    private static boolean escapable(String s) {
+        for (int n = 0; n < s.length(); n++) {
+            if (XML_SPECIAL.contains(s.charAt(n))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        toString(new char[0], sb);
+        return sb.toString();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/ClientKeyManager.java b/packages/Osu/src/com/android/hotspot2/osu/ClientKeyManager.java
new file mode 100644
index 0000000..f5d06d5
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/ClientKeyManager.java
@@ -0,0 +1,127 @@
+package com.android.hotspot2.osu;
+
+import android.util.Log;
+
+import com.android.hotspot2.pps.HomeSP;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.X509KeyManager;
+
+public class ClientKeyManager implements X509KeyManager {
+    private final KeyStore mKeyStore;
+    private final Map<OSUCertType, String> mAliasMap;
+    private final Map<OSUCertType, Object> mTempKeys;
+
+    private static final String sTempAlias = "client-alias";
+
+    public ClientKeyManager(HomeSP homeSP, KeyStore keyStore) throws IOException {
+        mKeyStore = keyStore;
+        mAliasMap = new HashMap<>();
+        mAliasMap.put(OSUCertType.AAA, OSUManager.CERT_CLT_CA_ALIAS + homeSP.getFQDN());
+        mAliasMap.put(OSUCertType.Client, OSUManager.CERT_CLT_CERT_ALIAS + homeSP.getFQDN());
+        mAliasMap.put(OSUCertType.PrivateKey, OSUManager.CERT_CLT_KEY_ALIAS + homeSP.getFQDN());
+        mTempKeys = new HashMap<>();
+    }
+
+    public void reloadKeys(Map<OSUCertType, List<X509Certificate>> certs, PrivateKey key)
+            throws IOException {
+        List<X509Certificate> clientCerts = certs.get(OSUCertType.Client);
+        X509Certificate[] certArray = new X509Certificate[clientCerts.size()];
+        int n = 0;
+        for (X509Certificate cert : clientCerts) {
+            certArray[n++] = cert;
+        }
+        mTempKeys.put(OSUCertType.Client, certArray);
+        mTempKeys.put(OSUCertType.PrivateKey, key);
+    }
+
+    @Override
+    public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
+        if (mTempKeys.isEmpty()) {
+            return mAliasMap.get(OSUCertType.Client);
+        } else {
+            return sTempAlias;
+        }
+    }
+
+    @Override
+    public String[] getClientAliases(String keyType, Principal[] issuers) {
+        if (mTempKeys.isEmpty()) {
+            String alias = mAliasMap.get(OSUCertType.Client);
+            return alias != null ? new String[]{alias} : null;
+        } else {
+            return new String[]{sTempAlias};
+        }
+    }
+
+    @Override
+    public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String[] getServerAliases(String keyType, Principal[] issuers) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public X509Certificate[] getCertificateChain(String alias) {
+        if (mTempKeys.isEmpty()) {
+            if (!mAliasMap.get(OSUCertType.Client).equals(alias)) {
+                Log.w(OSUManager.TAG, "Bad cert alias requested: '" + alias + "'");
+                return null;
+            }
+            try {
+                List<X509Certificate> certs = new ArrayList<>();
+                for (Certificate certificate :
+                        mKeyStore.getCertificateChain(mAliasMap.get(OSUCertType.Client))) {
+                    if (certificate instanceof X509Certificate) {
+                        certs.add((X509Certificate) certificate);
+                    }
+                }
+                return certs.toArray(new X509Certificate[certs.size()]);
+            } catch (KeyStoreException kse) {
+                Log.w(OSUManager.TAG, "Failed to retrieve certificates: " + kse);
+                return null;
+            }
+        } else if (sTempAlias.equals(alias)) {
+            return (X509Certificate[]) mTempKeys.get(OSUCertType.Client);
+        } else {
+            Log.w(OSUManager.TAG, "Bad cert alias requested: '" + alias + "'");
+            return null;
+        }
+    }
+
+    @Override
+    public PrivateKey getPrivateKey(String alias) {
+        if (mTempKeys.isEmpty()) {
+            if (!mAliasMap.get(OSUCertType.Client).equals(alias)) {
+                Log.w(OSUManager.TAG, "Bad key alias requested: '" + alias + "'");
+            }
+            try {
+                return (PrivateKey) mKeyStore.getKey(mAliasMap.get(OSUCertType.PrivateKey), null);
+            } catch (GeneralSecurityException gse) {
+                Log.w(OSUManager.TAG, "Failed to retrieve private key: " + gse);
+                return null;
+            }
+        } else if (sTempAlias.equals(alias)) {
+            return (PrivateKey) mTempKeys.get(OSUCertType.PrivateKey);
+        } else {
+            Log.w(OSUManager.TAG, "Bad cert alias requested: '" + alias + "'");
+            return null;
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/ExchangeCompleteResponse.java b/packages/Osu/src/com/android/hotspot2/osu/ExchangeCompleteResponse.java
new file mode 100644
index 0000000..fe23b5c
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/ExchangeCompleteResponse.java
@@ -0,0 +1,28 @@
+package com.android.hotspot2.osu;
+
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.XMLNode;
+
+	/*
+	<xsd:element name="sppExchangeComplete">
+		<xsd:annotation>
+			<xsd:documentation>SOAP method used by SPP server to end session.</xsd:documentation>
+		</xsd:annotation>
+		<xsd:complexType>
+			<xsd:sequence>
+				<xsd:element ref="sppError" minOccurs="0"/>
+				<xsd:any namespace="##other" maxOccurs="unbounded" minOccurs="0"/>
+			</xsd:sequence>
+			<xsd:attribute ref="sppVersion" use="required"/>
+			<xsd:attribute ref="sppStatus" use="required"/>
+			<xsd:attribute ref="sessionID" use="required"/>
+			<xsd:anyAttribute namespace="##other"/>
+		</xsd:complexType>
+	</xsd:element>
+	 */
+
+public class ExchangeCompleteResponse extends OSUResponse {
+    public ExchangeCompleteResponse(XMLNode root) throws OMAException {
+        super(root, OSUMessageType.ExchangeComplete);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/ExecCommand.java b/packages/Osu/src/com/android/hotspot2/osu/ExecCommand.java
new file mode 100644
index 0000000..38a3947
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/ExecCommand.java
@@ -0,0 +1,3 @@
+package com.android.hotspot2.osu;
+
+public enum ExecCommand {Browser, GetCert, UseClientCertTLS, UploadMO}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/HTTPHandler.java b/packages/Osu/src/com/android/hotspot2/osu/HTTPHandler.java
new file mode 100644
index 0000000..1a66fcf
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/HTTPHandler.java
@@ -0,0 +1,178 @@
+package com.android.hotspot2.osu;
+
+import android.util.Log;
+
+import com.android.hotspot2.utils.HTTPMessage;
+import com.android.hotspot2.utils.HTTPRequest;
+import com.android.hotspot2.utils.HTTPResponse;
+
+import com.android.org.conscrypt.OpenSSLSocketImpl;
+
+import org.xml.sax.SAXException;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSocket;
+import javax.xml.parsers.ParserConfigurationException;
+
+public class HTTPHandler implements AutoCloseable {
+    private final Charset mCharset;
+    private final OSUSocketFactory mSocketFactory;
+    private Socket mSocket;
+    private BufferedOutputStream mOut;
+    private BufferedInputStream mIn;
+    private final String mUser;
+    private final byte[] mPassword;
+    private boolean mHTTPAuthPerformed;
+    private static final AtomicInteger sSequence = new AtomicInteger();
+
+    public HTTPHandler(Charset charset, OSUSocketFactory socketFactory) throws IOException {
+        this(charset, socketFactory, null, null);
+    }
+
+    public HTTPHandler(Charset charset, OSUSocketFactory socketFactory,
+                       String user, byte[] password) throws IOException {
+        mCharset = charset;
+        mSocketFactory = socketFactory;
+        mSocket = mSocketFactory.createSocket();
+        mOut = new BufferedOutputStream(mSocket.getOutputStream());
+        mIn = new BufferedInputStream(mSocket.getInputStream());
+        mUser = user;
+        mPassword = password;
+    }
+
+    public boolean isHTTPAuthPerformed() {
+        return mHTTPAuthPerformed;
+    }
+
+    public X509Certificate getOSUCertificate(URL osu) throws GeneralSecurityException {
+        return mSocketFactory.getOSUCertificate(osu);
+    }
+
+    public void renegotiate(Map<OSUCertType, List<X509Certificate>> certs, PrivateKey key)
+            throws IOException {
+        if (!(mSocket instanceof SSLSocket)) {
+            throw new IOException("Not a TLS connection");
+        }
+        if (certs != null) {
+            mSocketFactory.reloadKeys(certs, key);
+        }
+        ((SSLSocket) mSocket).startHandshake();
+    }
+
+    public byte[] getTLSUnique() throws SSLException {
+        if (mSocket instanceof OpenSSLSocketImpl) {
+            return ((OpenSSLSocketImpl) mSocket).getChannelId();
+        }
+        return null;
+    }
+
+    public OSUResponse exchangeSOAP(URL url, String message) throws IOException {
+        HTTPResponse response = exchangeWithRetry(url, message, HTTPMessage.Method.POST,
+                HTTPMessage.ContentTypeSOAP);
+        if (response.getStatusCode() >= 300) {
+            throw new IOException("Bad HTTP status code " + response.getStatusCode());
+        }
+        try {
+            SOAPParser parser = new SOAPParser(response.getPayloadStream());
+            return parser.getResponse();
+        } catch (ParserConfigurationException | SAXException e) {
+            ByteBuffer x = response.getPayload();
+            byte[] b = new byte[x.remaining()];
+            x.get(b);
+            Log.w("XML", "Bad: '" + new String(b, StandardCharsets.ISO_8859_1));
+            throw new IOException(e);
+        }
+    }
+
+    public ByteBuffer exchangeBinary(URL url, String message, String contentType)
+            throws IOException {
+        HTTPResponse response =
+                exchangeWithRetry(url, message, HTTPMessage.Method.POST, contentType);
+        return response.getBinaryPayload();
+    }
+
+    public InputStream doGet(URL url) throws IOException {
+        HTTPResponse response = exchangeWithRetry(url, null, HTTPMessage.Method.GET, null);
+        return response.getPayloadStream();
+    }
+
+    public HTTPResponse doGetHTTP(URL url) throws IOException {
+        return exchangeWithRetry(url, null, HTTPMessage.Method.GET, null);
+    }
+
+    private HTTPResponse exchangeWithRetry(URL url, String message, HTTPMessage.Method method,
+                                           String contentType) throws IOException {
+        HTTPResponse response = null;
+        int retry = 0;
+        for (; ; ) {
+            try {
+                response = httpExchange(url, message, method, contentType);
+                break;
+            } catch (IOException ioe) {
+                close();
+                retry++;
+                if (retry > 3) {
+                    break;
+                }
+                Log.d(OSUManager.TAG, "Failed HTTP exchange, retry " + retry);
+                mSocket = mSocketFactory.createSocket();
+                mOut = new BufferedOutputStream(mSocket.getOutputStream());
+                mIn = new BufferedInputStream(mSocket.getInputStream());
+            }
+        }
+        if (response == null) {
+            throw new IOException("Failed to establish connection to peer");
+        }
+        return response;
+    }
+
+    private HTTPResponse httpExchange(URL url, String message, HTTPMessage.Method method,
+                                      String contentType)
+            throws IOException {
+        HTTPRequest request = new HTTPRequest(message, mCharset, method, url, contentType, false);
+        request.send(mOut);
+        HTTPResponse response = new HTTPResponse(mIn);
+        Log.d(OSUManager.TAG, "HTTP code " + response.getStatusCode() + ", user " + mUser +
+                ", pw " + (mPassword != null ? '\'' + new String(mPassword) + '\'' : "-"));
+        if (response.getStatusCode() == 401) {
+            if (mUser == null) {
+                throw new IOException("Missing user name for HTTP authentication");
+            }
+            try {
+                request = new HTTPRequest(message, StandardCharsets.ISO_8859_1, method, url,
+                        contentType, true);
+                request.doAuthenticate(response, mUser, mPassword, url,
+                        sSequence.incrementAndGet());
+                request.send(mOut);
+                mHTTPAuthPerformed = true;
+            } catch (GeneralSecurityException gse) {
+                throw new IOException(gse);
+            }
+
+            response = new HTTPResponse(mIn);
+        }
+        return response;
+    }
+
+    public void close() throws IOException {
+        mIn.close();
+        mOut.close();
+        mSocket.close();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/IconCache.java b/packages/Osu/src/com/android/hotspot2/osu/IconCache.java
new file mode 100644
index 0000000..b1580ac
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/IconCache.java
@@ -0,0 +1,392 @@
+package com.android.hotspot2.osu;
+
+import android.util.Log;
+
+import com.android.anqp.HSIconFileElement;
+import com.android.anqp.IconInfo;
+import com.android.hotspot2.Utils;
+
+import java.net.ProtocolException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static com.android.anqp.Constants.ANQPElementType.HSIconFile;
+
+public class IconCache extends Thread {
+    private static final int CacheSize = 64;
+    private static final int RetryCount = 3;
+
+    private final OSUManager mOSUManager;
+    private final Map<Long, LinkedList<QuerySet>> mBssQueues = new HashMap<>();
+
+    private final Map<IconKey, HSIconFileElement> mCache =
+            new LinkedHashMap<IconKey, HSIconFileElement>() {
+                @Override
+                protected boolean removeEldestEntry(Map.Entry eldest) {
+                    return size() > CacheSize;
+                }
+            };
+
+    private static class IconKey {
+        private final long mBSSID;
+        private final long mHESSID;
+        private final String mSSID;
+        private final int mAnqpDomID;
+        private final String mFileName;
+
+        private IconKey(OSUInfo osuInfo, String fileName) {
+            mBSSID = osuInfo.getBSSID();
+            mHESSID = osuInfo.getHESSID();
+            mSSID = osuInfo.getAdvertisingSSID();
+            mAnqpDomID = osuInfo.getAnqpDomID();
+            mFileName = fileName;
+        }
+
+        public String getFileName() {
+            return mFileName;
+        }
+
+        @Override
+        public boolean equals(Object thatObject) {
+            if (this == thatObject) {
+                return true;
+            }
+            if (thatObject == null || getClass() != thatObject.getClass()) {
+                return false;
+            }
+
+            IconKey that = (IconKey) thatObject;
+
+            return mFileName.equals(that.mFileName) && ((mBSSID == that.mBSSID) ||
+                    ((mAnqpDomID == that.mAnqpDomID) && (mAnqpDomID != 0) &&
+                            (mHESSID == that.mHESSID) && ((mHESSID != 0)
+                            || mSSID.equals(that.mSSID))));
+        }
+
+        @Override
+        public int hashCode() {
+            int result = (int) (mBSSID ^ (mBSSID >>> 32));
+            result = 31 * result + (int) (mHESSID ^ (mHESSID >>> 32));
+            result = 31 * result + mSSID.hashCode();
+            result = 31 * result + mAnqpDomID;
+            result = 31 * result + mFileName.hashCode();
+            return result;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%012x:%012x '%s' [%d] + '%s'",
+                    mBSSID, mHESSID, mSSID, mAnqpDomID, mFileName);
+        }
+    }
+
+    private static class QueryEntry {
+        private final IconKey mKey;
+        private int mRetry;
+        private long mLastSent;
+
+        private QueryEntry(IconKey key) {
+            mKey = key;
+            mLastSent = System.currentTimeMillis();
+        }
+
+        private IconKey getKey() {
+            return mKey;
+        }
+
+        private int bumpRetry() {
+            mLastSent = System.currentTimeMillis();
+            return mRetry++;
+        }
+
+        private long age(long now) {
+            return now - mLastSent;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("Entry %s, retry %d", mKey, mRetry);
+        }
+    }
+
+    private static class QuerySet {
+        private final OSUInfo mOsuInfo;
+        private final LinkedList<QueryEntry> mEntries;
+
+        private QuerySet(OSUInfo osuInfo, List<IconInfo> icons) {
+            mOsuInfo = osuInfo;
+            mEntries = new LinkedList<>();
+            for (IconInfo iconInfo : icons) {
+                mEntries.addLast(new QueryEntry(new IconKey(osuInfo, iconInfo.getFileName())));
+            }
+        }
+
+        private QueryEntry peek() {
+            return mEntries.getFirst();
+        }
+
+        private QueryEntry pop() {
+            mEntries.removeFirst();
+            return mEntries.isEmpty() ? null : mEntries.getFirst();
+        }
+
+        private boolean isEmpty() {
+            return mEntries.isEmpty();
+        }
+
+        private List<QueryEntry> getAllEntries() {
+            return Collections.unmodifiableList(mEntries);
+        }
+
+        private long getBssid() {
+            return mOsuInfo.getBSSID();
+        }
+
+        private OSUInfo getOsuInfo() {
+            return mOsuInfo;
+        }
+
+        private IconKey updateIcon(String fileName, HSIconFileElement iconFileElement) {
+            IconKey key = null;
+            for (QueryEntry queryEntry : mEntries) {
+                if (queryEntry.getKey().getFileName().equals(fileName)) {
+                    key = queryEntry.getKey();
+                }
+            }
+            if (key == null) {
+                return null;
+            }
+
+            if (iconFileElement != null) {
+                mOsuInfo.setIconFileElement(iconFileElement, fileName);
+            } else {
+                mOsuInfo.setIconStatus(OSUInfo.IconStatus.NotAvailable);
+            }
+            return key;
+        }
+
+        private boolean updateIcon(IconKey key, HSIconFileElement iconFileElement) {
+            boolean match = false;
+            for (QueryEntry queryEntry : mEntries) {
+                if (queryEntry.getKey().equals(key)) {
+                    match = true;
+                    break;
+                }
+            }
+            if (!match) {
+                return false;
+            }
+
+            if (iconFileElement != null) {
+                mOsuInfo.setIconFileElement(iconFileElement, key.getFileName());
+            } else {
+                mOsuInfo.setIconStatus(OSUInfo.IconStatus.NotAvailable);
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "OSU " + mOsuInfo + ": " + mEntries;
+        }
+    }
+
+    public IconCache(OSUManager osuManager) {
+        mOSUManager = osuManager;
+    }
+
+    public void clear() {
+        mBssQueues.clear();
+        mCache.clear();
+    }
+
+    private boolean enqueue(QuerySet querySet) {
+        boolean newEntry = false;
+        LinkedList<QuerySet> queries = mBssQueues.get(querySet.getBssid());
+        if (queries == null) {
+            queries = new LinkedList<>();
+            mBssQueues.put(querySet.getBssid(), queries);
+            newEntry = true;
+        }
+        queries.addLast(querySet);
+        return newEntry;
+    }
+
+    public void startIconQuery(OSUInfo osuInfo, List<IconInfo> icons) {
+        Log.d("ZXZ", String.format("Icon query on %012x for %s", osuInfo.getBSSID(), icons));
+        if (icons == null || icons.isEmpty()) {
+            return;
+        }
+
+        QuerySet querySet = new QuerySet(osuInfo, icons);
+        for (QueryEntry entry : querySet.getAllEntries()) {
+            HSIconFileElement iconElement = mCache.get(entry.getKey());
+            if (iconElement != null) {
+                osuInfo.setIconFileElement(iconElement, entry.getKey().getFileName());
+                mOSUManager.iconResults(Arrays.asList(osuInfo));
+                return;
+            }
+        }
+        if (enqueue(querySet)) {
+            initiateQuery(querySet.getBssid());
+        }
+    }
+
+    private void initiateQuery(long bssid) {
+        LinkedList<QuerySet> queryEntries = mBssQueues.get(bssid);
+        if (queryEntries == null) {
+            return;
+        } else if (queryEntries.isEmpty()) {
+            mBssQueues.remove(bssid);
+            return;
+        }
+
+        QuerySet querySet = queryEntries.getFirst();
+        QueryEntry queryEntry = querySet.peek();
+        if (queryEntry.bumpRetry() >= RetryCount) {
+            QueryEntry newEntry = querySet.pop();
+            if (newEntry == null) {
+                // No more entries in this QuerySet, advance to the next set.
+                querySet.getOsuInfo().setIconStatus(OSUInfo.IconStatus.NotAvailable);
+                queryEntries.removeFirst();
+                if (queryEntries.isEmpty()) {
+                    // No further QuerySet on this BSSID, drop the bucket and bail.
+                    mBssQueues.remove(bssid);
+                    return;
+                } else {
+                    querySet = queryEntries.getFirst();
+                    queryEntry = querySet.peek();
+                    queryEntry.bumpRetry();
+                }
+            }
+        }
+        mOSUManager.doIconQuery(bssid, queryEntry.getKey().getFileName());
+    }
+
+    public void notifyIconReceived(long bssid, String fileName, byte[] iconData) {
+        Log.d("ZXZ", String.format("Icon '%s':%d received from %012x",
+                fileName, iconData != null ? iconData.length : -1, bssid));
+        IconKey key;
+        HSIconFileElement iconFileElement = null;
+        List<OSUInfo> updates = new ArrayList<>();
+
+        LinkedList<QuerySet> querySets = mBssQueues.get(bssid);
+        if (querySets == null || querySets.isEmpty()) {
+            Log.d(OSUManager.TAG,
+                    String.format("Spurious icon response from %012x for '%s' (%d) bytes",
+                            bssid, fileName, iconData != null ? iconData.length : -1));
+            Log.d("ZXZ", "query set: " + querySets
+                    + ", BSS queues: " + Utils.bssidsToString(mBssQueues.keySet()));
+            return;
+        } else {
+            QuerySet querySet = querySets.removeFirst();
+            if (iconData != null) {
+                try {
+                    iconFileElement = new HSIconFileElement(HSIconFile,
+                            ByteBuffer.wrap(iconData).order(ByteOrder.LITTLE_ENDIAN));
+                } catch (ProtocolException | BufferUnderflowException e) {
+                    Log.e(OSUManager.TAG, "Failed to parse ANQP icon file: " + e);
+                }
+            }
+            key = querySet.updateIcon(fileName, iconFileElement);
+            if (key == null) {
+                Log.d(OSUManager.TAG,
+                        String.format("Spurious icon response from %012x for '%s' (%d) bytes",
+                                bssid, fileName, iconData != null ? iconData.length : -1));
+                Log.d("ZXZ", "query set: " + querySets + ", BSS queues: "
+                        + Utils.bssidsToString(mBssQueues.keySet()));
+                querySets.addFirst(querySet);
+                return;
+            }
+
+            if (iconFileElement != null) {
+                mCache.put(key, iconFileElement);
+            }
+
+            if (querySet.isEmpty()) {
+                mBssQueues.remove(bssid);
+            }
+            updates.add(querySet.getOsuInfo());
+        }
+
+        // Update any other pending entries that matches the ESS of the currently resolved icon
+        Iterator<Map.Entry<Long, LinkedList<QuerySet>>> bssIterator =
+                mBssQueues.entrySet().iterator();
+        while (bssIterator.hasNext()) {
+            Map.Entry<Long, LinkedList<QuerySet>> bssEntries = bssIterator.next();
+            Iterator<QuerySet> querySetIterator = bssEntries.getValue().iterator();
+            while (querySetIterator.hasNext()) {
+                QuerySet querySet = querySetIterator.next();
+                if (querySet.updateIcon(key, iconFileElement)) {
+                    querySetIterator.remove();
+                    updates.add(querySet.getOsuInfo());
+                }
+            }
+            if (bssEntries.getValue().isEmpty()) {
+                bssIterator.remove();
+            }
+        }
+
+        initiateQuery(bssid);
+
+        mOSUManager.iconResults(updates);
+    }
+
+    private static final long RequeryTimeLow = 6000L;
+    private static final long RequeryTimeHigh = 15000L;
+
+    public void tickle(boolean wifiOff) {
+        synchronized (mCache) {
+            if (wifiOff) {
+                mBssQueues.clear();
+            } else {
+                long now = System.currentTimeMillis();
+
+                Iterator<Map.Entry<Long, LinkedList<QuerySet>>> bssIterator =
+                        mBssQueues.entrySet().iterator();
+                while (bssIterator.hasNext()) {
+                    // Get the list of entries for this BSSID
+                    Map.Entry<Long, LinkedList<QuerySet>> bssEntries = bssIterator.next();
+                    Iterator<QuerySet> querySetIterator = bssEntries.getValue().iterator();
+                    while (querySetIterator.hasNext()) {
+                        QuerySet querySet = querySetIterator.next();
+                        QueryEntry queryEntry = querySet.peek();
+                        long age = queryEntry.age(now);
+                        if (age > RequeryTimeHigh) {
+                            // Timed out entry, move on to the next.
+                            queryEntry = querySet.pop();
+                            if (queryEntry == null) {
+                                // Empty query set, update status and remove it.
+                                querySet.getOsuInfo()
+                                        .setIconStatus(OSUInfo.IconStatus.NotAvailable);
+                                querySetIterator.remove();
+                            } else {
+                                // Start a query on the next entry and bail out of the set iteration
+                                initiateQuery(querySet.getBssid());
+                                break;
+                            }
+                        } else if (age > RequeryTimeLow) {
+                            // Re-issue queries for qualified entries and bail out of set iteration
+                            initiateQuery(querySet.getBssid());
+                            break;
+                        }
+                    }
+                    if (bssEntries.getValue().isEmpty()) {
+                        // Kill the whole bucket if the set list is empty
+                        bssIterator.remove();
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUCache.java b/packages/Osu/src/com/android/hotspot2/osu/OSUCache.java
new file mode 100644
index 0000000..dadda26
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUCache.java
@@ -0,0 +1,172 @@
+package com.android.hotspot2.osu;
+
+import android.net.wifi.AnqpInformationElement;
+import android.net.wifi.ScanResult;
+import android.util.Log;
+
+import com.android.anqp.Constants;
+import com.android.anqp.HSOsuProvidersElement;
+import com.android.anqp.OSUProvider;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This class holds a stable set of OSU information as well as scan results based on a trail of
+ * scan results.
+ * The purpose of this class is to provide a stable set of information over a a limited span of
+ * time (SCAN_BATCH_HISTORY_SIZE scan batches) so that OSU entries in the selection list does not
+ * come and go with temporarily lost scan results.
+ * The stable set of scan results are used by the remediation flow to retrieve ANQP information
+ * for the current network to determine whether the currently associated network is a roaming
+ * network for the Home SP whose timer has currently fired.
+ */
+public class OSUCache {
+    private static final int SCAN_BATCH_HISTORY_SIZE = 8;
+
+    private int mInstant;
+    private final Map<OSUProvider, ScanResult> mBatchedOSUs = new HashMap<>();
+    private final Map<OSUProvider, ScanInstance> mCache = new HashMap<>();
+
+    private static class ScanInstance {
+        private final ScanResult mScanResult;
+        private int mInstant;
+
+        private ScanInstance(ScanResult scanResult, int instant) {
+            mScanResult = scanResult;
+            mInstant = instant;
+        }
+
+        public ScanResult getScanResult() {
+            return mScanResult;
+        }
+
+        public int getInstant() {
+            return mInstant;
+        }
+
+        private boolean bssidEqual(ScanResult scanResult) {
+            return mScanResult.BSSID.equals(scanResult.BSSID);
+        }
+
+        private void updateInstant(int newInstant) {
+            mInstant = newInstant;
+        }
+
+        @Override
+        public String toString() {
+            return mScanResult.SSID + " @ " + mInstant;
+        }
+    }
+
+    public OSUCache() {
+        mInstant = 0;
+    }
+
+    private void clear() {
+        mBatchedOSUs.clear();
+    }
+
+    public void clearAll() {
+        clear();
+        mCache.clear();
+    }
+
+    public Map<OSUProvider, ScanResult> pushScanResults(Collection<ScanResult> scanResults) {
+        for (ScanResult scanResult : scanResults) {
+            AnqpInformationElement[] osuInfo = scanResult.anqpElements;
+            if (osuInfo != null && osuInfo.length > 0) {
+                putResult(scanResult, osuInfo);
+            }
+        }
+        return scanEnd();
+    }
+
+    private void putResult(ScanResult scanResult, AnqpInformationElement[] elements) {
+        for (AnqpInformationElement ie : elements) {
+            if (ie.getElementId() == AnqpInformationElement.HS_OSU_PROVIDERS
+                    && ie.getVendorId() == AnqpInformationElement.HOTSPOT20_VENDOR_ID) {
+                try {
+                    HSOsuProvidersElement providers = new HSOsuProvidersElement(
+                            Constants.ANQPElementType.HSOSUProviders,
+                            ByteBuffer.wrap(ie.getPayload()).order(ByteOrder.LITTLE_ENDIAN));
+
+                    putProviders(scanResult, providers);
+                } catch (ProtocolException pe) {
+                    Log.w(OSUManager.TAG,
+                            "Failed to parse OSU element: " + pe);
+                }
+            }
+        }
+    }
+
+    private void putProviders(ScanResult scanResult, HSOsuProvidersElement osuProviders) {
+        for (OSUProvider provider : osuProviders.getProviders()) {
+            // Make a predictive put
+            ScanResult existing = mBatchedOSUs.put(provider, scanResult);
+            if (existing != null && existing.level > scanResult.level) {
+                // But undo it if the entry already held a better RSSI
+                mBatchedOSUs.put(provider, existing);
+            }
+        }
+    }
+
+    private Map<OSUProvider, ScanResult> scanEnd() {
+        // Update the trail of OSU Providers:
+        int changes = 0;
+        Map<OSUProvider, ScanInstance> aged = new HashMap<>(mCache);
+        for (Map.Entry<OSUProvider, ScanResult> entry : mBatchedOSUs.entrySet()) {
+            ScanInstance current = aged.remove(entry.getKey());
+            if (current == null || !current.bssidEqual(entry.getValue())) {
+                mCache.put(entry.getKey(), new ScanInstance(entry.getValue(), mInstant));
+                changes++;
+                if (current == null) {
+                    Log.d("ZXZ", "Add OSU " + entry.getKey() + " from " + entry.getValue().SSID);
+                } else {
+                    Log.d("ZXZ", "Update OSU " + entry.getKey() + " with " +
+                            entry.getValue().SSID + " to " + current);
+                }
+            } else {
+                Log.d("ZXZ", "Existing OSU " + entry.getKey() + ", "
+                        + current.getInstant() + " -> " + mInstant);
+                current.updateInstant(mInstant);
+            }
+        }
+
+        for (Map.Entry<OSUProvider, ScanInstance> entry : aged.entrySet()) {
+            if (mInstant - entry.getValue().getInstant() > SCAN_BATCH_HISTORY_SIZE) {
+                Log.d("ZXZ", "Remove OSU " + entry.getKey() + ", "
+                        + entry.getValue().getInstant() + " @ " + mInstant);
+                mCache.remove(entry.getKey());
+                changes++;
+            }
+        }
+
+        mInstant++;
+        clear();
+
+        // Return the latest results if there were any changes from last batch
+        if (changes > 0) {
+            Map<OSUProvider, ScanResult> results = new HashMap<>(mCache.size());
+            for (Map.Entry<OSUProvider, ScanInstance> entry : mCache.entrySet()) {
+                results.put(entry.getKey(), entry.getValue().getScanResult());
+            }
+            return results;
+        } else {
+            return null;
+        }
+    }
+
+    private static String toBSSIDStrings(Set<Long> bssids) {
+        StringBuilder sb = new StringBuilder();
+        for (Long bssid : bssids) {
+            sb.append(String.format(" %012x", bssid));
+        }
+        return sb.toString();
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUCertType.java b/packages/Osu/src/com/android/hotspot2/osu/OSUCertType.java
new file mode 100644
index 0000000..91d7f72
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUCertType.java
@@ -0,0 +1,10 @@
+package com.android.hotspot2.osu;
+
+public enum OSUCertType {
+    CA,
+    Client,
+    AAA,
+    Remediation,
+    Policy,
+    PrivateKey
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUClient.java b/packages/Osu/src/com/android/hotspot2/osu/OSUClient.java
new file mode 100644
index 0000000..12dffe3
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUClient.java
@@ -0,0 +1,485 @@
+package com.android.hotspot2.osu;
+
+/*
+ * policy-server.r2-testbed             IN      A       10.123.107.107
+ * remediation-server.r2-testbed        IN      A       10.123.107.107
+ * subscription-server.r2-testbed       IN      A       10.123.107.107
+ * www.r2-testbed                       IN      A       10.123.107.107
+ * osu-server.r2-testbed-rks            IN      A       10.123.107.107
+ * policy-server.r2-testbed-rks         IN      A       10.123.107.107
+ * remediation-server.r2-testbed-rks    IN      A       10.123.107.107
+ * subscription-server.r2-testbed-rks   IN      A       10.123.107.107
+ */
+
+import android.net.Network;
+import android.util.Log;
+
+import com.android.hotspot2.OMADMAdapter;
+import com.android.hotspot2.est.ESTHandler;
+import com.android.hotspot2.omadm.OMAConstants;
+import com.android.hotspot2.omadm.OMANode;
+import com.android.hotspot2.osu.commands.BrowserURI;
+import com.android.hotspot2.osu.commands.ClientCertInfo;
+import com.android.hotspot2.osu.commands.GetCertData;
+import com.android.hotspot2.osu.commands.MOData;
+import com.android.hotspot2.pps.Credential;
+import com.android.hotspot2.pps.HomeSP;
+import com.android.hotspot2.pps.UpdateInfo;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.net.ssl.KeyManager;
+
+public class OSUClient {
+    private static final String TAG = "OSUCLT";
+    private static final String TTLS_OSU =
+            "https://osu-server.r2-testbed-rks.wi-fi.org:9447/OnlineSignup/services/newUser/digest";
+    private static final String TLS_OSU =
+            "https://osu-server.r2-testbed-rks.wi-fi.org:9446/OnlineSignup/services/newUser/certificate";
+
+    private final OSUInfo mOSUInfo;
+    private final URL mURL;
+    private final KeyStore mKeyStore;
+
+    public OSUClient(OSUInfo osuInfo, KeyStore ks) throws MalformedURLException {
+        mOSUInfo = osuInfo;
+        mURL = new URL(osuInfo.getOSUProvider().getOSUServer());
+        mKeyStore = ks;
+    }
+
+    public OSUClient(String osu, KeyStore ks) throws MalformedURLException {
+        mOSUInfo = null;
+        mURL = new URL(osu);
+        mKeyStore = ks;
+    }
+
+    public void provision(OSUManager osuManager, Network network, KeyManager km)
+            throws IOException, GeneralSecurityException {
+        try (HTTPHandler httpHandler = new HTTPHandler(StandardCharsets.UTF_8,
+                OSUSocketFactory.getSocketFactory(mKeyStore, null, OSUManager.FLOW_PROVISIONING,
+                        network, mURL, km, true))) {
+
+            SPVerifier spVerifier = new SPVerifier(mOSUInfo);
+            spVerifier.verify(httpHandler.getOSUCertificate(mURL));
+
+            URL redirectURL = osuManager.prepareUserInput(mOSUInfo.getName(Locale.getDefault()));
+            OMADMAdapter omadmAdapter = osuManager.getOMADMAdapter();
+
+            String regRequest = SOAPBuilder.buildPostDevDataResponse(RequestReason.SubRegistration,
+                    null,
+                    redirectURL.toString(),
+                    omadmAdapter.getMO(OMAConstants.DevInfoURN),
+                    omadmAdapter.getMO(OMAConstants.DevDetailURN));
+            Log.d(TAG, "Registration request: " + regRequest);
+            OSUResponse osuResponse = httpHandler.exchangeSOAP(mURL, regRequest);
+
+            Log.d(TAG, "Response: " + osuResponse);
+            if (osuResponse.getMessageType() != OSUMessageType.PostDevData) {
+                throw new IOException("Expected a PostDevDataResponse");
+            }
+            PostDevDataResponse regResponse = (PostDevDataResponse) osuResponse;
+            String sessionID = regResponse.getSessionID();
+            if (regResponse.getExecCommand() == ExecCommand.UseClientCertTLS) {
+                ClientCertInfo ccInfo = (ClientCertInfo) regResponse.getCommandData();
+                if (ccInfo.doesAcceptMfgCerts()) {
+                    throw new IOException("Mfg certs are not supported in Android");
+                } else if (ccInfo.doesAcceptProviderCerts()) {
+                    ((WiFiKeyManager) km).enableClientAuth(ccInfo.getIssuerNames());
+                    httpHandler.renegotiate(null, null);
+                } else {
+                    throw new IOException("Neither manufacturer nor provider cert specified");
+                }
+                regRequest = SOAPBuilder.buildPostDevDataResponse(RequestReason.SubRegistration,
+                        sessionID,
+                        redirectURL.toString(),
+                        omadmAdapter.getMO(OMAConstants.DevInfoURN),
+                        omadmAdapter.getMO(OMAConstants.DevDetailURN));
+
+                osuResponse = httpHandler.exchangeSOAP(mURL, regRequest);
+                if (osuResponse.getMessageType() != OSUMessageType.PostDevData) {
+                    throw new IOException("Expected a PostDevDataResponse");
+                }
+                regResponse = (PostDevDataResponse) osuResponse;
+            }
+
+            if (regResponse.getExecCommand() != ExecCommand.Browser) {
+                throw new IOException("Expected a launchBrowser command");
+            }
+            Log.d(TAG, "Exec: " + regResponse.getExecCommand() + ", for '" +
+                    regResponse.getCommandData() + "'");
+
+            if (!osuResponse.getSessionID().equals(sessionID)) {
+                throw new IOException("Mismatching session IDs");
+            }
+            String webURL = ((BrowserURI) regResponse.getCommandData()).getURI();
+
+            if (webURL == null) {
+                throw new IOException("No web-url");
+            } else if (!webURL.contains(sessionID)) {
+                throw new IOException("Bad or missing session ID in webURL");
+            }
+
+            if (!osuManager.startUserInput(new URL(webURL), network)) {
+                throw new IOException("User session failed");
+            }
+
+            Log.d(TAG, " -- Sending user input complete:");
+            String userComplete = SOAPBuilder.buildPostDevDataResponse(RequestReason.InputComplete,
+                    sessionID, null,
+                    omadmAdapter.getMO(OMAConstants.DevInfoURN),
+                    omadmAdapter.getMO(OMAConstants.DevDetailURN));
+            OSUResponse moResponse1 = httpHandler.exchangeSOAP(mURL, userComplete);
+            if (moResponse1.getMessageType() != OSUMessageType.PostDevData) {
+                throw new IOException("Bad user input complete response: " + moResponse1);
+            }
+            PostDevDataResponse provResponse = (PostDevDataResponse) moResponse1;
+            GetCertData estData = checkResponse(provResponse);
+
+            Map<OSUCertType, List<X509Certificate>> certs = new HashMap<>();
+            PrivateKey clientKey = null;
+
+            MOData moData;
+            if (estData == null) {
+                moData = (MOData) provResponse.getCommandData();
+            } else {
+                try (ESTHandler estHandler = new ESTHandler((GetCertData) provResponse.
+                        getCommandData(), network, osuManager.getOMADMAdapter(),
+                        km, mKeyStore, null, OSUManager.FLOW_PROVISIONING)) {
+                    estHandler.execute(false);
+                    certs.put(OSUCertType.CA, estHandler.getCACerts());
+                    certs.put(OSUCertType.Client, estHandler.getClientCerts());
+                    clientKey = estHandler.getClientKey();
+                }
+
+                Log.d(TAG, " -- Sending provisioning cert enrollment complete:");
+                String certComplete =
+                        SOAPBuilder.buildPostDevDataResponse(RequestReason.CertEnrollmentComplete,
+                                sessionID, null,
+                                omadmAdapter.getMO(OMAConstants.DevInfoURN),
+                                omadmAdapter.getMO(OMAConstants.DevDetailURN));
+                OSUResponse moResponse2 = httpHandler.exchangeSOAP(mURL, certComplete);
+                if (moResponse2.getMessageType() != OSUMessageType.PostDevData) {
+                    throw new IOException("Bad cert enrollment complete response: " + moResponse2);
+                }
+                PostDevDataResponse provComplete = (PostDevDataResponse) moResponse2;
+                if (provComplete.getStatus() != OSUStatus.ProvComplete ||
+                        provComplete.getOSUCommand() != OSUCommandID.AddMO) {
+                    throw new IOException("Expected addMO: " + provComplete);
+                }
+                moData = (MOData) provComplete.getCommandData();
+            }
+
+            // !!! How can an ExchangeComplete be sent w/o knowing the fate of the certs???
+            String updateResponse = SOAPBuilder.buildUpdateResponse(sessionID, null);
+            Log.d(TAG, " -- Sending updateResponse:");
+            OSUResponse exComplete = httpHandler.exchangeSOAP(mURL, updateResponse);
+            Log.d(TAG, "exComplete response: " + exComplete);
+            if (exComplete.getMessageType() != OSUMessageType.ExchangeComplete) {
+                throw new IOException("Expected ExchangeComplete: " + exComplete);
+            } else if (exComplete.getStatus() != OSUStatus.ExchangeComplete) {
+                throw new IOException("Bad ExchangeComplete status: " + exComplete);
+            }
+
+            retrieveCerts(moData.getMOTree().getRoot(), certs, network, km, mKeyStore);
+            osuManager.provisioningComplete(mOSUInfo, moData, certs, clientKey, network);
+        }
+    }
+
+    public void remediate(OSUManager osuManager, Network network, KeyManager km, HomeSP homeSP,
+                          int flowType)
+            throws IOException, GeneralSecurityException {
+        try (HTTPHandler httpHandler = createHandler(network, homeSP, km, flowType)) {
+            URL redirectURL = osuManager.prepareUserInput(homeSP.getFriendlyName());
+            OMADMAdapter omadmAdapter = osuManager.getOMADMAdapter();
+
+            String regRequest = SOAPBuilder.buildPostDevDataResponse(RequestReason.SubRemediation,
+                    null,
+                    redirectURL.toString(),
+                    omadmAdapter.getMO(OMAConstants.DevInfoURN),
+                    omadmAdapter.getMO(OMAConstants.DevDetailURN));
+
+            OSUResponse serverResponse = httpHandler.exchangeSOAP(mURL, regRequest);
+            if (serverResponse.getMessageType() != OSUMessageType.PostDevData) {
+                throw new IOException("Expected a PostDevDataResponse");
+            }
+            String sessionID = serverResponse.getSessionID();
+
+            PostDevDataResponse pddResponse = (PostDevDataResponse) serverResponse;
+            Log.d(TAG, "Remediation response: " + pddResponse);
+
+            Map<OSUCertType, List<X509Certificate>> certs = null;
+            PrivateKey clientKey = null;
+
+            if (pddResponse.getStatus() != OSUStatus.RemediationComplete) {
+                if (pddResponse.getExecCommand() == ExecCommand.UploadMO) {
+                    String ulMessage = SOAPBuilder.buildPostDevDataResponse(RequestReason.MOUpload,
+                            null,
+                            redirectURL.toString(),
+                            omadmAdapter.getMO(OMAConstants.DevInfoURN),
+                            omadmAdapter.getMO(OMAConstants.DevDetailURN),
+                            osuManager.getMOTree(homeSP));
+
+                    Log.d(TAG, "Upload MO: " + ulMessage);
+
+                    OSUResponse ulResponse = httpHandler.exchangeSOAP(mURL, ulMessage);
+                    if (ulResponse.getMessageType() != OSUMessageType.PostDevData) {
+                        throw new IOException("Expected a PostDevDataResponse to MOUpload");
+                    }
+                    pddResponse = (PostDevDataResponse) ulResponse;
+                }
+
+                if (pddResponse.getExecCommand() == ExecCommand.Browser) {
+                    if (flowType == OSUManager.FLOW_POLICY) {
+                        throw new IOException("Browser launch requested in policy flow");
+                    }
+                    String webURL = ((BrowserURI) pddResponse.getCommandData()).getURI();
+
+                    if (webURL == null) {
+                        throw new IOException("No web-url");
+                    } else if (!webURL.contains(sessionID)) {
+                        throw new IOException("Bad or missing session ID in webURL");
+                    }
+
+                    if (!osuManager.startUserInput(new URL(webURL), network)) {
+                        throw new IOException("User session failed");
+                    }
+
+                    Log.d(TAG, " -- Sending user input complete:");
+                    String userComplete =
+                            SOAPBuilder.buildPostDevDataResponse(RequestReason.InputComplete,
+                                    sessionID, null,
+                                    omadmAdapter.getMO(OMAConstants.DevInfoURN),
+                                    omadmAdapter.getMO(OMAConstants.DevDetailURN));
+
+                    OSUResponse udResponse = httpHandler.exchangeSOAP(mURL, userComplete);
+                    if (udResponse.getMessageType() != OSUMessageType.PostDevData) {
+                        throw new IOException("Bad user input complete response: " + udResponse);
+                    }
+                    pddResponse = (PostDevDataResponse) udResponse;
+                } else if (pddResponse.getExecCommand() == ExecCommand.GetCert) {
+                    certs = new HashMap<>();
+                    try (ESTHandler estHandler = new ESTHandler((GetCertData) pddResponse.
+                            getCommandData(), network, osuManager.getOMADMAdapter(),
+                            km, mKeyStore, homeSP, flowType)) {
+                        estHandler.execute(true);
+                        certs.put(OSUCertType.CA, estHandler.getCACerts());
+                        certs.put(OSUCertType.Client, estHandler.getClientCerts());
+                        clientKey = estHandler.getClientKey();
+                    }
+
+                    if (httpHandler.isHTTPAuthPerformed()) {        // 8.4.3.6
+                        httpHandler.renegotiate(certs, clientKey);
+                    }
+
+                    Log.d(TAG, " -- Sending remediation cert enrollment complete:");
+                    // 8.4.3.5 in the spec actually prescribes that an update URI is sent here,
+                    // but there is no remediation flow that defines user interaction after EST
+                    // so for now a null is passed.
+                    String certComplete =
+                            SOAPBuilder
+                                    .buildPostDevDataResponse(RequestReason.CertEnrollmentComplete,
+                                            sessionID, null,
+                                            omadmAdapter.getMO(OMAConstants.DevInfoURN),
+                                            omadmAdapter.getMO(OMAConstants.DevDetailURN));
+                    OSUResponse ceResponse = httpHandler.exchangeSOAP(mURL, certComplete);
+                    if (ceResponse.getMessageType() != OSUMessageType.PostDevData) {
+                        throw new IOException("Bad cert enrollment complete response: "
+                                + ceResponse);
+                    }
+                    pddResponse = (PostDevDataResponse) ceResponse;
+                } else {
+                    throw new IOException("Unexpected command: " + pddResponse.getExecCommand());
+                }
+            }
+
+            if (pddResponse.getStatus() != OSUStatus.RemediationComplete) {
+                throw new IOException("Expected a PostDevDataResponse to MOUpload");
+            }
+
+            Log.d(TAG, "Remediation response: " + pddResponse);
+
+            List<MOData> mods = new ArrayList<>();
+            for (OSUCommand command : pddResponse.getCommands()) {
+                if (command.getOSUCommand() == OSUCommandID.UpdateNode) {
+                    mods.add((MOData) command.getCommandData());
+                } else if (command.getOSUCommand() != OSUCommandID.NoMOUpdate) {
+                    throw new IOException("Unexpected OSU response: " + command);
+                }
+            }
+
+            // 1. Machine remediation: Remediation complete + replace node
+            // 2a. User remediation with upload: ExecCommand.UploadMO
+            // 2b. User remediation without upload: ExecCommand.Browser
+            // 3. User remediation only: -> sppPostDevData user input complete
+            //
+            // 4. Update node
+            // 5. -> Update response
+            // 6. Exchange complete
+
+            OSUError error = null;
+
+            String updateResponse = SOAPBuilder.buildUpdateResponse(sessionID, error);
+            Log.d(TAG, " -- Sending updateResponse:");
+            OSUResponse exComplete = httpHandler.exchangeSOAP(mURL, updateResponse);
+            Log.d(TAG, "exComplete response: " + exComplete);
+            if (exComplete.getMessageType() != OSUMessageType.ExchangeComplete) {
+                throw new IOException("Expected ExchangeComplete: " + exComplete);
+            } else if (exComplete.getStatus() != OSUStatus.ExchangeComplete) {
+                throw new IOException("Bad ExchangeComplete status: " + exComplete);
+            }
+
+            // There's a chicken and egg here: If the config is saved before sending update complete
+            // the network is lost and the remediation flow fails.
+            try {
+                osuManager.remediationComplete(homeSP, mods, certs, clientKey);
+            } catch (IOException | GeneralSecurityException e) {
+                osuManager.provisioningFailed(homeSP.getFriendlyName(), e.getMessage(), homeSP,
+                        OSUManager.FLOW_REMEDIATION);
+                error = OSUError.CommandFailed;
+            }
+        }
+    }
+
+    private HTTPHandler createHandler(Network network, HomeSP homeSP,
+                                      KeyManager km, int flowType) throws GeneralSecurityException, IOException {
+        Credential credential = homeSP.getCredential();
+
+        Log.d(TAG, "Credential method " + credential.getEAPMethod().getEAPMethodID());
+        switch (credential.getEAPMethod().getEAPMethodID()) {
+            case EAP_TTLS:
+                String user;
+                byte[] password;
+                UpdateInfo subscriptionUpdate;
+                if (flowType == OSUManager.FLOW_POLICY) {
+                    subscriptionUpdate = homeSP.getPolicy() != null ?
+                            homeSP.getPolicy().getPolicyUpdate() : null;
+                } else {
+                    subscriptionUpdate = homeSP.getSubscriptionUpdate();
+                }
+                if (subscriptionUpdate != null && subscriptionUpdate.getUsername() != null) {
+                    user = subscriptionUpdate.getUsername();
+                    password = subscriptionUpdate.getPassword() != null ?
+                            subscriptionUpdate.getPassword().getBytes(StandardCharsets.UTF_8) :
+                            new byte[0];
+                } else {
+                    user = credential.getUserName();
+                    password = credential.getPassword().getBytes(StandardCharsets.UTF_8);
+                }
+                return new HTTPHandler(StandardCharsets.UTF_8,
+                        OSUSocketFactory.getSocketFactory(mKeyStore, homeSP, flowType, network,
+                                mURL, km, true), user, password);
+            case EAP_TLS:
+                return new HTTPHandler(StandardCharsets.UTF_8,
+                        OSUSocketFactory.getSocketFactory(mKeyStore, homeSP, flowType, network,
+                                mURL, km, true));
+            default:
+                throw new IOException("Cannot remediate account with " +
+                        credential.getEAPMethod().getEAPMethodID());
+        }
+    }
+
+    private static GetCertData checkResponse(PostDevDataResponse response) throws IOException {
+        if (response.getStatus() == OSUStatus.ProvComplete &&
+                response.getOSUCommand() == OSUCommandID.AddMO) {
+            return null;
+        }
+
+        if (response.getOSUCommand() == OSUCommandID.Exec &&
+                response.getExecCommand() == ExecCommand.GetCert) {
+            return (GetCertData) response.getCommandData();
+        } else {
+            throw new IOException("Unexpected command: " + response);
+        }
+    }
+
+    private static final String[] AAACertPath =
+            {"PerProviderSubscription", "?", "AAAServerTrustRoot", "*", "CertURL"};
+    private static final String[] RemdCertPath =
+            {"PerProviderSubscription", "?", "SubscriptionUpdate", "TrustRoot", "CertURL"};
+    private static final String[] PolicyCertPath =
+            {"PerProviderSubscription", "?", "Policy", "PolicyUpdate", "TrustRoot", "CertURL"};
+
+    private static void retrieveCerts(OMANode ppsRoot,
+                                      Map<OSUCertType, List<X509Certificate>> certs,
+                                      Network network, KeyManager km, KeyStore ks)
+            throws GeneralSecurityException, IOException {
+
+        List<X509Certificate> aaaCerts = getCerts(ppsRoot, AAACertPath, network, km, ks);
+        certs.put(OSUCertType.AAA, aaaCerts);
+        certs.put(OSUCertType.Remediation, getCerts(ppsRoot, RemdCertPath, network, km, ks));
+        certs.put(OSUCertType.Policy, getCerts(ppsRoot, PolicyCertPath, network, km, ks));
+    }
+
+    private static List<X509Certificate> getCerts(OMANode ppsRoot, String[] path, Network network,
+                                                  KeyManager km, KeyStore ks)
+            throws GeneralSecurityException, IOException {
+        List<String> urls = new ArrayList<>();
+        getCertURLs(ppsRoot, Arrays.asList(path).iterator(), urls);
+        Log.d(TAG, Arrays.toString(path) + ": " + urls);
+
+        List<X509Certificate> certs = new ArrayList<>(urls.size());
+        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+        for (String urlString : urls) {
+            URL url = new URL(urlString);
+            HTTPHandler httpHandler = new HTTPHandler(StandardCharsets.UTF_8,
+                    OSUSocketFactory.getSocketFactory(ks, null, OSUManager.FLOW_PROVISIONING,
+                            network, url, km, false));
+
+            certs.add((X509Certificate) certFactory.generateCertificate(httpHandler.doGet(url)));
+        }
+        return certs;
+    }
+
+    private static void getCertURLs(OMANode root, Iterator<String> path, List<String> urls)
+            throws IOException {
+
+        String name = path.next();
+        // Log.d(TAG, "Pulling '" + name + "' out of '" + root.getName() + "'");
+        Collection<OMANode> nodes = null;
+        switch (name) {
+            case "?":
+                for (OMANode node : root.getChildren()) {
+                    if (!node.isLeaf()) {
+                        nodes = Arrays.asList(node);
+                        break;
+                    }
+                }
+                break;
+            case "*":
+                nodes = root.getChildren();
+                break;
+            default:
+                nodes = Arrays.asList(root.getChild(name));
+                break;
+        }
+
+        if (nodes == null) {
+            throw new IllegalArgumentException("No matching node in " + root.getName()
+                    + " for " + name);
+        }
+
+        for (OMANode node : nodes) {
+            if (path.hasNext()) {
+                getCertURLs(node, path, urls);
+            } else {
+                urls.add(node.getValue());
+            }
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUCommand.java b/packages/Osu/src/com/android/hotspot2/osu/OSUCommand.java
new file mode 100644
index 0000000..4730377
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUCommand.java
@@ -0,0 +1,130 @@
+package com.android.hotspot2.osu;
+
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.XMLNode;
+import com.android.hotspot2.osu.commands.BrowserURI;
+import com.android.hotspot2.osu.commands.ClientCertInfo;
+import com.android.hotspot2.osu.commands.GetCertData;
+import com.android.hotspot2.osu.commands.MOData;
+import com.android.hotspot2.osu.commands.MOURN;
+import com.android.hotspot2.osu.commands.OSUCommandData;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class OSUCommand {
+    private final OSUCommandID mOSUCommand;
+    private final ExecCommand mExecCommand;
+    private final OSUCommandData mCommandData;
+
+    private static final Map<String, OSUCommandID> sCommands = new HashMap<>();
+    private static final Map<String, ExecCommand> sExecs = new HashMap<>();
+
+    static {
+        sCommands.put("exec", OSUCommandID.Exec);
+        sCommands.put("addmo", OSUCommandID.AddMO);
+        sCommands.put("updatenode", OSUCommandID.UpdateNode);      // Multi
+        sCommands.put("nomoupdate", OSUCommandID.NoMOUpdate);
+
+        sExecs.put("launchbrowsertouri", ExecCommand.Browser);
+        sExecs.put("getcertificate", ExecCommand.GetCert);
+        sExecs.put("useclientcerttls", ExecCommand.UseClientCertTLS);
+        sExecs.put("uploadmo", ExecCommand.UploadMO);
+    }
+
+    public OSUCommand(XMLNode child) throws OMAException {
+        mOSUCommand = sCommands.get(child.getStrippedTag());
+
+        switch (mOSUCommand) {
+            case Exec:
+                /*
+                 * Receipt of this element by a mobile device causes the following command
+                 * to be executed.
+                 */
+                child = child.getSoleChild();
+                mExecCommand = sExecs.get(child.getStrippedTag());
+                if (mExecCommand == null) {
+                    throw new OMAException("Unrecognized exec command: " + child.getStrippedTag());
+                }
+                switch (mExecCommand) {
+                    case Browser:
+                        /*
+                         * When the mobile device receives this command, it launches its default
+                         * browser to the URI contained in this element. The URI must use HTTPS as
+                         * the protocol and must contain an FQDN.
+                         */
+                        mCommandData = new BrowserURI(child);
+                        break;
+                    case GetCert:
+                        mCommandData = new GetCertData(child);
+                        break;
+                    case UploadMO:
+                        mCommandData = new MOURN(child);
+                        break;
+                    case UseClientCertTLS:
+                        /*
+                         * Command to mobile to re-negotiate the TLS connection using a client
+                         * certificate of the accepted type or Issuer to authenticate with the
+                         * Subscription server.
+                         */
+                        mCommandData = new ClientCertInfo(child);
+                        break;
+                    default:
+                        mCommandData = null;
+                        break;
+                }
+                break;
+            case AddMO:
+                /*
+                 * This command causes an management object in the mobile devices management tree
+                 * at the specified location to be added.
+                 * If there is already a management object at that location, the object is replaced.
+                 */
+                mExecCommand = null;
+                mCommandData = new MOData(child);
+                break;
+            case UpdateNode:
+                /*
+                 * This command causes the update of an interior node and its child nodes (if any)
+                 * at the location specified in the management tree URI attribute. The content of
+                 * this element is the MO node XML.
+                 */
+                mExecCommand = null;
+                mCommandData = new MOData(child);
+                break;
+            case NoMOUpdate:
+                /*
+                 * This response is used when there is no command to be executed nor update of
+                 * any MO required.
+                 */
+                mExecCommand = null;
+                mCommandData = null;
+                break;
+            default:
+                mExecCommand = null;
+                mCommandData = null;
+                break;
+        }
+    }
+
+    public OSUCommandID getOSUCommand() {
+        return mOSUCommand;
+    }
+
+    public ExecCommand getExecCommand() {
+        return mExecCommand;
+    }
+
+    public OSUCommandData getCommandData() {
+        return mCommandData;
+    }
+
+    @Override
+    public String toString() {
+        return "OSUCommand{" +
+                "OSUCommand=" + mOSUCommand +
+                ", execCommand=" + mExecCommand +
+                ", commandData=" + mCommandData +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUCommandID.java b/packages/Osu/src/com/android/hotspot2/osu/OSUCommandID.java
new file mode 100644
index 0000000..eca953f
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUCommandID.java
@@ -0,0 +1,5 @@
+package com.android.hotspot2.osu;
+
+public enum OSUCommandID {
+    Exec, AddMO, UpdateNode, NoMOUpdate
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUError.java b/packages/Osu/src/com/android/hotspot2/osu/OSUError.java
new file mode 100644
index 0000000..2fa7de0
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUError.java
@@ -0,0 +1,22 @@
+package com.android.hotspot2.osu;
+
+public enum OSUError {
+    SPPversionNotSupported,
+    MOsNotSupported,
+    CredentialsFailure,
+    RemediationFailure,
+    ProvisioningFailed,
+    ExistingCertificate,
+    CookieInvalid,
+    WebSessionID,
+    PermissionDenied,
+    CommandFailed,
+    MOaddOrUpdateFailed,
+    DeviceFull,
+    BadTreeURI,
+    TooLarge,
+    CommandNotAllowed,
+    UserAborted,
+    NotFound,
+    Other
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUInfo.java b/packages/Osu/src/com/android/hotspot2/osu/OSUInfo.java
new file mode 100644
index 0000000..86c0be9
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUInfo.java
@@ -0,0 +1,252 @@
+package com.android.hotspot2.osu;
+
+import android.net.wifi.ScanResult;
+import android.util.Log;
+
+import com.android.anqp.HSIconFileElement;
+import com.android.anqp.I18Name;
+import com.android.anqp.IconInfo;
+import com.android.anqp.OSUProvider;
+import com.android.hotspot2.Utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+public class OSUInfo {
+    public static final String GenericLocale = "zxx";
+
+    public enum IconStatus {
+        NotQueried,     //
+        InProgress,     // Query pending
+        NotAvailable,   // Deterministically unavailable
+        Available       // Icon data retrieved
+    }
+
+    private final long mBSSID;
+    private final long mHESSID;
+    private final int mAnqpDomID;
+    private final String mSSID;
+    private final String mAdvertisingSSID;
+    private final OSUProvider mOSUProvider;
+    private final int mOsuID;
+    private long mOSUBssid;
+    private IconStatus mIconStatus = IconStatus.NotQueried;
+    private HSIconFileElement mIconFileElement;
+    private IconInfo mIconInfo;
+
+    public OSUInfo(ScanResult scanResult, String ssid, OSUProvider osuProvider, int osuID) {
+        mOsuID = osuID;
+        mBSSID = Utils.parseMac(scanResult.BSSID);
+        mHESSID = scanResult.hessid;
+        mAnqpDomID = scanResult.anqpDomainId;
+        mAdvertisingSSID = scanResult.SSID;
+        mSSID = ssid;
+        mOSUProvider = osuProvider;
+    }
+
+    public long getOSUBssid() {
+        return mOSUBssid;
+    }
+
+    public void setOSUBssid(long OSUBssid) {
+        mOSUBssid = OSUBssid;
+    }
+
+    public long getHESSID() {
+        return mHESSID;
+    }
+
+    public int getAnqpDomID() {
+        return mAnqpDomID;
+    }
+
+    public String getAdvertisingSSID() {
+        return mAdvertisingSSID;
+    }
+
+    public Set<Locale> getNameLocales() {
+        Set<Locale> locales = new HashSet<>(mOSUProvider.getNames().size());
+        for (I18Name name : mOSUProvider.getNames()) {
+            locales.add(name.getLocale());
+        }
+        return locales;
+    }
+
+    public Set<Locale> getServiceLocales() {
+        Set<Locale> locales = new HashSet<>(mOSUProvider.getServiceDescriptions().size());
+        for (I18Name name : mOSUProvider.getServiceDescriptions()) {
+            locales.add(name.getLocale());
+        }
+        return locales;
+    }
+
+    public Set<String> getIconLanguages() {
+        Set<String> locales = new HashSet<>(mOSUProvider.getIcons().size());
+        for (IconInfo iconInfo : mOSUProvider.getIcons()) {
+            locales.add(iconInfo.getLanguage());
+        }
+        return locales;
+    }
+
+    public String getName(Locale locale) {
+        List<ScoreEntry<String>> scoreList = new ArrayList<>();
+        for (I18Name name : mOSUProvider.getNames()) {
+            if (locale == null || name.getLocale().equals(locale)) {
+                return name.getText();
+            }
+            scoreList.add(new ScoreEntry<String>(name.getText(),
+                    languageScore(name.getLanguage(), locale)));
+        }
+        Collections.sort(scoreList);
+        return scoreList.isEmpty() ? null : scoreList.iterator().next().getData();
+    }
+
+    public String getServiceDescription(Locale locale) {
+        List<ScoreEntry<String>> scoreList = new ArrayList<>();
+        for (I18Name service : mOSUProvider.getServiceDescriptions()) {
+            if (locale == null || service.getLocale().equals(locale)) {
+                return service.getText();
+            }
+            scoreList.add(new ScoreEntry<>(service.getText(),
+                    languageScore(service.getLanguage(), locale)));
+        }
+        Collections.sort(scoreList);
+        return scoreList.isEmpty() ? null : scoreList.iterator().next().getData();
+    }
+
+    public int getOsuID() {
+        return mOsuID;
+    }
+
+    public void setIconStatus(IconStatus iconStatus) {
+        synchronized (mOSUProvider) {
+            mIconStatus = iconStatus;
+        }
+    }
+
+    public IconStatus getIconStatus() {
+        synchronized (mOSUProvider) {
+            return mIconStatus;
+        }
+    }
+
+    public HSIconFileElement getIconFileElement() {
+        synchronized (mOSUProvider) {
+            return mIconFileElement;
+        }
+    }
+
+    public IconInfo getIconInfo() {
+        synchronized (mOSUProvider) {
+            return mIconInfo;
+        }
+    }
+
+    public void setIconFileElement(HSIconFileElement iconFileElement, String fileName) {
+        synchronized (mOSUProvider) {
+            mIconFileElement = iconFileElement;
+            for (IconInfo iconInfo : mOSUProvider.getIcons()) {
+                if (iconInfo.getFileName().equals(fileName)) {
+                    mIconInfo = iconInfo;
+                    break;
+                }
+            }
+            mIconStatus = IconStatus.Available;
+        }
+    }
+
+    private static class ScoreEntry<T> implements Comparable<ScoreEntry> {
+        private final T mData;
+        private final int mScore;
+
+        private ScoreEntry(T data, int score) {
+            mData = data;
+            mScore = score;
+        }
+
+        public T getData() {
+            return mData;
+        }
+
+        @Override
+        public int compareTo(ScoreEntry other) {
+            return Integer.compare(mScore, other.mScore);
+        }
+    }
+
+    public List<IconInfo> getIconInfo(Locale locale, Set<String> types, int width, int height) {
+        if (mOSUProvider.getIcons().isEmpty()) {
+            return null;
+        }
+        Log.d(OSUManager.TAG, "Matching icons against " + locale
+                + ", types " + types + ", " + width + "*" + height);
+
+        List<ScoreEntry<IconInfo>> matches = new ArrayList<>();
+        for (IconInfo iconInfo : mOSUProvider.getIcons()) {
+            Log.d(OSUManager.TAG, "Checking icon " + iconInfo.toString());
+            if (!types.contains(iconInfo.getIconType())) {
+                continue;
+            }
+
+            int score = languageScore(iconInfo.getLanguage(), locale);
+            int delta = iconInfo.getWidth() - width;
+            // Best size score is 1024 for a exact match, i.e. 2048 if both sides match
+            if (delta >= 0) {
+                score += (256 - delta) * 4;  // Prefer down-scaling
+            } else {
+                score += 256 + delta;    // Before up-scaling
+            }
+            delta = iconInfo.getHeight() - height;
+            if (delta >= 0) {
+                score += (256 - delta) * 4;
+            } else {
+                score += 256 + delta;
+            }
+            matches.add(new ScoreEntry<>(iconInfo, score));
+        }
+        if (matches.isEmpty()) {
+            return Collections.emptyList();
+        }
+        Collections.sort(matches);
+        List<IconInfo> icons = new ArrayList<>(matches.size());
+        for (ScoreEntry<IconInfo> scoredIcon : matches) {
+            icons.add(scoredIcon.getData());
+        }
+        return icons;
+    }
+
+    private static int languageScore(String language, Locale locale) {
+        if (language.length() == 3 && language.equalsIgnoreCase(locale.getISO3Language()) ||
+                language.length() == 2 && language.equalsIgnoreCase(locale.getLanguage())) {
+            return 4096;
+        } else if (language.equalsIgnoreCase(GenericLocale)) {
+            return 3072;
+        } else if (language.equalsIgnoreCase("eng")) {
+            return 2048;
+        } else {
+            return 1024;
+        }
+    }
+
+    public long getBSSID() {
+        return mBSSID;
+    }
+
+    public String getSSID() {
+        return mSSID;
+    }
+
+    public OSUProvider getOSUProvider() {
+        return mOSUProvider;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("OSU Info '%s' %012x -> %s, icon %s",
+                mSSID, mBSSID, getServiceDescription(null), mIconStatus);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUListener.java b/packages/Osu/src/com/android/hotspot2/osu/OSUListener.java
new file mode 100644
index 0000000..9197620
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUListener.java
@@ -0,0 +1,5 @@
+package com.android.hotspot2.osu;
+
+public interface OSUListener {
+    public void osuNotification(int count);
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUManager.java b/packages/Osu/src/com/android/hotspot2/osu/OSUManager.java
new file mode 100644
index 0000000..c90e96b
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUManager.java
@@ -0,0 +1,977 @@
+package com.android.hotspot2.osu;
+
+import android.content.Context;
+import android.net.Network;
+import android.net.NetworkInfo;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.util.Log;
+
+import com.android.anqp.Constants;
+import com.android.anqp.OSUProvider;
+import com.android.hotspot2.AppBridge;
+import com.android.hotspot2.OMADMAdapter;
+import com.android.hotspot2.PasspointMatch;
+import com.android.hotspot2.Utils;
+import com.android.hotspot2.WifiNetworkAdapter;
+import com.android.hotspot2.omadm.MOManager;
+import com.android.hotspot2.omadm.MOTree;
+import com.android.hotspot2.osu.commands.MOData;
+import com.android.hotspot2.osu.service.RedirectListener;
+import com.android.hotspot2.osu.service.SubscriptionTimer;
+import com.android.hotspot2.pps.HomeSP;
+import com.android.hotspot2.pps.UpdateInfo;
+
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.net.ssl.KeyManager;
+
+public class OSUManager {
+    public static final String TAG = "OSUMGR";
+    public static final boolean R2_ENABLED = true;
+    public static final boolean R2_MOCK = true;
+    private static final boolean MATCH_BSSID = false;
+
+    private static final String KEYSTORE_FILE = "passpoint.ks";
+    private static final String WFA_CA_LOC = "/etc/security/wfa";
+
+    private static final String OSU_COUNT = "osu-count";
+    private static final String SP_NAME = "sp-name";
+    private static final String PROV_SUCCESS = "prov-success";
+    private static final String DEAUTH = "deauth";
+    private static final String DEAUTH_DELAY = "deauth-delay";
+    private static final String DEAUTH_URL = "deauth-url";
+    private static final String PROV_MESSAGE = "prov-message";
+
+    private static final long REMEDIATION_TIMEOUT = 120000L;
+    // How many scan result batches to hang on to
+
+    public static final int FLOW_PROVISIONING = 1;
+    public static final int FLOW_REMEDIATION = 2;
+    public static final int FLOW_POLICY = 3;
+
+    public static final String CERT_WFA_ALIAS = "wfa-root-";
+    public static final String CERT_REM_ALIAS = "rem-";
+    public static final String CERT_POLICY_ALIAS = "pol-";
+    public static final String CERT_SHARED_ALIAS = "shr-";
+    public static final String CERT_CLT_CERT_ALIAS = "clt-";
+    public static final String CERT_CLT_KEY_ALIAS = "prv-";
+    public static final String CERT_CLT_CA_ALIAS = "aaa-";
+
+    // Preferred icon parameters
+    private static final Set<String> ICON_TYPES =
+            new HashSet<>(Arrays.asList("image/png", "image/jpeg"));
+    private static final int ICON_WIDTH = 64;
+    private static final int ICON_HEIGHT = 64;
+    public static final Locale LOCALE = java.util.Locale.getDefault();
+
+    private final WifiNetworkAdapter mWifiNetworkAdapter;
+
+    private final AppBridge mAppBridge;
+    private final Context mContext;
+    private final IconCache mIconCache;
+    private final SubscriptionTimer mSubscriptionTimer;
+    private final Set<String> mOSUSSIDs = new HashSet<>();
+    private final Map<OSUProvider, OSUInfo> mOSUMap = new HashMap<>();
+    private final KeyStore mKeyStore;
+    private RedirectListener mRedirectListener;
+    private final AtomicInteger mOSUSequence = new AtomicInteger();
+    private OSUThread mProvisioningThread;
+    private final Map<String, OSUThread> mServiceThreads = new HashMap<>();
+    private volatile OSUInfo mPendingOSU;
+    private volatile Integer mOSUNwkID;
+
+    private final OSUCache mOSUCache;
+
+    public OSUManager(Context context) {
+        mContext = context;
+        mAppBridge = new AppBridge(context);
+        mIconCache = new IconCache(this);
+        mWifiNetworkAdapter = new WifiNetworkAdapter(context, this);
+        mSubscriptionTimer = new SubscriptionTimer(this, mWifiNetworkAdapter, context);
+        mOSUCache = new OSUCache();
+        KeyStore ks = null;
+        try {
+            //ks = loadKeyStore(KEYSTORE_FILE, readCertsFromDisk(WFA_CA_LOC));
+            ks = loadKeyStore(new File(context.getFilesDir(), KEYSTORE_FILE),
+                    OSUSocketFactory.buildCertSet());
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to initialize Passpoint keystore, OSU disabled", e);
+        }
+        mKeyStore = ks;
+    }
+
+    private static KeyStore loadKeyStore(File ksFile, Set<X509Certificate> diskCerts)
+            throws IOException {
+        try {
+            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+            if (ksFile.exists()) {
+                try (FileInputStream in = new FileInputStream(ksFile)) {
+                    keyStore.load(in, null);
+                }
+
+                // Note: comparing two sets of certs does not work.
+                boolean mismatch = false;
+                int loadCount = 0;
+                for (int n = 0; n < 1000; n++) {
+                    String alias = String.format("%s%d", CERT_WFA_ALIAS, n);
+                    Certificate cert = keyStore.getCertificate(alias);
+                    if (cert == null) {
+                        break;
+                    }
+
+                    loadCount++;
+                    boolean matched = false;
+                    Iterator<X509Certificate> iter = diskCerts.iterator();
+                    while (iter.hasNext()) {
+                        X509Certificate diskCert = iter.next();
+                        if (cert.equals(diskCert)) {
+                            iter.remove();
+                            matched = true;
+                            break;
+                        }
+                    }
+                    if (!matched) {
+                        mismatch = true;
+                        break;
+                    }
+                }
+                if (mismatch || !diskCerts.isEmpty()) {
+                    Log.d(TAG, "Re-seeding Passpoint key store with " +
+                            diskCerts.size() + " WFA certs");
+                    for (int n = 0; n < 1000; n++) {
+                        String alias = String.format("%s%d", CERT_WFA_ALIAS, n);
+                        Certificate cert = keyStore.getCertificate(alias);
+                        if (cert == null) {
+                            break;
+                        } else {
+                            keyStore.deleteEntry(alias);
+                        }
+                    }
+                    int index = 0;
+                    for (X509Certificate caCert : diskCerts) {
+                        keyStore.setCertificateEntry(
+                                String.format("%s%d", CERT_WFA_ALIAS, index), caCert);
+                        index++;
+                    }
+
+                    try (FileOutputStream out = new FileOutputStream(ksFile)) {
+                        keyStore.store(out, null);
+                    }
+                } else {
+                    Log.d(TAG, "Loaded Passpoint key store with " + loadCount + " CA certs");
+                    Enumeration<String> aliases = keyStore.aliases();
+                    while (aliases.hasMoreElements()) {
+                        Log.d("ZXC", "KS Alias '" + aliases.nextElement() + "'");
+                    }
+                }
+            } else {
+                keyStore.load(null, null);
+                int index = 0;
+                for (X509Certificate caCert : diskCerts) {
+                    keyStore.setCertificateEntry(
+                            String.format("%s%d", CERT_WFA_ALIAS, index), caCert);
+                    index++;
+                }
+
+                try (FileOutputStream out = new FileOutputStream(ksFile)) {
+                    keyStore.store(out, null);
+                }
+                Log.d(TAG, "Initialized Passpoint key store with " +
+                        diskCerts.size() + " CA certs");
+            }
+            return keyStore;
+        } catch (GeneralSecurityException gse) {
+            throw new IOException(gse);
+        }
+    }
+
+    private static Set<X509Certificate> readCertsFromDisk(String dir) throws CertificateException {
+        Set<X509Certificate> certs = new HashSet<>();
+        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+        File caDir = new File(dir);
+        File[] certFiles = caDir.listFiles();
+        if (certFiles != null) {
+            for (File certFile : certFiles) {
+                try {
+                    try (FileInputStream in = new FileInputStream(certFile)) {
+                        Certificate cert = certFactory.generateCertificate(in);
+                        if (cert instanceof X509Certificate) {
+                            certs.add((X509Certificate) cert);
+                        }
+                    }
+                } catch (CertificateException | IOException e) {
+                            /* Ignore */
+                }
+            }
+        }
+        return certs;
+    }
+
+    public KeyStore getKeyStore() {
+        return mKeyStore;
+    }
+
+    private static class OSUThread extends Thread {
+        private final OSUClient mOSUClient;
+        private final OSUManager mOSUManager;
+        private final HomeSP mHomeSP;
+        private final String mSpName;
+        private final int mFlowType;
+        private final KeyManager mKeyManager;
+        private final long mLaunchTime;
+        private final Object mLock = new Object();
+        private boolean mLocalAddressSet;
+        private Network mNetwork;
+
+        private OSUThread(OSUInfo osuInfo, OSUManager osuManager, KeyManager km)
+                throws MalformedURLException {
+            mOSUClient = new OSUClient(osuInfo, osuManager.getKeyStore());
+            mOSUManager = osuManager;
+            mHomeSP = null;
+            mSpName = osuInfo.getName(LOCALE);
+            mFlowType = FLOW_PROVISIONING;
+            mKeyManager = km;
+            mLaunchTime = System.currentTimeMillis();
+
+            setDaemon(true);
+            setName("OSU Client Thread");
+        }
+
+        private OSUThread(String osuURL, OSUManager osuManager, KeyManager km, HomeSP homeSP,
+                          int flowType) throws MalformedURLException {
+            mOSUClient = new OSUClient(osuURL, osuManager.getKeyStore());
+            mOSUManager = osuManager;
+            mHomeSP = homeSP;
+            mSpName = homeSP.getFriendlyName();
+            mFlowType = flowType;
+            mKeyManager = km;
+            mLaunchTime = System.currentTimeMillis();
+
+            setDaemon(true);
+            setName("OSU Client Thread");
+        }
+
+        public long getLaunchTime() {
+            return mLaunchTime;
+        }
+
+        private void connect(Network network) {
+            synchronized (mLock) {
+                mNetwork = network;
+                mLocalAddressSet = true;
+                mLock.notifyAll();
+            }
+            Log.d(TAG, "Client notified...");
+        }
+
+        @Override
+        public void run() {
+            Log.d(TAG, mFlowType + "-" + getName() + " running.");
+            Network network;
+            synchronized (mLock) {
+                while (!mLocalAddressSet) {
+                    try {
+                        mLock.wait();
+                    } catch (InterruptedException ie) {
+                        /**/
+                    }
+                    Log.d(TAG, "OSU Thread running...");
+                }
+                network = mNetwork;
+            }
+
+            if (network == null) {
+                Log.d(TAG, "Association failed, exiting OSU flow");
+                mOSUManager.provisioningFailed(mSpName, "Network cannot be reached",
+                        mHomeSP, mFlowType);
+                return;
+            }
+
+            Log.d(TAG, "OSU SSID Associated at " + network.toString());
+            try {
+                if (mFlowType == FLOW_PROVISIONING) {
+                    mOSUClient.provision(mOSUManager, network, mKeyManager);
+                } else {
+                    mOSUClient.remediate(mOSUManager, network, mKeyManager, mHomeSP, mFlowType);
+                }
+            } catch (Throwable t) {
+                Log.w(TAG, "OSU flow failed: " + t, t);
+                mOSUManager.provisioningFailed(mSpName, t.getMessage(), mHomeSP, mFlowType);
+            }
+        }
+    }
+
+    /*
+    public void startOSU() {
+        registerUserInputListener(new UserInputListener() {
+            @Override
+            public void requestUserInput(URL target, Network network, URL endRedirect) {
+                Log.d(TAG, "Browser to " + target + ", land at " + endRedirect);
+
+                final Intent intent = new Intent(
+                        ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
+                intent.putExtra(ConnectivityManager.EXTRA_NETWORK, network);
+                intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
+                        new CaptivePortal(new ICaptivePortal.Stub() {
+                            @Override
+                            public void appResponse(int response) {
+                            }
+                        }));
+                //intent.setData(Uri.parse(target.toString()));     !!! Doesn't work!
+                intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, target.toString());
+                intent.setFlags(
+                        Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+                mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+            }
+
+            @Override
+            public String operationStatus(String spIdentity, OSUOperationStatus status,
+                                          String message) {
+                Log.d(TAG, "OSU OP Status: " + status + ", message " + message);
+                Intent intent = new Intent(Intent.ACTION_OSU_NOTIFICATION);
+                intent.putExtra(SP_NAME, spIdentity);
+                intent.putExtra(PROV_SUCCESS, status == OSUOperationStatus.ProvisioningSuccess);
+                if (message != null) {
+                    intent.putExtra(PROV_MESSAGE, message);
+                }
+                intent.setFlags(
+                        Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+                mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+                return null;
+            }
+
+            @Override
+            public void deAuthNotification(String spIdentity, boolean ess, int delay, URL url) {
+                Log.i(TAG, "De-authentication imminent for " + (ess ? "ess" : "bss") +
+                        ", redirect to " + url);
+                Intent intent = new Intent(Intent.ACTION_OSU_NOTIFICATION);
+                intent.putExtra(SP_NAME, spIdentity);
+                intent.putExtra(DEAUTH, ess);
+                intent.putExtra(DEAUTH_DELAY, delay);
+                intent.putExtra(DEAUTH_URL, url.toString());
+                intent.setFlags(
+                        Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+                mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+            }
+        });
+        addOSUListener(new OSUListener() {
+            @Override
+            public void osuNotification(int count) {
+                Intent intent = new Intent(Intent.ACTION_OSU_NOTIFICATION);
+                intent.putExtra(OSU_COUNT, count);
+                intent.setFlags(
+                        Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
+                mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+            }
+        });
+        mWifiNetworkAdapter.initialize();
+        mSubscriptionTimer.checkUpdates();
+    }
+    */
+
+    public List<OSUInfo> getAvailableOSUs() {
+        synchronized (mOSUMap) {
+            List<OSUInfo> completeOSUs = new ArrayList<>();
+            for (OSUInfo osuInfo : mOSUMap.values()) {
+                if (osuInfo.getIconStatus() == OSUInfo.IconStatus.Available) {
+                    completeOSUs.add(osuInfo);
+                }
+            }
+            return completeOSUs;
+        }
+    }
+
+    public void recheckTimers() {
+        mSubscriptionTimer.checkUpdates();
+    }
+
+    public void setOSUSelection(int osuID) {
+        OSUInfo selection = null;
+        for (OSUInfo osuInfo : mOSUMap.values()) {
+            Log.d("ZXZ", "In select: " + osuInfo + ", id " + osuInfo.getOsuID());
+            if (osuInfo.getOsuID() == osuID &&
+                    osuInfo.getIconStatus() == OSUInfo.IconStatus.Available) {
+                selection = osuInfo;
+                break;
+            }
+        }
+
+        Log.d(TAG, "Selected OSU ID " + osuID + ", matches " + selection);
+
+        if (selection == null) {
+            mPendingOSU = null;
+            return;
+        }
+
+        mPendingOSU = selection;
+        WifiConfiguration config = mWifiNetworkAdapter.getActiveWifiConfig();
+
+        if (config != null &&
+                bssidMatch(selection) &&
+                Utils.unquote(config.SSID).equals(selection.getSSID())) {
+
+            try {
+                // Go straight to provisioning if the network is already selected.
+                // Also note that mOSUNwkID is left unset to leave the network around after
+                // flow completion since it was not added by the OSU flow.
+                initiateProvisioning(mPendingOSU, mWifiNetworkAdapter.getCurrentNetwork());
+            } catch (IOException ioe) {
+                notifyUser(OSUOperationStatus.ProvisioningFailure, ioe.getMessage(),
+                        mPendingOSU.getName(LOCALE));
+            } finally {
+                mPendingOSU = null;
+            }
+        } else {
+            try {
+                mOSUNwkID = mWifiNetworkAdapter.connect(selection, mPendingOSU.getName(LOCALE));
+            } catch (IOException ioe) {
+                notifyUser(OSUOperationStatus.ProvisioningFailure, ioe.getMessage(),
+                        selection.getName(LOCALE));
+            }
+        }
+    }
+
+    public void networkConfigChange(WifiConfiguration configuration) {
+        mWifiNetworkAdapter.networkConfigChange(configuration);
+    }
+
+    public void networkConnectEvent(WifiInfo wifiInfo) {
+        if (wifiInfo != null) {
+            setActiveNetwork(mWifiNetworkAdapter.getActiveWifiConfig(),
+                    mWifiNetworkAdapter.getCurrentNetwork());
+        }
+    }
+
+    public void wifiStateChange(boolean on) {
+        if (!on) {
+            int current = mOSUMap.size();
+            mOSUMap.clear();
+            mOSUCache.clearAll();
+            mIconCache.clear();
+            if (current > 0) {
+                notifyOSUCount(0);
+            }
+        }
+    }
+
+    private boolean bssidMatch(OSUInfo osuInfo) {
+        if (MATCH_BSSID) {
+            WifiInfo wifiInfo = mWifiNetworkAdapter.getConnectionInfo();
+            return wifiInfo != null && Utils.parseMac(wifiInfo.getBSSID()) == osuInfo.getBSSID();
+        } else {
+            return true;
+        }
+    }
+
+    public void setActiveNetwork(WifiConfiguration wifiConfiguration, Network network) {
+        Log.d(TAG, "Network change: " + network + ", cfg " +
+                (wifiConfiguration != null ? wifiConfiguration.SSID : "-") + ", osu " + mPendingOSU);
+        if (mPendingOSU != null &&
+                wifiConfiguration != null &&
+                network != null &&
+                bssidMatch(mPendingOSU) &&
+                Utils.unquote(wifiConfiguration.SSID).equals(mPendingOSU.getSSID())) {
+
+            try {
+                Log.d(TAG, "New network " + network + ", current OSU " + mPendingOSU);
+                initiateProvisioning(mPendingOSU, network);
+            } catch (IOException ioe) {
+                notifyUser(OSUOperationStatus.ProvisioningFailure, ioe.getMessage(),
+                        mPendingOSU.getName(LOCALE));
+            } finally {
+                mPendingOSU = null;
+            }
+            return;
+        }
+
+        /*
+        // !!! Hack to force start remediation at connection time
+        else if (wifiConfiguration != null && wifiConfiguration.isPasspoint()) {
+            HomeSP homeSP = mWifiConfigStore.getHomeSPForConfig(wifiConfiguration);
+            if (homeSP != null && homeSP.getSubscriptionUpdate() != null) {
+                if (!mServiceThreads.containsKey(homeSP.getFQDN())) {
+                    try {
+                        remediate(homeSP);
+                    } catch (IOException ioe) {
+                        Log.w(TAG, "Failed to remediate: " + ioe);
+                    }
+                }
+            }
+        }
+        */
+        else if (wifiConfiguration == null) {
+            mServiceThreads.clear();
+        }
+    }
+
+
+    /**
+     * Called when an OSU has been selected and the associated network is fully connected.
+     *
+     * @param osuInfo The selected OSUInfo or null if the current OSU flow is cancelled externally,
+     *                e.g. WiFi is turned off or the OSU network is otherwise detected as
+     *                unreachable.
+     * @param network The currently associated network (for the OSU SSID).
+     * @throws IOException
+     * @throws GeneralSecurityException
+     */
+    private void initiateProvisioning(OSUInfo osuInfo, Network network)
+            throws IOException {
+        synchronized (mWifiNetworkAdapter) {
+            if (mProvisioningThread != null) {
+                mProvisioningThread.connect(null);
+                mProvisioningThread = null;
+            }
+            if (mRedirectListener != null) {
+                mRedirectListener.abort();
+                mRedirectListener = null;
+            }
+            if (osuInfo != null) {
+                //new ConnMonitor().start();
+                mProvisioningThread = new OSUThread(osuInfo, this, getKeyManager(null, mKeyStore));
+                mProvisioningThread.start();
+                //mWifiNetworkAdapter.associate(osuInfo.getSSID(),
+                //        osuInfo.getBSSID(), osuInfo.getOSUProvider().getOsuNai());
+                mProvisioningThread.connect(network);
+            }
+        }
+    }
+
+    /**
+     * @param homeSP The Home SP associated with the keying material in question. Passing
+     *               null returns a "system wide" KeyManager to support pre-provisioned certs based
+     *               on names retrieved from the ClientCertInfo request.
+     * @return A key manager suitable for the given configuration (or pre-provisioned keys).
+     */
+    private static KeyManager getKeyManager(HomeSP homeSP, KeyStore keyStore)
+            throws IOException {
+        return homeSP != null ? new ClientKeyManager(homeSP, keyStore) :
+                new WiFiKeyManager(keyStore);
+    }
+
+    public boolean isOSU(String ssid) {
+        synchronized (mOSUMap) {
+            return mOSUSSIDs.contains(ssid);
+        }
+    }
+
+    public void tickleIconCache(boolean all) {
+        mIconCache.tickle(all);
+
+        if (all) {
+            synchronized (mOSUMap) {
+                int current = mOSUMap.size();
+                mOSUMap.clear();
+                mOSUCache.clearAll();
+                mIconCache.clear();
+                if (current > 0) {
+                    notifyOSUCount(0);
+                }
+            }
+        }
+    }
+
+    public void pushScanResults(Collection<ScanResult> scanResults) {
+        Map<OSUProvider, ScanResult> results = mOSUCache.pushScanResults(scanResults);
+        if (results != null) {
+            updateOSUInfoCache(results);
+        }
+    }
+
+    private void updateOSUInfoCache(Map<OSUProvider, ScanResult> results) {
+        Map<OSUProvider, OSUInfo> osus = new HashMap<>();
+        for (Map.Entry<OSUProvider, ScanResult> entry : results.entrySet()) {
+            OSUInfo existing = mOSUMap.get(entry.getKey());
+            long bssid = Utils.parseMac(entry.getValue().BSSID);
+
+            if (existing == null || existing.getBSSID() != bssid) {
+                osus.put(entry.getKey(), new OSUInfo(entry.getValue(), entry.getKey().getSSID(),
+                        entry.getKey(), mOSUSequence.getAndIncrement()));
+            } else {
+                // Maintain existing entries.
+                osus.put(entry.getKey(), existing);
+            }
+        }
+
+        mOSUMap.clear();
+        mOSUMap.putAll(osus);
+
+        mOSUSSIDs.clear();
+        for (OSUInfo osuInfo : mOSUMap.values()) {
+            mOSUSSIDs.add(osuInfo.getSSID());
+        }
+
+        if (mOSUMap.isEmpty()) {
+            notifyOSUCount(0);
+        }
+        initiateIconQueries();
+        Log.d(TAG, "Latest (app) OSU info: " + mOSUMap);
+    }
+
+    public void iconResults(List<OSUInfo> osuInfos) {
+        int newIcons = 0;
+        for (OSUInfo osuInfo : osuInfos) {
+            if (osuInfo.getIconStatus() == OSUInfo.IconStatus.Available) {
+                newIcons++;
+            }
+        }
+        if (newIcons > 0) {
+            int count = 0;
+            for (OSUInfo existing : mOSUMap.values()) {
+                if (existing.getIconStatus() == OSUInfo.IconStatus.Available) {
+                    count++;
+                }
+            }
+            Log.d(TAG, "Icon results for " + count + " OSUs");
+            notifyOSUCount(count);
+        }
+    }
+
+    private void notifyOSUCount(int count) {
+        mAppBridge.showOsuCount(count, getAvailableOSUs());
+    }
+
+    private void initiateIconQueries() {
+        for (OSUInfo osuInfo : mOSUMap.values()) {
+            if (osuInfo.getIconStatus() == OSUInfo.IconStatus.NotQueried) {
+                mIconCache.startIconQuery(osuInfo,
+                        osuInfo.getIconInfo(LOCALE, ICON_TYPES, ICON_WIDTH, ICON_HEIGHT));
+            }
+        }
+    }
+
+    public void deauth(long bssid, boolean ess, int delay, String url) throws MalformedURLException {
+        Log.d(TAG, String.format("De-auth imminent on %s, delay %ss to '%s'",
+                ess ? "ess" : "bss",
+                delay,
+                url));
+        mWifiNetworkAdapter.setHoldoffTime(delay * Constants.MILLIS_IN_A_SEC, ess);
+        HomeSP homeSP = mWifiNetworkAdapter.getCurrentSP();
+        String spName = homeSP != null ? homeSP.getFriendlyName() : "unknown";
+        mAppBridge.showDeauth(spName, ess, delay, url);
+    }
+
+    // !!! Consistently check passpoint match.
+    // !!! Convert to a one-thread thread-pool
+    public void wnmRemediate(long bssid, String url, PasspointMatch match)
+            throws IOException, SAXException {
+        WifiConfiguration config = mWifiNetworkAdapter.getActiveWifiConfig();
+        HomeSP homeSP = MOManager.buildSP(config.getMoTree());
+        if (homeSP == null) {
+            throw new IOException("Remediation request for unidentified Passpoint network " +
+                    config.networkId);
+        }
+        Network network = mWifiNetworkAdapter.getCurrentNetwork();
+        if (network == null) {
+            throw new IOException("Failed to determine current network");
+        }
+        WifiInfo wifiInfo = mWifiNetworkAdapter.getConnectionInfo();
+        if (wifiInfo == null || Utils.parseMac(wifiInfo.getBSSID()) != bssid) {
+            throw new IOException("Mismatching BSSID");
+        }
+        Log.d(TAG, "WNM Remediation on " + network.netId + " FQDN " + homeSP.getFQDN());
+
+        doRemediate(url, network, homeSP, false);
+    }
+
+    public void remediate(HomeSP homeSP, boolean policy) throws IOException, SAXException {
+        UpdateInfo updateInfo;
+        if (policy) {
+            if (homeSP.getPolicy() == null) {
+                throw new IOException("No policy object");
+            }
+            updateInfo = homeSP.getPolicy().getPolicyUpdate();
+        } else {
+            updateInfo = homeSP.getSubscriptionUpdate();
+        }
+        switch (updateInfo.getUpdateRestriction()) {
+            case HomeSP: {
+                Network network = mWifiNetworkAdapter.getCurrentNetwork();
+                if (network == null) {
+                    throw new IOException("Failed to determine current network");
+                }
+
+                WifiConfiguration config = mWifiNetworkAdapter.getActivePasspointNetwork();
+                HomeSP activeSP = MOManager.buildSP(config.getMoTree());
+
+                if (activeSP == null || !activeSP.getFQDN().equals(homeSP.getFQDN())) {
+                    throw new IOException("Remediation restricted to HomeSP");
+                }
+                doRemediate(updateInfo.getURI(), network, homeSP, policy);
+                break;
+            }
+            case RoamingPartner: {
+                Network network = mWifiNetworkAdapter.getCurrentNetwork();
+                if (network == null) {
+                    throw new IOException("Failed to determine current network");
+                }
+
+                WifiInfo wifiInfo = mWifiNetworkAdapter.getConnectionInfo();
+                if (wifiInfo == null) {
+                    throw new IOException("Unable to determine WiFi info");
+                }
+
+                PasspointMatch match = mWifiNetworkAdapter.
+                        matchProviderWithCurrentNetwork(homeSP.getFQDN());
+
+                if (match == PasspointMatch.HomeProvider ||
+                        match == PasspointMatch.RoamingProvider) {
+                    doRemediate(updateInfo.getURI(), network, homeSP, policy);
+                } else {
+                    throw new IOException("No roaming network match: " + match);
+                }
+                break;
+            }
+            case Unrestricted: {
+                Network network = mWifiNetworkAdapter.getCurrentNetwork();
+                doRemediate(updateInfo.getURI(), network, homeSP, policy);
+                break;
+            }
+        }
+    }
+
+    private void doRemediate(String url, Network network, HomeSP homeSP, boolean policy)
+            throws IOException {
+        synchronized (mWifiNetworkAdapter) {
+            OSUThread existing = mServiceThreads.get(homeSP.getFQDN());
+            if (existing != null) {
+                if (System.currentTimeMillis() - existing.getLaunchTime() > REMEDIATION_TIMEOUT) {
+                    throw new IOException("Ignoring recurring remediation request");
+                } else {
+                    existing.connect(null);
+                }
+            }
+
+            try {
+                OSUThread osuThread = new OSUThread(url, this,
+                        getKeyManager(homeSP, mKeyStore),
+                        homeSP, policy ? FLOW_POLICY : FLOW_REMEDIATION);
+                osuThread.start();
+                osuThread.connect(network);
+                mServiceThreads.put(homeSP.getFQDN(), osuThread);
+            } catch (MalformedURLException me) {
+                throw new IOException("Failed to start remediation: " + me);
+            }
+        }
+    }
+
+    public MOTree getMOTree(HomeSP homeSP) throws IOException {
+        return mWifiNetworkAdapter.getMOTree(homeSP);
+    }
+
+    public void notifyIconReceived(long bssid, String fileName, byte[] data) {
+        mIconCache.notifyIconReceived(bssid, fileName, data);
+    }
+
+    public void doIconQuery(long bssid, String fileName) {
+        mWifiNetworkAdapter.doIconQuery(bssid, fileName);
+    }
+
+    protected URL prepareUserInput(String spName) throws IOException {
+        mRedirectListener = new RedirectListener(this, spName);
+        return mRedirectListener.getURL();
+    }
+
+    protected boolean startUserInput(URL target, Network network) throws IOException {
+        mRedirectListener.startService();
+        mWifiNetworkAdapter.launchBrowser(target, network, mRedirectListener.getURL());
+
+        return mRedirectListener.waitForUser();
+    }
+
+    public String notifyUser(OSUOperationStatus status, String message, String spName) {
+        if (status == OSUOperationStatus.UserInputComplete) {
+            return null;
+        }
+        if (mOSUNwkID != null) {
+            // Delete the OSU network if it was added by the OSU flow
+            mWifiNetworkAdapter.deleteNetwork(mOSUNwkID);
+            mOSUNwkID = null;
+        }
+        mAppBridge.showStatus(status, spName, message, null);
+        return null;
+    }
+
+    public void provisioningFailed(String spName, String message, HomeSP homeSP,
+                                   int flowType) {
+        synchronized (mWifiNetworkAdapter) {
+            switch (flowType) {
+                case FLOW_PROVISIONING:
+                    mProvisioningThread = null;
+                    if (mRedirectListener != null) {
+                        mRedirectListener.abort();
+                        mRedirectListener = null;
+                    }
+                    break;
+                case FLOW_REMEDIATION:
+                case FLOW_POLICY:
+                    mServiceThreads.remove(homeSP.getFQDN());
+                    if (mServiceThreads.isEmpty() && mRedirectListener != null) {
+                        mRedirectListener.abort();
+                        mRedirectListener = null;
+                    }
+                    break;
+            }
+        }
+        notifyUser(OSUOperationStatus.ProvisioningFailure, message, spName);
+    }
+
+    public void provisioningComplete(OSUInfo osuInfo,
+                                     MOData moData, Map<OSUCertType, List<X509Certificate>> certs,
+                                     PrivateKey privateKey, Network osuNetwork) {
+        synchronized (mWifiNetworkAdapter) {
+            mProvisioningThread = null;
+        }
+        try {
+            Log.d("ZXZ", "MOTree.toXML: " + moData.getMOTree().toXml());
+            HomeSP homeSP = mWifiNetworkAdapter.addSP(moData.getMOTree());
+
+            Integer spNwk = mWifiNetworkAdapter.addNetwork(homeSP, certs, privateKey, osuNetwork);
+            if (spNwk == null) {
+                notifyUser(OSUOperationStatus.ProvisioningFailure,
+                        "Failed to save network configuration", osuInfo.getName(LOCALE));
+                mWifiNetworkAdapter.removeSP(homeSP.getFQDN());
+            } else {
+                Set<X509Certificate> rootCerts = OSUSocketFactory.getRootCerts(mKeyStore);
+                X509Certificate remCert = getCert(certs, OSUCertType.Remediation);
+                X509Certificate polCert = getCert(certs, OSUCertType.Policy);
+                if (privateKey != null) {
+                    X509Certificate cltCert = getCert(certs, OSUCertType.Client);
+                    mKeyStore.setKeyEntry(CERT_CLT_KEY_ALIAS + homeSP,
+                            privateKey.getEncoded(),
+                            new X509Certificate[]{cltCert});
+                    mKeyStore.setCertificateEntry(CERT_CLT_CERT_ALIAS, cltCert);
+                }
+                boolean usingShared = false;
+                int newCerts = 0;
+                if (remCert != null) {
+                    if (!rootCerts.contains(remCert)) {
+                        if (remCert.equals(polCert)) {
+                            mKeyStore.setCertificateEntry(CERT_SHARED_ALIAS + homeSP.getFQDN(),
+                                    remCert);
+                            usingShared = true;
+                            newCerts++;
+                        } else {
+                            mKeyStore.setCertificateEntry(CERT_REM_ALIAS + homeSP.getFQDN(),
+                                    remCert);
+                            newCerts++;
+                        }
+                    }
+                }
+                if (!usingShared && polCert != null) {
+                    if (!rootCerts.contains(polCert)) {
+                        mKeyStore.setCertificateEntry(CERT_POLICY_ALIAS + homeSP.getFQDN(),
+                                remCert);
+                        newCerts++;
+                    }
+                }
+
+                if (newCerts > 0) {
+                    try (FileOutputStream out = new FileOutputStream(KEYSTORE_FILE)) {
+                        mKeyStore.store(out, null);
+                    }
+                }
+                notifyUser(OSUOperationStatus.ProvisioningSuccess, null, osuInfo.getName(LOCALE));
+                Log.d(TAG, "Provisioning complete.");
+            }
+        } catch (IOException | GeneralSecurityException | SAXException e) {
+            Log.e(TAG, "Failed to provision: " + e, e);
+            notifyUser(OSUOperationStatus.ProvisioningFailure, e.toString(),
+                    osuInfo.getName(LOCALE));
+        }
+    }
+
+    private static X509Certificate getCert(Map<OSUCertType, List<X509Certificate>> certMap,
+                                           OSUCertType certType) {
+        List<X509Certificate> certs = certMap.get(certType);
+        if (certs == null || certs.isEmpty()) {
+            return null;
+        }
+        return certs.iterator().next();
+    }
+
+    public void spDeleted(String fqdn) {
+        int count = deleteCerts(mKeyStore, fqdn,
+                CERT_REM_ALIAS, CERT_POLICY_ALIAS, CERT_SHARED_ALIAS);
+
+        if (count > 0) {
+            try (FileOutputStream out = new FileOutputStream(KEYSTORE_FILE)) {
+                mKeyStore.store(out, null);
+            } catch (IOException | GeneralSecurityException e) {
+                Log.w(TAG, "Failed to remove certs from key store: " + e);
+            }
+        }
+    }
+
+    private static int deleteCerts(KeyStore keyStore, String fqdn, String... prefixes) {
+        int count = 0;
+        for (String prefix : prefixes) {
+            try {
+                String alias = prefix + fqdn;
+                Certificate cert = keyStore.getCertificate(alias);
+                if (cert != null) {
+                    keyStore.deleteEntry(alias);
+                    count++;
+                }
+            } catch (KeyStoreException kse) {
+                /**/
+            }
+        }
+        return count;
+    }
+
+    public void remediationComplete(HomeSP homeSP, Collection<MOData> mods,
+                                    Map<OSUCertType, List<X509Certificate>> certs,
+                                    PrivateKey privateKey)
+            throws IOException, GeneralSecurityException {
+
+        HomeSP altSP = mWifiNetworkAdapter.modifySP(homeSP, mods);
+        X509Certificate caCert = null;
+        List<X509Certificate> clientCerts = null;
+        if (certs != null) {
+            List<X509Certificate> certList = certs.get(OSUCertType.AAA);
+            caCert = certList != null && !certList.isEmpty() ? certList.iterator().next() : null;
+            clientCerts = certs.get(OSUCertType.Client);
+        }
+        if (altSP != null || certs != null) {
+            if (altSP == null) {
+                altSP = homeSP;     // No MO mods, only certs and key
+            }
+            mWifiNetworkAdapter.updateNetwork(altSP, caCert, clientCerts, privateKey);
+        }
+        notifyUser(OSUOperationStatus.ProvisioningSuccess, null, homeSP.getFriendlyName());
+    }
+
+    protected OMADMAdapter getOMADMAdapter() {
+        return OMADMAdapter.getInstance(mContext);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUMessageType.java b/packages/Osu/src/com/android/hotspot2/osu/OSUMessageType.java
new file mode 100644
index 0000000..8c1b50a
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUMessageType.java
@@ -0,0 +1,5 @@
+package com.android.hotspot2.osu;
+
+public enum OSUMessageType {
+    PostDevData, ExchangeComplete, GetCertificate, Error
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUOperationStatus.java b/packages/Osu/src/com/android/hotspot2/osu/OSUOperationStatus.java
new file mode 100644
index 0000000..ddda89c
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUOperationStatus.java
@@ -0,0 +1,8 @@
+package com.android.hotspot2.osu;
+
+public enum OSUOperationStatus {
+    UserInputComplete,
+    UserInputAborted,
+    ProvisioningSuccess,
+    ProvisioningFailure
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUResponse.java b/packages/Osu/src/com/android/hotspot2/osu/OSUResponse.java
new file mode 100644
index 0000000..1e4398d
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUResponse.java
@@ -0,0 +1,97 @@
+package com.android.hotspot2.osu;
+
+import com.android.hotspot2.omadm.OMAConstants;
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.XMLNode;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class OSUResponse {
+    private static final String SPPVersionAttribute = "sppVersion";
+    private static final String SPPStatusAttribute = "sppStatus";
+    private static final String SPPSessionIDAttribute = "sessionID";
+
+    private final OSUMessageType mMessageType;
+    private final String mVersion;
+    private final String mSessionID;
+    private final OSUStatus mStatus;
+    private final OSUError mError;
+    private final Map<String, String> mAttributes;
+
+    protected OSUResponse(XMLNode root, OSUMessageType messageType, String... attributes)
+            throws OMAException {
+        mMessageType = messageType;
+        String ns = root.getNameSpace() + ":";
+        mVersion = root.getAttributeValue(ns + SPPVersionAttribute);
+        mSessionID = root.getAttributeValue(ns + SPPSessionIDAttribute);
+
+        String status = root.getAttributeValue(ns + SPPStatusAttribute);
+        if (status == null) {
+            throw new OMAException("Missing status");
+        }
+        mStatus = OMAConstants.mapStatus(status);
+
+        if (mVersion == null || mSessionID == null || mStatus == null) {
+            throw new OMAException("Incomplete request: " + root.getAttributes());
+        }
+
+        if (attributes != null) {
+            mAttributes = new HashMap<>();
+            for (String attribute : attributes) {
+                String value = root.getAttributeValue(ns + attribute);
+                if (value == null) {
+                    throw new OMAException("Missing attribute: " + attribute);
+                }
+                mAttributes.put(attribute, value);
+            }
+        } else {
+            mAttributes = null;
+        }
+
+        if (mStatus == OSUStatus.Error) {
+            OSUError error = null;
+            String errorTag = ns + "sppError";
+            for (XMLNode child : root.getChildren()) {
+                if (child.getTag().equals(errorTag)) {
+                    error = OMAConstants.mapError(child.getAttributeValue("errorCode"));
+                    break;
+                }
+            }
+            mError = error;
+        } else {
+            mError = null;
+        }
+    }
+
+    public OSUMessageType getMessageType() {
+        return mMessageType;
+    }
+
+    public String getVersion() {
+        return mVersion;
+    }
+
+    public String getSessionID() {
+        return mSessionID;
+    }
+
+    public OSUStatus getStatus() {
+        return mStatus;
+    }
+
+    public OSUError getError() {
+        return mError;
+    }
+
+    protected Map<String, String> getAttributes() {
+        return mAttributes;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s version '%s', status %s, session-id '%s'%s",
+                mMessageType, mVersion, mStatus, mSessionID, mError != null
+                        ? (" (" + mError + ")") : "");
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUSocketFactory.java b/packages/Osu/src/com/android/hotspot2/osu/OSUSocketFactory.java
new file mode 100644
index 0000000..ef22f643
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUSocketFactory.java
@@ -0,0 +1,447 @@
+package com.android.hotspot2.osu;
+
+import android.net.Network;
+import android.util.Base64;
+import android.util.Log;
+
+import com.android.hotspot2.Utils;
+import com.android.hotspot2.pps.HomeSP;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.PrivateKey;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+public class OSUSocketFactory {
+    private static final long ConnectionTimeout = 10000L;
+    private static final long ReconnectWait = 2000L;
+
+    private static final String SecureHTTP = "https";
+    private static final String UnsecureHTTP = "http";
+    private static final String EKU_ID = "2.5.29.37";
+    private static final Set<String> EKU_ID_SET = new HashSet<>(Arrays.asList(EKU_ID));
+    private static final EKUChecker sEKUChecker = new EKUChecker();
+
+    private final Network mNetwork;
+    private final SocketFactory mSocketFactory;
+    private final KeyManager mKeyManager;
+    private final WFATrustManager mTrustManager;
+    private final List<InetSocketAddress> mRemotes;
+
+    public static Set<X509Certificate> buildCertSet() {
+        try {
+            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+            Set<X509Certificate> set = new HashSet<>();
+            for (String b64 : WFACerts) {
+                ByteArrayInputStream bis = new ByteArrayInputStream(
+                        Base64.decode(b64, Base64.DEFAULT));
+                X509Certificate cert = (X509Certificate) certFactory.generateCertificate(bis);
+                set.add(cert);
+            }
+            return set;
+        } catch (CertificateException ce) {
+            Log.e(OSUManager.TAG, "Cannot build CA cert set");
+            return null;
+        }
+    }
+
+    public static OSUSocketFactory getSocketFactory(KeyStore ks, HomeSP homeSP, int flowType,
+                                                    Network network, URL url, KeyManager km,
+                                                    boolean enforceSecurity)
+            throws GeneralSecurityException, IOException {
+
+        if (enforceSecurity && !url.getProtocol().equalsIgnoreCase(SecureHTTP)) {
+            throw new IOException("Protocol '" + url.getProtocol() + "' is not secure");
+        }
+        return new OSUSocketFactory(ks, homeSP, flowType, network, url, km);
+    }
+
+    private OSUSocketFactory(KeyStore ks, HomeSP homeSP, int flowType, Network network,
+                             URL url, KeyManager km) throws GeneralSecurityException, IOException {
+        mNetwork = network;
+        mKeyManager = km;
+        mTrustManager = new WFATrustManager(ks, homeSP, flowType);
+        int port;
+        switch (url.getProtocol()) {
+            case UnsecureHTTP:
+                mSocketFactory = new DefaultSocketFactory();
+                port = url.getPort() > 0 ? url.getPort() : 80;
+                break;
+            case SecureHTTP:
+                SSLContext tlsContext = SSLContext.getInstance("TLSv1");
+                tlsContext.init(km != null ? new KeyManager[]{km} : null,
+                        new TrustManager[]{mTrustManager}, null);
+                mSocketFactory = tlsContext.getSocketFactory();
+                port = url.getPort() > 0 ? url.getPort() : 443;
+                break;
+            default:
+                throw new IOException("Bad URL: " + url);
+        }
+        if (OSUManager.R2_MOCK && url.getHost().endsWith(".wi-fi.org")) {
+            // !!! Warning: Ruckus hack!
+            mRemotes = new ArrayList<>(1);
+            mRemotes.add(new InetSocketAddress(InetAddress.getByName("10.123.107.107"), port));
+        } else {
+            InetAddress[] remotes = mNetwork.getAllByName(url.getHost());
+            android.util.Log.d(OSUManager.TAG, "'" + url.getHost() + "' resolves to " +
+                    Arrays.toString(remotes));
+            if (remotes == null || remotes.length == 0) {
+                throw new IOException("Failed to look up host from " + url);
+            }
+            mRemotes = new ArrayList<>(remotes.length);
+            for (InetAddress remote : remotes) {
+                mRemotes.add(new InetSocketAddress(remote, port));
+            }
+        }
+        Collections.shuffle(mRemotes);
+    }
+
+    public void reloadKeys(Map<OSUCertType, List<X509Certificate>> certs, PrivateKey key)
+            throws IOException {
+        if (mKeyManager instanceof ClientKeyManager) {
+            ((ClientKeyManager) mKeyManager).reloadKeys(certs, key);
+        }
+    }
+
+    public Socket createSocket() throws IOException {
+        Socket socket = mSocketFactory.createSocket();
+        mNetwork.bindSocket(socket);
+
+        long bail = System.currentTimeMillis() + ConnectionTimeout;
+        boolean success = false;
+
+        while (System.currentTimeMillis() < bail) {
+            for (InetSocketAddress remote : mRemotes) {
+                try {
+                    socket.connect(remote);
+                    Log.d(OSUManager.TAG, "Connection " + socket.getLocalSocketAddress() +
+                            " to " + socket.getRemoteSocketAddress());
+                    success = true;
+                    break;
+                } catch (IOException ioe) {
+                    Log.d(OSUManager.TAG, "Failed to connect to " + remote + ": " + ioe);
+                    socket = mSocketFactory.createSocket();
+                    mNetwork.bindSocket(socket);
+                }
+            }
+            if (success) {
+                break;
+            }
+            Utils.delay(ReconnectWait);
+        }
+        if (!success) {
+            throw new IOException("No available network");
+        }
+        return socket;
+    }
+
+    public X509Certificate getOSUCertificate(URL url) throws GeneralSecurityException {
+        String fqdn = url.getHost();
+        for (X509Certificate certificate : mTrustManager.getTrustChain()) {
+            for (List<?> name : certificate.getSubjectAlternativeNames()) {
+                if (name.size() >= SPVerifier.DNSName &&
+                        name.get(0).getClass() == Integer.class &&
+                        name.get(1).toString().equals(fqdn)) {
+                    return certificate;
+                }
+            }
+        }
+        return null;
+    }
+
+    final class DefaultSocketFactory extends SocketFactory {
+
+        DefaultSocketFactory() {
+        }
+
+        @Override
+        public Socket createSocket() throws IOException {
+            return new Socket();
+        }
+
+        @Override
+        public Socket createSocket(String host, int port) throws IOException {
+            return new Socket(host, port);
+        }
+
+        @Override
+        public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
+                throws IOException {
+            return new Socket(host, port, localHost, localPort);
+        }
+
+        @Override
+        public Socket createSocket(InetAddress host, int port) throws IOException {
+            return new Socket(host, port);
+        }
+
+        @Override
+        public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
+                                   int localPort) throws IOException {
+            return new Socket(address, port, localAddress, localPort);
+        }
+    }
+
+    private static class WFATrustManager implements X509TrustManager {
+        private final KeyStore mKeyStore;
+        private final HomeSP mHomeSP;
+        private final int mFlowType;
+        private X509Certificate[] mTrustChain;
+
+        private WFATrustManager(KeyStore ks, HomeSP homeSP, int flowType)
+                throws CertificateException {
+            mKeyStore = ks;
+            mHomeSP = homeSP;
+            mFlowType = flowType;
+        }
+
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType)
+                throws CertificateException {
+            // N/A
+        }
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType)
+                throws CertificateException {
+            Log.d("TLSOSU", "Checking " + chain.length + " certs.");
+
+            try {
+                CertPathValidator validator =
+                        CertPathValidator.getInstance(CertPathValidator.getDefaultType());
+                CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+                CertPath path = certFactory.generateCertPath(
+                        Arrays.asList(chain));
+                Set<TrustAnchor> trustAnchors = new HashSet<>();
+                if (mHomeSP == null) {
+                    for (X509Certificate cert : getRootCerts(mKeyStore)) {
+                        trustAnchors.add(new TrustAnchor(cert, null));
+                    }
+                } else {
+                    String prefix = mFlowType == OSUManager.FLOW_REMEDIATION ?
+                            OSUManager.CERT_REM_ALIAS : OSUManager.CERT_POLICY_ALIAS;
+
+                    X509Certificate cert = getCert(mKeyStore, prefix + mHomeSP.getFQDN());
+                    if (cert == null) {
+                        cert = getCert(mKeyStore, OSUManager.CERT_SHARED_ALIAS + mHomeSP.getFQDN());
+                    }
+                    if (cert == null) {
+                        for (X509Certificate root : getRootCerts(mKeyStore)) {
+                            trustAnchors.add(new TrustAnchor(root, null));
+                        }
+                    } else {
+                        trustAnchors.add(new TrustAnchor(cert, null));
+                    }
+                }
+                PKIXParameters params = new PKIXParameters(trustAnchors);
+                params.setRevocationEnabled(false);
+                params.addCertPathChecker(sEKUChecker);
+                validator.validate(path, params);
+                mTrustChain = chain;
+            } catch (GeneralSecurityException gse) {
+                throw new SecurityException(gse);
+            }
+            mTrustChain = chain;
+        }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+
+        public X509Certificate[] getTrustChain() {
+            return mTrustChain != null ? mTrustChain : new X509Certificate[0];
+        }
+    }
+
+    private static X509Certificate getCert(KeyStore keyStore, String alias)
+            throws KeyStoreException {
+        Certificate cert = keyStore.getCertificate(alias);
+        if (cert != null && cert instanceof X509Certificate) {
+            return (X509Certificate) cert;
+        }
+        return null;
+    }
+
+    public static Set<X509Certificate> getRootCerts(KeyStore keyStore) throws KeyStoreException {
+        Set<X509Certificate> certSet = new HashSet<>();
+        int index = 0;
+        for (int n = 0; n < 1000; n++) {
+            Certificate cert = keyStore.getCertificate(
+                    String.format("%s%d", OSUManager.CERT_WFA_ALIAS, index));
+            if (cert == null) {
+                break;
+            } else if (cert instanceof X509Certificate) {
+                certSet.add((X509Certificate) cert);
+            }
+            index++;
+        }
+        return certSet;
+    }
+
+    private static class EKUChecker extends PKIXCertPathChecker {
+        @Override
+        public void init(boolean forward) throws CertPathValidatorException {
+
+        }
+
+        @Override
+        public boolean isForwardCheckingSupported() {
+            return true;
+        }
+
+        @Override
+        public Set<String> getSupportedExtensions() {
+            return EKU_ID_SET;
+        }
+
+        @Override
+        public void check(Certificate cert, Collection<String> unresolvedCritExts)
+                throws CertPathValidatorException {
+            Log.d(OSUManager.TAG, "Checking EKU " + unresolvedCritExts);
+            unresolvedCritExts.remove(EKU_ID);
+        }
+    }
+
+    /*
+     *
+      Subject: CN=osu-server.r2-testbed-rks.wi-fi.org, O=Intel Corporation CCG DRD, C=US
+      Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
+      Validity: [From: Wed Jan 28 16:00:00 PST 2015,
+                   To: Sat Jan 28 15:59:59 PST 2017]
+      Issuer: CN="NetworkFX, Inc. Hotspot 2.0 Intermediate CA", OU=OSU CA - 01, O="NetworkFX, Inc.", C=US
+      SerialNumber: [    312af3db 138eae19 1defbce2 e2b88b55]
+    *
+    *
+      Subject: CN="NetworkFX, Inc. Hotspot 2.0 Intermediate CA", OU=OSU CA - 01, O="NetworkFX, Inc.", C=US
+      Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
+      Validity: [From: Tue Nov 19 16:00:00 PST 2013,
+                   To: Sun Nov 19 15:59:59 PST 2023]
+      Issuer: CN=Hotspot 2.0 Trust Root CA - 01, O=WFA Hotspot 2.0, C=US
+      SerialNumber: [    4152b1b0 301495f3 8fa76428 2ef41046]
+     */
+
+    public static final String[] WFACerts = {
+            "MIIFbDCCA1SgAwIBAgIQDLMPcPKGpDPguQmJ3gHttzANBgkqhkiG9w0BAQsFADBQ" +
+                    "MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPV0ZBIEhvdHNwb3QgMi4wMScwJQYDVQQD" +
+                    "Ex5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0gMDMwHhcNMTMxMjA4MTIwMDAw" +
+                    "WhcNNDMxMjA4MTIwMDAwWjBQMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPV0ZBIEhv" +
+                    "dHNwb3QgMi4wMScwJQYDVQQDEx5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0g" +
+                    "MDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsdEtReIUbMlO+hR6b" +
+                    "yQk4nGVITv3meYTaDeVwZnQVal8EjHuu4Kd89g8yRYVTv3J1kq9ukE7CDrDehrXK" +
+                    "ym+8VlR7ro0lB/lwRyNk3W7yNccg3AknQ0x5fKVwcFznwD/FYg37owGmhGFtpMTB" +
+                    "cxzreQaLXvLta8YNlJU10ZkfputBpzi9bLPWsLOkIrQw7KH1Wc+Oiy4hUMUbTlSi" +
+                    "cjqacKPR188mVIoxxUoICHyVV1KvMmYZrVdc/b5dbmd0haMHxC0VSqbydXxxS7vv" +
+                    "/lCrC2d5qbKE66PiuBPkhzyU7SI9C8GU/S7akYm1MMSTn5W7lSp2AWRDnf9LQg51" +
+                    "dLvDxJ7t2fruXtSkkqG/cwY1yQI8O+WZYPDThKPcDmNbaxVE9lOizAHXFVsfYrXA" +
+                    "PbbMOkzKehYwaIikmNgcpxtQNw+wikJiZb9N8VwwtwHK71XEFi+n5DGlPa9VDYgB" +
+                    "YkBcxvVo2rbE3i3teQgHm+pWZNP08aFNWwMk9yQkm/SOGdLq1jLbQA9yd7fyR1Ct" +
+                    "W1GLzKi1Ojr/6XiB9/noL3oxP/+gb8OSgcqVfkZp4QLvrGdlKiOI2fE7Bslmzn6l" +
+                    "B3UTpApjab7BQ99rCXzDwt3Xd7IrCtAJNkxi302J7k6hnGlW8S4oPQBElkOtoH9y" +
+                    "XEhp9rNS0lZiuwtFmWW2q50fkQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G" +
+                    "A1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUZw5JLGEXnuvt4FTnhNmbrWRgc2UwDQYJ" +
+                    "KoZIhvcNAQELBQADggIBAFPoGFDyzFg9B9+jJUPGW32omftBhChVcgjllI07RCie" +
+                    "KTMBi47+auuLgiMox3xRyP7/dX7YaUeMXEQ1BMv6nlrsXWv1lH4yu+RNuehPlqRs" +
+                    "fY351mAfPtQ654SBUi0Wg++9iyTOfgF5a9IWEDt4lnSZMvA4vlw8pUCz6zpKXHnA" +
+                    "RXKrpY3bU+2dnrFDKR0XQhmAQdo7UvdsT1elVoFIxHhLpwfzx+kpEhtrXw3nGgt+" +
+                    "M4jNp684XoWpxVGaQ4Vvv00Sm2DQ8jq2sf9F+kRWszZpQOTiMGKZr0lX2CI5cww1" +
+                    "dfmd1BkAjI9cIWLkD8YSeaggZzvYe1o9d7e7lKfdJmjDlSQ0uBiG77keUK4tF2fi" +
+                    "xFTxibtPux56p3GYQ2GdRsBaKjH3A3HMJSKXwIGR+wb1sgz/bBdlyJSylG8hYD//" +
+                    "0Hyo+UrMUszAdszoPhMY+4Ol3QE3QRWzXi+W/NtKeYD2K8xUzjZM10wMdxCfoFOa" +
+                    "8bzzWnxZQlnu880ULUSHIxDPeE+DDZYYOaN1hV2Rh/hrFKvvV+gJj2eXHF5G7y9u" +
+                    "Yg7nHYCCf7Hy8UTIXDtAAeDCQNon1ReN8G+XOqhLQ9TalmnJ5U5ARtC0MdQDht7T" +
+                    "DZpWeEVv+pQHARX9GDV/T85MV2RPJWKqfZ6kK0gvQDkunADdg8IhZAjwMMx3k6B/",
+
+            "MIIFbDCCA1SgAwIBAgIQaAV8NQv/Xdusi4IU+tpUfjANBgkqhkiG9w0BAQsFADBQ" +
+                    "MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPV0ZBIEhvdHNwb3QgMi4wMScwJQYDVQQD" +
+                    "Ex5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0gMDEwHhcNMTMxMTIwMDAwMDAw" +
+                    "WhcNNDMxMTE5MjM1OTU5WjBQMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPV0ZBIEhv" +
+                    "dHNwb3QgMi4wMScwJQYDVQQDEx5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0g" +
+                    "MDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/gf4CHxWjr2EcktAZ" +
+                    "pHT4z1yFYZILD3ZVqvzzXBK+YKjWhjsgZ28Z1VwXqu51JvVzwTGDalPf5m7zMcJW" +
+                    "CpPtPBdxxwQ/cBDPK4w+/sCuYYSddlMLzwZ/IgwFike12tKTR7Kk7Nk6ghrYaxCG" +
+                    "R+QEZDVrxITj79vGpgk2otVnMI4d3H9mWt1o6Lx+hVioyBgOvmo2OWHR2uKkbg5h" +
+                    "tktXqmBEtzK+qDqIIUY4WRRZHxlOaF2/EdIIGhXlf+Vlr13aPqOPiDiE08o+GARz" +
+                    "TIp8BrW2boo0+2kpEFUKiqc427vOYEkUdSMfwu4aGOcuOewc8sk6ztquL/JcPROL" +
+                    "VSFSSFR3HKhUto8EJcHEEG9wzcOi1OO/OOSVxjNwiaV/hB9Ed1wvoBhiJ+C+Q8/K" +
+                    "HXmoH/ankXDaB06yjt2Ojemt0nO45qlarRj8tO7zbpghJuJxztur47U7PJta7Zcg" +
+                    "z7kOPJPTAbzmOU2TXt1pXO1hVnSlV+M1rRwe7qivnSMMrTnkX15YWmyK27/tgJeu" +
+                    "muR2YzvPwPtF/m1N0bRKI7FW05NYg3smItFq0E/eyf/orgolcXTZ7zNRyRGnjWNs" +
+                    "/w9SDbdby0uVUfdN4V/5uC4HBmA1rikoBbGZ+nzCtesY4yW8eEwMfguVpNT3ueaU" +
+                    "q30nufeY2VnA3Rv1WH8TaeZU+wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G" +
+                    "A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU+RjGVZbebjpzEPfthaTLqbvXMiEwDQYJ" +
+                    "KoZIhvcNAQELBQADggIBABj3LP1UXVa16HYeXC1+GU1dX/cla1n1bwpIlxRnCZ5/" +
+                    "3I3zGw/nRnsLUTkGf8q3XCgin+jX22kyzzQNrgepn0zqBsmAj+pjUUwWzYQUzphc" +
+                    "Uzmg4PJRWaEaGG3kvD+wJEC0pWvIhe48qcq8FZCCmjbvecEVn5mM0smPzPyUjf/o" +
+                    "fjUMQvVWqug/Ff5HT6kbyDWhC3nD+8IZ5PjyO85OnoBnQkr8WYwr24XJgO2HS2rs" +
+                    "W40CzQe3Kdg7HHyef+/iyLYTBJH7EUJPCHGVQtZ3q0aNqURkutXJ/CxKJYMcNTEB" +
+                    "x+a09EhZ6DOHQDqsdTuAqGh3VyrxhFk+3suNsxoh6XaRK10VslvdNB/1YKfU8DWe" +
+                    "V6XfDH/TR0NIL04exUp3rER8sERulpJGBOnaG6OQKh4bFYDB406+QfusQnvO0aYR" +
+                    "UXJzf01B15HRJgpZsggpIuex0UDcJhTTpkRfTj8L4ayUce2ZRsGn3dBaT9ZMx4o9" +
+                    "E/YsQyOpfw28gM5u+zZt4BJz4gAaRGbp4r4sk5Vm/P1/0EXJ70Du6K9d0HAHtpEv" +
+                    "Y94Ww5W6fpMDdyAKYTXZBgTX3cqtikNkLX/kHH8l4o/XW2sXqU3X7vOYqgeVYoD9" +
+                    "NnhZXYCerH4Se5Lgj8/KhXxRWtcn3XduMdkC6UTApMooA64Vs508173Z3lJn2SeQ",
+
+            "MIIFXTCCA0WgAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEY" +
+                    "MBYGA1UECgwPV0ZBIEhvdHNwb3QgMi4wMScwJQYDVQQDDB5Ib3RzcG90IDIuMCBU" +
+                    "cnVzdCBSb290IENBIC0gMDIwHhcNMTMxMjAyMjA1NzU3WhcNNDMxMjAyMjA1NTAz" +
+                    "WjBQMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPV0ZBIEhvdHNwb3QgMi4wMScwJQYD" +
+                    "VQQDDB5Ib3RzcG90IDIuMCBUcnVzdCBSb290IENBIC0gMDIwggIiMA0GCSqGSIb3" +
+                    "DQEBAQUAA4ICDwAwggIKAoICAQDCSoMqNhtTwbnIsINp6nUhx5UFuq9ZQoTv+KDk" +
+                    "vAajT0di6+cQG3sAVvZLySmJoiBAv3PizYYLOD4eGMrFQRqi7PmSJ83WqNv23ZYF" +
+                    "ryFFJiy/URXc/ALDuB3dgElPt24Mx7n2xDPAh9t82HTmuskpQRrsyg9QPoi5rRRS" +
+                    "Djm5mjFJjKChq99RWcweNV/KGH1sTwcmlDmNMScK16A+BBNiSvmZlsGJgAlP369k" +
+                    "lnNqt6UiDhepcktuKpHmSvNel+c/xqzR0gURfUnXcZhzjzS94Rx5O+CNWL4EGiJq" +
+                    "qKAfk99j/lbD0MWYo7Rh0UKQlXSdohWDiV93hxvvfugej8KUOIb+1wmd1Fi+lwDZ" +
+                    "bR2yg2f0qyxbC/tAV4JJNnuDLFb19leD78x+68eAnlbMi+xMH5lINs15+26s2H5d" +
+                    "lx9kwRDBJq02LuHnen6FLafWjejnnBQ/PuGD0ACvBegSsDKDaCuTAnTNS6MDmQr4" +
+                    "wza08iX360ZN+BbSAnCK1YGa/7J7fhyydwxLJ7s5Eo0b6SUMY87FMc5XmkAk4xxL" +
+                    "MLqS2HMtqsGBI5JQT0SgH0ghE6DjMWArBTZcD+swuzTi1/Cz5+Z9Es8xJ3MPvSZW" +
+                    "pJi6VVB2eVMAqfHOj4ozHoVpvJypIVGRwWBzVRWom76R47utuRK6uKzoLiB1jwE5" +
+                    "vwHpUQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBxjAd" +
+                    "BgNVHQ4EFgQU5C9c1OMsB+/MOwl9OKG2D/XSwrUwDQYJKoZIhvcNAQELBQADggIB" +
+                    "AGULYE/VrnA3K0ptgHrWlQoPfp5wGvScgsmy0wp9qE3b6n/4bLehBKb5w4Y3JVA9" +
+                    "gjxoQ5xE2ssDtULZ3nKnGWmMN3qOBoRZCA6KjKs1860p09tm1ScUsajDJ15Tp1nI" +
+                    "zfR0oP63+2bJx+JXM8fPKOJe245hj2rs1c3JXsGCe+UVrlGsotG+wR0PdrejaXJ8" +
+                    "HbhBQHcbhgjsD1Gb6Egm4YxRKAtcVY3q9EKKWAGhbC1qvCh1iLNKo3FeGgm2r3EG" +
+                    "L4cYJBb2fhSKltjISqCDhYq4tplOIeQSJJyJC8gfW/BnMU39lTjNgnSjjGPLQXGV" +
+                    "+Ulb/CgNMJ3RhRJdBoLcpIm/EeLx6JLq/2Erxy7CxjaSOcD0UKa14+dzLSHVsXft" +
+                    "HZuOy548X8m18KruSZsf5uAT3c7NqlXtr9YgOVUqSJykNAHTGi/BHB1dC2clKvxN" +
+                    "ElfLWWrG9yaAd5TFW0+3wsaDIwRZL584AsFwwAD3KMo1oU/2zRvtm0E+VghsuD/Z" +
+                    "IE1xaVGTPaL7ph/YgC9+0rGHieauT8SXz6Ryp3h0RtYMLFZOMTKM7xjmcbMZDwrO" +
+                    "c+J/XjK9dbiCqlx5/B8P0xWaYYHzvE5/fafiPYzoGyFVUXquu0dFCCQrvjF/y0tC" +
+                    "TPm4hQim3k1F+5NChcbeNggN+kq+VdlSqPhQEuOY+kNv"
+    };
+
+    //private static final Set<TrustAnchor> sTrustAnchors = buildCertSet();
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUStatus.java b/packages/Osu/src/com/android/hotspot2/osu/OSUStatus.java
new file mode 100644
index 0000000..00f0634
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUStatus.java
@@ -0,0 +1,5 @@
+package com.android.hotspot2.osu;
+
+public enum OSUStatus {
+    OK, ProvComplete, RemediationComplete, UpdateComplete, ExchangeComplete, Unknown, Error
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/PostDevDataResponse.java b/packages/Osu/src/com/android/hotspot2/osu/PostDevDataResponse.java
new file mode 100644
index 0000000..12b9997
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/PostDevDataResponse.java
@@ -0,0 +1,49 @@
+package com.android.hotspot2.osu;
+
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.XMLNode;
+import com.android.hotspot2.osu.commands.OSUCommandData;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class PostDevDataResponse extends OSUResponse {
+    private final List<OSUCommand> mOSUCommands;
+
+    public PostDevDataResponse(XMLNode root) throws OMAException {
+        super(root, OSUMessageType.PostDevData);
+
+        if (getStatus() == OSUStatus.Error) {
+            mOSUCommands = null;
+            return;
+        }
+
+        mOSUCommands = new ArrayList<>();
+        for (XMLNode child : root.getChildren()) {
+            mOSUCommands.add(new OSUCommand(child));
+        }
+    }
+
+    public OSUCommandID getOSUCommand() {
+        return mOSUCommands.size() == 1 ? mOSUCommands.get(0).getOSUCommand() : null;
+    }
+
+    public ExecCommand getExecCommand() {
+        return mOSUCommands.size() == 1 ? mOSUCommands.get(0).getExecCommand() : null;
+    }
+
+    public OSUCommandData getCommandData() {
+        return mOSUCommands.size() == 1 ? mOSUCommands.get(0).getCommandData() : null;
+    }
+
+    public Collection<OSUCommand> getCommands() {
+        return Collections.unmodifiableCollection(mOSUCommands);
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + ", commands " + mOSUCommands;
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/RequestReason.java b/packages/Osu/src/com/android/hotspot2/osu/RequestReason.java
new file mode 100644
index 0000000..db222b4
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/RequestReason.java
@@ -0,0 +1,16 @@
+package com.android.hotspot2.osu;
+
+public enum RequestReason {
+    SubRegistration,
+    SubProvisioning,
+    SubRemediation,
+    InputComplete,
+    NoClientCert,
+    CertEnrollmentComplete,
+    CertEnrollmentFailed,
+    SubMetaDataUpdate,
+    PolicyUpdate,
+    NextCommand,
+    MOUpload,
+    Unspecified
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/ResponseFactory.java b/packages/Osu/src/com/android/hotspot2/osu/ResponseFactory.java
new file mode 100644
index 0000000..3e236a7
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/ResponseFactory.java
@@ -0,0 +1,8 @@
+package com.android.hotspot2.osu;
+
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.XMLNode;
+
+public interface ResponseFactory {
+    public OSUResponse buildResponse(XMLNode root) throws OMAException;
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/SOAPBuilder.java b/packages/Osu/src/com/android/hotspot2/osu/SOAPBuilder.java
new file mode 100644
index 0000000..e2f91ea
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/SOAPBuilder.java
@@ -0,0 +1,188 @@
+package com.android.hotspot2.osu;
+
+import com.android.hotspot2.omadm.MOTree;
+import com.android.hotspot2.omadm.OMAConstants;
+import com.android.hotspot2.omadm.XMLNode;
+
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SOAPBuilder {
+    private static final String EnvelopeTag = "s12:Envelope";
+    private static final String BodyTag = "s12:Body";
+
+    private static final Map<String, String> sEnvelopeAttributes = new HashMap<>(2);
+    private static final Map<RequestReason, String> sRequestReasons =
+            new EnumMap<>(RequestReason.class);
+
+    static {
+        sEnvelopeAttributes.put("xmlns:s12", "http://www.w3.org/2003/05/soap-envelope");
+        sEnvelopeAttributes.put("xmlns:spp",
+                "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp");
+
+        sRequestReasons.put(RequestReason.SubRegistration, "Subscription registration");
+        sRequestReasons.put(RequestReason.SubProvisioning, "Subscription provisioning");
+        sRequestReasons.put(RequestReason.SubRemediation, "Subscription remediation");
+        sRequestReasons.put(RequestReason.InputComplete, "User input completed");
+        sRequestReasons.put(RequestReason.NoClientCert, "No acceptable client certificate");
+        sRequestReasons.put(RequestReason.CertEnrollmentComplete,
+                "Certificate enrollment completed");
+        sRequestReasons.put(RequestReason.CertEnrollmentFailed, "Certificate enrollment failed");
+        sRequestReasons.put(RequestReason.SubMetaDataUpdate, "Subscription metadata update");
+        sRequestReasons.put(RequestReason.PolicyUpdate, "Policy update");
+        sRequestReasons.put(RequestReason.NextCommand, "Retrieve next command");
+        sRequestReasons.put(RequestReason.MOUpload, "MO upload");
+        sRequestReasons.put(RequestReason.Unspecified, "Unspecified");
+    }
+
+    public static String buildPostDevDataResponse(RequestReason reason, String sessionID,
+                                                  String redirURI, MOTree... mos) {
+        XMLNode envelope = buildEnvelope();
+        buildSppPostDevData(envelope.getChildren().get(0), sessionID, reason, redirURI, mos);
+        return envelope.toString();
+    }
+
+    public static String buildUpdateResponse(String sessionID, OSUError error) {
+        XMLNode envelope = buildEnvelope();
+        buildSppUpdateResponse(envelope.getChildren().get(0), sessionID, error);
+        return envelope.toString();
+    }
+
+    private static XMLNode buildEnvelope() {
+        XMLNode envelope = new XMLNode(null, EnvelopeTag, sEnvelopeAttributes);
+        envelope.addChild(new XMLNode(envelope, BodyTag, (Map<String, String>) null));
+        return envelope;
+    }
+
+    private static XMLNode buildSppPostDevData(XMLNode parent, String sessionID,
+                                               RequestReason reason, String redirURI,
+                                               MOTree... mos) {
+        Map<String, String> pddAttributes = new HashMap<>();
+        pddAttributes.put(OMAConstants.TAG_Version, OMAConstants.MOVersion);
+        pddAttributes.put("requestReason", sRequestReasons.get(reason));
+        if (sessionID != null) {
+            pddAttributes.put(OMAConstants.TAG_SessionID, sessionID);
+        }
+        if (redirURI != null) {
+            pddAttributes.put("redirectURI", redirURI);
+        }
+
+        XMLNode pddNode = new XMLNode(parent, OMAConstants.TAG_PostDevData, pddAttributes);
+
+        XMLNode vNode = new XMLNode(pddNode, OMAConstants.TAG_SupportedVersions,
+                (HashMap<String, String>) null);
+        vNode.setText("1.0");
+        pddNode.addChild(vNode);
+
+        XMLNode moNode = new XMLNode(pddNode, OMAConstants.TAG_SupportedMOs,
+                (HashMap<String, String>) null);
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (String urn : OMAConstants.SupportedMO_URNs) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(' ');
+            }
+            sb.append(urn);
+        }
+        moNode.setText(sb.toString());
+        pddNode.addChild(moNode);
+
+        if (mos != null) {
+            for (MOTree moTree : mos) {
+                Map<String, String> map = null;
+                if (moTree.getUrn() != null) {
+                    map = new HashMap<>(1);
+                    map.put(OMAConstants.SppMOAttribute, moTree.getUrn());
+                }
+                moNode = new XMLNode(pddNode, OMAConstants.TAG_MOContainer, map);
+                moNode.setText(moTree.toXml());
+                pddNode.addChild(moNode);
+            }
+        }
+
+        parent.addChild(pddNode);
+        return pddNode;
+    }
+
+    private static XMLNode buildSppUpdateResponse(XMLNode parent, String sessionID,
+                                                  OSUError error) {
+        Map<String, String> urAttributes = new HashMap<>();
+        urAttributes.put(OMAConstants.TAG_Version, OMAConstants.MOVersion);
+        if (sessionID != null) {
+            urAttributes.put(OMAConstants.TAG_SessionID, sessionID);
+        }
+        if (error == null) {
+            urAttributes.put(OMAConstants.TAG_Status, OMAConstants.mapStatus(OSUStatus.OK));
+        } else {
+            urAttributes.put(OMAConstants.TAG_Status, OMAConstants.mapStatus(OSUStatus.Error));
+        }
+
+        XMLNode urNode = new XMLNode(parent, OMAConstants.TAG_UpdateResponse, urAttributes);
+
+        if (error != null) {
+            Map<String, String> errorAttributes = new HashMap<>();
+            errorAttributes.put("errorCode", OMAConstants.mapError(error));
+            XMLNode errorNode = new XMLNode(urNode, OMAConstants.TAG_Error, errorAttributes);
+            urNode.addChild(errorNode);
+        }
+
+        parent.addChild(urNode);
+        return urNode;
+    }
+
+    /*
+    <xsd:element name="sppUpdateResponse">
+		<xsd:annotation>
+			<xsd:documentation>SOAP method used by SPP client to confirm installation of MO addition or update.</xsd:documentation>
+		</xsd:annotation>
+		<xsd:complexType>
+			<xsd:sequence>
+				<xsd:element ref="sppError" minOccurs="0"/>
+				<xsd:any namespace="##other" maxOccurs="unbounded" minOccurs="0"/>
+			</xsd:sequence>
+			<xsd:attribute ref="sppVersion" use="required"/>
+			<xsd:attribute ref="sppStatus" use="required"/>
+			<xsd:attribute ref="sessionID" use="required"/>
+			<xsd:anyAttribute namespace="##other"/>
+		</xsd:complexType>
+	</xsd:element>
+
+    <xsd:element name="sppError">
+		<xsd:annotation>
+			<xsd:documentation>Error response.</xsd:documentation>
+		</xsd:annotation>
+		<xsd:complexType>
+			<xsd:attribute name="errorCode" use="required">
+				<xsd:simpleType>
+					<xsd:restriction base="xsd:string">
+						<xsd:enumeration value="SPP version not supported"/>
+						<xsd:enumeration value="One or more mandatory MOs not supported"/>
+						<xsd:enumeration value="Credentials cannot be provisioned at this time"/>
+						<xsd:enumeration value="Remediation cannot be completed at this time"/>
+						<xsd:enumeration value="Provisioning cannot be completed at this time"/>
+						<xsd:enumeration value="Continue to use existing certificate"/>
+						<xsd:enumeration value="Cookie invalid"/>
+						<xsd:enumeration value="No corresponding web-browser-connection Session ID"/>
+						<xsd:enumeration value="Permission denied"/>
+						<xsd:enumeration value="Command failed"/>
+						<xsd:enumeration value="MO addition or update failed"/>
+						<xsd:enumeration value="Device full"/>
+						<xsd:enumeration value="Bad management tree URI"/>
+						<xsd:enumeration value="Requested entity too large"/>
+						<xsd:enumeration value="Command not allowed"/>
+						<xsd:enumeration value="Command not executed due to user"/>
+						<xsd:enumeration value="Not found"/>
+						<xsd:enumeration value="Other"/>
+					</xsd:restriction>
+				</xsd:simpleType>
+			</xsd:attribute>
+			<xsd:anyAttribute namespace="##other"/>
+		</xsd:complexType>
+	</xsd:element>
+
+
+     */
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/SOAPParser.java b/packages/Osu/src/com/android/hotspot2/osu/SOAPParser.java
new file mode 100644
index 0000000..b848ba9
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/SOAPParser.java
@@ -0,0 +1,327 @@
+package com.android.hotspot2.osu;
+
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.XMLNode;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+public class SOAPParser {
+
+    private static final String EnvelopeTag = "envelope";
+    private static final String BodyTag = "body";
+
+    private static final Map<String, ResponseFactory> sResponseMap = new HashMap<>();
+
+    static {
+        sResponseMap.put("spppostdevdataresponse", new ResponseFactory() {
+            @Override
+            public OSUResponse buildResponse(XMLNode root) throws OMAException {
+                return new PostDevDataResponse(root);
+            }
+        });
+        sResponseMap.put("sppexchangecomplete", new ResponseFactory() {
+            @Override
+            public OSUResponse buildResponse(XMLNode root) throws OMAException {
+                return new ExchangeCompleteResponse(root);
+            }
+        });
+        sResponseMap.put("getcertificate", new ResponseFactory() {
+            @Override
+            public OSUResponse buildResponse(XMLNode root) {
+                return null;
+            }
+        });
+        sResponseMap.put("spperror", new ResponseFactory() {
+            @Override
+            public OSUResponse buildResponse(XMLNode root) {
+                return null;
+            }
+        });
+    }
+
+    private final XMLNode mResponseNode;
+
+    public SOAPParser(InputStream in)
+            throws ParserConfigurationException, SAXException, IOException {
+        XMLNode root;
+
+        try {
+            XMLParser parser = new XMLParser(in);
+            root = parser.getRoot();
+        } finally {
+            in.close();
+        }
+
+        String[] nsn = root.getTag().split(":");
+        if (nsn.length > 2) {
+            throw new OMAException("Bad root tag syntax: '" + root.getTag() + "'");
+        } else if (!EnvelopeTag.equalsIgnoreCase(nsn[nsn.length - 1])) {
+            throw new OMAException("Expected envelope: '" + root.getTag() + "'");
+        }
+
+        String bodyTag = nsn.length > 1 ? (nsn[0] + ":" + BodyTag) : BodyTag;
+        XMLNode body = null;
+
+        for (XMLNode child : root.getChildren()) {
+            if (bodyTag.equalsIgnoreCase(child.getTag())) {
+                body = child;
+                break;
+            }
+        }
+
+        if (body == null || body.getChildren().isEmpty()) {
+            throw new OMAException("Missing SOAP body");
+        }
+
+        mResponseNode = body.getSoleChild();
+    }
+
+    public OSUResponse getResponse() throws OMAException {
+        ResponseFactory responseFactory = sResponseMap.get(mResponseNode.getStrippedTag());
+        if (responseFactory == null) {
+            throw new OMAException("Unknown response type: '"
+                    + mResponseNode.getStrippedTag() + "'");
+        }
+        return responseFactory.buildResponse(mResponseNode);
+    }
+
+    public XMLNode getResponseNode() {
+        return mResponseNode;
+    }
+
+
+    /*
+    <xsd:element name="sppPostDevDataResponse">
+		<xsd:annotation>
+			<xsd:documentation>SOAP method response from SPP server.</xsd:documentation>
+		</xsd:annotation>
+		<xsd:complexType>
+			<xsd:choice>
+				<xsd:element ref="sppError"/>
+				<xsd:element name="exec">
+					<xsd:annotation>
+						<xsd:documentation>Receipt of this element by a mobile device causes the following command to be executed.</xsd:documentation>
+					</xsd:annotation>
+					<xsd:complexType>
+						<xsd:choice>
+							<xsd:element name="launchBrowserToURI" type="httpsURIType">
+								<xsd:annotation>
+									<xsd:documentation>When the mobile device receives this command, it launches its default browser to the URI contained in this element.  The URI must use HTTPS as the protocol and must contain an FQDN.</xsd:documentation>
+								</xsd:annotation>
+							</xsd:element>
+							<xsd:element ref="getCertificate"/>
+							<xsd:element name="useClientCertTLS">
+								<xsd:annotation>
+									<xsd:documentation>Command to mobile to re-negotiate the TLS connection using a client certificate of the accepted type or Issuer to authenticate with the Subscription server.</xsd:documentation>
+								</xsd:annotation>
+								<xsd:complexType>
+									<xsd:sequence>
+										<xsd:element name="providerIssuerName" minOccurs="0"
+											maxOccurs="unbounded">
+											<xsd:complexType>
+												<xsd:attribute name="name" type="xsd:string">
+												<xsd:annotation>
+												<xsd:documentation>The issuer name of an acceptable provider-issued certificate.  The text of this element is formatted in accordance with the Issuer Name field in RFC-3280.  This element is present only when acceptProviderCerts is true.</xsd:documentation>
+												</xsd:annotation>
+												</xsd:attribute>
+												<xsd:anyAttribute namespace="##other"/>
+											</xsd:complexType>
+										</xsd:element>
+										<xsd:any namespace="##other" minOccurs="0"
+											maxOccurs="unbounded"/>
+									</xsd:sequence>
+									<xsd:attribute name="acceptMfgCerts" type="xsd:boolean"
+										use="optional" default="false">
+										<xsd:annotation>
+											<xsd:documentation>When this boolean is true, IEEE 802.1ar manufacturing certificates are acceptable for mobile device authentication.</xsd:documentation>
+										</xsd:annotation>
+									</xsd:attribute>
+									<xsd:attribute name="acceptProviderCerts" type="xsd:boolean"
+										use="optional" default="true">
+										<xsd:annotation>
+											<xsd:documentation>When this boolean is true, X509v3 certificates issued by providers identified in the providerIssuerName child element(s) are acceptable for mobile device authentication.</xsd:documentation>
+										</xsd:annotation>
+									</xsd:attribute>
+									<xsd:anyAttribute namespace="##other"/>
+								</xsd:complexType>
+							</xsd:element>
+							<xsd:element name="uploadMO" maxOccurs="unbounded">
+								<xsd:annotation>
+									<xsd:documentation>Command to mobile to upload the MO named in the moURN attribute to the SPP server.</xsd:documentation>
+								</xsd:annotation>
+								<xsd:complexType>
+									<xsd:attribute ref="moURN"/>
+								</xsd:complexType>
+							</xsd:element>
+							<xsd:any namespace="##other" maxOccurs="unbounded" minOccurs="0">
+								<xsd:annotation>
+									<xsd:documentation>Element to allow the addition of new commands in the future.</xsd:documentation>
+								</xsd:annotation>
+							</xsd:any>
+						</xsd:choice>
+						<xsd:anyAttribute namespace="##other"/>
+					</xsd:complexType>
+				</xsd:element>
+				<xsd:element name="addMO">
+					<xsd:annotation>
+						<xsd:documentation>This command causes an management object in the mobile devices management tree at the specified location to be added.  If there is already a management object at that location, the object is replaced.</xsd:documentation>
+					</xsd:annotation>
+					<xsd:complexType>
+						<xsd:simpleContent>
+							<xsd:extension base="xsd:string">
+								<xsd:attribute ref="managementTreeURI"/>
+								<xsd:attribute ref="moURN"/>
+							</xsd:extension>
+						</xsd:simpleContent>
+					</xsd:complexType>
+				</xsd:element>
+				<xsd:element maxOccurs="unbounded" name="updateNode">
+					<xsd:annotation>
+						<xsd:documentation>This command causes the update of an interior node and its child nodes (if any) at the location specified in the management tree URI attribute.  The content of this element is the MO node XML.</xsd:documentation>
+					</xsd:annotation>
+					<xsd:complexType>
+						<xsd:simpleContent>
+							<xsd:extension base="xsd:string">
+								<xsd:attribute ref="managementTreeURI"/>
+							</xsd:extension>
+						</xsd:simpleContent>
+					</xsd:complexType>
+				</xsd:element>
+				<xsd:element name="noMOUpdate">
+					<xsd:annotation>
+						<xsd:documentation>This response is used when there is no command to be executed nor update of any MO required.</xsd:documentation>
+					</xsd:annotation>
+				</xsd:element>
+				<xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded">
+					<xsd:annotation>
+						<xsd:documentation>For vendor-specific extensions or future needs.</xsd:documentation>
+					</xsd:annotation>
+				</xsd:any>
+			</xsd:choice>
+			<xsd:attribute ref="sppVersion" use="required"/>
+			<xsd:attribute ref="sppStatus" use="required"/>
+			<xsd:attribute ref="moreCommands" use="optional"/>
+			<xsd:attribute ref="sessionID" use="required"/>
+			<xsd:anyAttribute namespace="##other"/>
+		</xsd:complexType>
+	</xsd:element>
+	<xsd:element name="sppUpdateResponse">
+		<xsd:annotation>
+			<xsd:documentation>SOAP method used by SPP client to confirm installation of MO addition or update.</xsd:documentation>
+		</xsd:annotation>
+		<xsd:complexType>
+			<xsd:sequence>
+				<xsd:element ref="sppError" minOccurs="0"/>
+				<xsd:any namespace="##other" maxOccurs="unbounded" minOccurs="0"/>
+			</xsd:sequence>
+			<xsd:attribute ref="sppVersion" use="required"/>
+			<xsd:attribute ref="sppStatus" use="required"/>
+			<xsd:attribute ref="sessionID" use="required"/>
+			<xsd:anyAttribute namespace="##other"/>
+		</xsd:complexType>
+	</xsd:element>
+	<xsd:element name="sppExchangeComplete">
+		<xsd:annotation>
+			<xsd:documentation>SOAP method used by SPP server to end session.</xsd:documentation>
+		</xsd:annotation>
+		<xsd:complexType>
+			<xsd:sequence>
+				<xsd:element ref="sppError" minOccurs="0"/>
+				<xsd:any namespace="##other" maxOccurs="unbounded" minOccurs="0"/>
+			</xsd:sequence>
+			<xsd:attribute ref="sppVersion" use="required"/>
+			<xsd:attribute ref="sppStatus" use="required"/>
+			<xsd:attribute ref="sessionID" use="required"/>
+			<xsd:anyAttribute namespace="##other"/>
+		</xsd:complexType>
+	</xsd:element>
+	<xsd:element name="getCertificate">
+		<xsd:annotation>
+			<xsd:documentation>Command to mobile to initiate certificate enrollment or re-enrollment and is a container for metadata to enable enrollment.</xsd:documentation>
+		</xsd:annotation>
+		<xsd:complexType>
+			<xsd:sequence>
+				<xsd:element name="enrollmentServerURI" type="httpsURIType">
+					<xsd:annotation>
+						<xsd:documentation>HTTPS URI of the server to be contacted to initiate certificate enrollment.  The URI must contain an FQDN.</xsd:documentation>
+					</xsd:annotation>
+				</xsd:element>
+				<xsd:element name="estUserID" minOccurs="0">
+					<xsd:annotation>
+						<xsd:documentation>Temporary userid used by an EST client to authenticate to the EST server using HTTP Digest authentication.  This element must be used for initial certificate enrollment; its use is optional for certificate re-enrollment.</xsd:documentation>
+					</xsd:annotation>
+					<xsd:simpleType>
+						<xsd:restriction base="xsd:string">
+							<xsd:maxLength value="255"/>
+						</xsd:restriction>
+					</xsd:simpleType>
+				</xsd:element>
+				<xsd:element name="estPassword" minOccurs="0">
+					<xsd:annotation>
+						<xsd:documentation>Temporary password used by an EST client to authenticate to the EST server using HTTP Digest authentication.  This element must be used for initial certificate enrollment; its use is optional for certificate re-enrollment.</xsd:documentation>
+					</xsd:annotation>
+					<xsd:simpleType>
+						<xsd:restriction base="xsd:base64Binary">
+							<xsd:maxLength value="340"/>
+						</xsd:restriction>
+					</xsd:simpleType>
+				</xsd:element>
+				<xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded">
+					<xsd:annotation>
+						<xsd:documentation>For vendor-specific extensions or future needs.</xsd:documentation>
+					</xsd:annotation>
+				</xsd:any>
+			</xsd:sequence>
+			<xsd:attribute name="enrollmentProtocol" use="required">
+				<xsd:simpleType>
+					<xsd:restriction base="xsd:string">
+						<xsd:enumeration value="EST"/>
+						<xsd:enumeration value="Other"/>
+					</xsd:restriction>
+				</xsd:simpleType>
+			</xsd:attribute>
+			<xsd:anyAttribute namespace="##other"/>
+		</xsd:complexType>
+	</xsd:element>
+	<xsd:element name="sppError">
+		<xsd:annotation>
+			<xsd:documentation>Error response.</xsd:documentation>
+		</xsd:annotation>
+		<xsd:complexType>
+			<xsd:attribute name="errorCode" use="required">
+				<xsd:simpleType>
+					<xsd:restriction base="xsd:string">
+						<xsd:enumeration value="SPP version not supported"/>
+						<xsd:enumeration value="One or more mandatory MOs not supported"/>
+						<xsd:enumeration value="Credentials cannot be provisioned at this time"/>
+						<xsd:enumeration value="Remediation cannot be completed at this time"/>
+						<xsd:enumeration value="Provisioning cannot be completed at this time"/>
+						<xsd:enumeration value="Continue to use existing certificate"/>
+						<xsd:enumeration value="Cookie invalid"/>
+						<xsd:enumeration value="No corresponding web-browser-connection Session ID"/>
+						<xsd:enumeration value="Permission denied"/>
+						<xsd:enumeration value="Command failed"/>
+						<xsd:enumeration value="MO addition or update failed"/>
+						<xsd:enumeration value="Device full"/>
+						<xsd:enumeration value="Bad management tree URI"/>
+						<xsd:enumeration value="Requested entity too large"/>
+						<xsd:enumeration value="Command not allowed"/>
+						<xsd:enumeration value="Command not executed due to user"/>
+						<xsd:enumeration value="Not found"/>
+						<xsd:enumeration value="Other"/>
+					</xsd:restriction>
+				</xsd:simpleType>
+			</xsd:attribute>
+			<xsd:anyAttribute namespace="##other"/>
+		</xsd:complexType>
+	</xsd:element>
+
+     */
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/SPVerifier.java b/packages/Osu/src/com/android/hotspot2/osu/SPVerifier.java
new file mode 100644
index 0000000..c529053
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/SPVerifier.java
@@ -0,0 +1,329 @@
+package com.android.hotspot2.osu;
+
+import android.util.Log;
+
+import com.android.anqp.HSIconFileElement;
+import com.android.anqp.I18Name;
+import com.android.anqp.IconInfo;
+import com.android.hotspot2.Utils;
+import com.android.hotspot2.asn1.Asn1Class;
+import com.android.hotspot2.asn1.Asn1Constructed;
+import com.android.hotspot2.asn1.Asn1Decoder;
+import com.android.hotspot2.asn1.Asn1Integer;
+import com.android.hotspot2.asn1.Asn1Object;
+import com.android.hotspot2.asn1.Asn1Octets;
+import com.android.hotspot2.asn1.Asn1Oid;
+import com.android.hotspot2.asn1.Asn1String;
+import com.android.hotspot2.asn1.OidMappings;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class SPVerifier {
+    public static final int OtherName = 0;
+    public static final int DNSName = 2;
+
+    private final OSUInfo mOSUInfo;
+
+    public SPVerifier(OSUInfo osuInfo) {
+        mOSUInfo = osuInfo;
+    }
+
+    /*
+    SEQUENCE:
+      [Context 0]:
+        SEQUENCE:
+          [Context 0]:                      -- LogotypeData
+            SEQUENCE:
+              SEQUENCE:
+                SEQUENCE:
+                  IA5String='image/png'
+                  SEQUENCE:
+                    SEQUENCE:
+                      SEQUENCE:
+                        OID=2.16.840.1.101.3.4.2.1
+                        NULL
+                      OCTET_STRING= cf aa 74 a8 ad af 85 82 06 c8 f5 b5 bf ee 45 72 8a ee ea bd 47 ab 50 d3 62 0c 92 c1 53 c3 4c 6b
+                  SEQUENCE:
+                    IA5String='http://www.r2-testbed.wi-fi.org/icon_orange_zxx.png'
+                SEQUENCE:
+                  INTEGER=4184
+                  INTEGER=-128
+                  INTEGER=61
+                  [Context 4]= 7a 78 78
+          [Context 0]:                      -- LogotypeData
+            SEQUENCE:
+              SEQUENCE:                     -- LogotypeImage
+                SEQUENCE:                   -- LogoTypeDetails
+                  IA5String='image/png'
+                  SEQUENCE:
+                    SEQUENCE:               -- HashAlgAndValue
+                      SEQUENCE:
+                        OID=2.16.840.1.101.3.4.2.1
+                        NULL
+                      OCTET_STRING= cb 35 5c ba 7a 21 59 df 8e 0a e1 d8 9f a4 81 9e 41 8f af 58 0c 08 d6 28 7f 66 22 98 13 57 95 8d
+                  SEQUENCE:
+                    IA5String='http://www.r2-testbed.wi-fi.org/icon_orange_eng.png'
+                SEQUENCE:                   -- LogotypeImageInfo
+                  INTEGER=11635
+                  INTEGER=-96
+                  INTEGER=76
+                  [Context 4]= 65 6e 67
+     */
+
+    private static class LogoTypeImage {
+        private final String mMimeType;
+        private final List<HashAlgAndValue> mHashes = new ArrayList<>();
+        private final List<String> mURIs = new ArrayList<>();
+        private final int mFileSize;
+        private final int mXsize;
+        private final int mYsize;
+        private final String mLanguage;
+
+        private LogoTypeImage(Asn1Constructed sequence) throws IOException {
+            Iterator<Asn1Object> children = sequence.getChildren().iterator();
+
+            Iterator<Asn1Object> logoTypeDetails =
+                    castObject(children.next(), Asn1Constructed.class).getChildren().iterator();
+            mMimeType = castObject(logoTypeDetails.next(), Asn1String.class).getString();
+
+            Asn1Constructed hashes = castObject(logoTypeDetails.next(), Asn1Constructed.class);
+            for (Asn1Object hash : hashes.getChildren()) {
+                mHashes.add(new HashAlgAndValue(castObject(hash, Asn1Constructed.class)));
+            }
+            Asn1Constructed urls = castObject(logoTypeDetails.next(), Asn1Constructed.class);
+            for (Asn1Object url : urls.getChildren()) {
+                mURIs.add(castObject(url, Asn1String.class).getString());
+            }
+
+            boolean imageInfoSet = false;
+            int fileSize = -1;
+            int xSize = -1;
+            int ySize = -1;
+            String language = null;
+
+            if (children.hasNext()) {
+                Iterator<Asn1Object> imageInfo =
+                        castObject(children.next(), Asn1Constructed.class).getChildren().iterator();
+
+                Asn1Object first = imageInfo.next();
+                if (first.getTag() == 0) {
+                    first = imageInfo.next();   // Ignore optional LogotypeImageType
+                }
+
+                fileSize = (int) castObject(first, Asn1Integer.class).getValue();
+                xSize = (int) castObject(imageInfo.next(), Asn1Integer.class).getValue();
+                ySize = (int) castObject(imageInfo.next(), Asn1Integer.class).getValue();
+                imageInfoSet = true;
+
+                if (imageInfo.hasNext()) {
+                    Asn1Object next = imageInfo.next();
+                    if (next.getTag() != 4) {
+                        next = imageInfo.hasNext() ? imageInfo.next() : null;   // Skip resolution
+                    }
+                    if (next != null && next.getTag() == 4) {
+                        language = new String(castObject(next, Asn1Octets.class).getOctets(),
+                                StandardCharsets.US_ASCII);
+                    }
+                }
+            }
+
+            if (imageInfoSet) {
+                mFileSize = complement(fileSize);
+                mXsize = complement(xSize);
+                mYsize = complement(ySize);
+            } else {
+                mFileSize = mXsize = mYsize = -1;
+            }
+            mLanguage = language;
+        }
+
+        private boolean verify(OSUInfo osuInfo) throws GeneralSecurityException, IOException {
+            IconInfo iconInfo = osuInfo.getIconInfo();
+            HSIconFileElement iconData = osuInfo.getIconFileElement();
+            if (!iconInfo.getIconType().equals(mMimeType) ||
+                    !iconInfo.getLanguage().equals(mLanguage) ||
+                    iconData.getIconData().length != mFileSize) {
+                return false;
+            }
+            for (HashAlgAndValue hash : mHashes) {
+                if (hash.getJCEName() != null) {
+                    MessageDigest digest = MessageDigest.getInstance(hash.getJCEName());
+                    byte[] computed = digest.digest(iconData.getIconData());
+                    if (!Arrays.equals(computed, hash.getHash())) {
+                        throw new IOException("Icon hash mismatch");
+                    } else {
+                        Log.d(OSUManager.TAG, "Icon verified with " + hash.getJCEName());
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "LogoTypeImage{" +
+                    "MimeType='" + mMimeType + '\'' +
+                    ", hashes=" + mHashes +
+                    ", URIs=" + mURIs +
+                    ", fileSize=" + mFileSize +
+                    ", xSize=" + mXsize +
+                    ", ySize=" + mYsize +
+                    ", language='" + mLanguage + '\'' +
+                    '}';
+        }
+    }
+
+    private static class HashAlgAndValue {
+        private final String mJCEName;
+        private final byte[] mHash;
+
+        private HashAlgAndValue(Asn1Constructed sequence) throws IOException {
+            if (sequence.getChildren().size() != 2) {
+                throw new IOException("Bad HashAlgAndValue");
+            }
+            Iterator<Asn1Object> children = sequence.getChildren().iterator();
+            mJCEName = OidMappings.getJCEName(getFirstInner(children.next(), Asn1Oid.class));
+            mHash = castObject(children.next(), Asn1Octets.class).getOctets();
+        }
+
+        public String getJCEName() {
+            return mJCEName;
+        }
+
+        public byte[] getHash() {
+            return mHash;
+        }
+
+        @Override
+        public String toString() {
+            return "HashAlgAndValue{" +
+                    "JCEName='" + mJCEName + '\'' +
+                    ", hash=" + Utils.toHex(mHash) +
+                    '}';
+        }
+    }
+
+    private static int complement(int value) {
+        return value >= 0 ? value : (~value) + 1;
+    }
+
+    private static <T extends Asn1Object> T castObject(Asn1Object object, Class<T> klass)
+            throws IOException {
+        if (object.getClass() != klass) {
+            throw new IOException("Object is an " + object.getClass().getSimpleName() +
+                    " expected an " + klass.getSimpleName());
+        }
+        return klass.cast(object);
+    }
+
+    private static <T extends Asn1Object> T getFirstInner(Asn1Object container, Class<T> klass)
+            throws IOException {
+        if (container.getClass() != Asn1Constructed.class) {
+            throw new IOException("Not a container");
+        }
+        Iterator<Asn1Object> children = container.getChildren().iterator();
+        if (!children.hasNext()) {
+            throw new IOException("No content");
+        }
+        return castObject(children.next(), klass);
+    }
+
+    public void verify(X509Certificate osuCert) throws IOException, GeneralSecurityException {
+        if (osuCert == null) {
+            throw new IOException("No OSU cert found");
+        }
+
+        checkName(castObject(getExtension(osuCert, OidMappings.IdCeSubjectAltName),
+                Asn1Constructed.class));
+
+        List<LogoTypeImage> logos = getImageData(getExtension(osuCert, OidMappings.IdPeLogotype));
+        Log.d(OSUManager.TAG, "Logos: " + logos);
+        for (LogoTypeImage logoTypeImage : logos) {
+            if (logoTypeImage.verify(mOSUInfo)) {
+                return;
+            }
+        }
+        throw new IOException("Failed to match icon against any cert logo");
+    }
+
+    private static List<LogoTypeImage> getImageData(Asn1Object logoExtension) throws IOException {
+        Asn1Constructed logo = castObject(logoExtension, Asn1Constructed.class);
+        Asn1Constructed communityLogo = castObject(logo.getChildren().iterator().next(),
+                Asn1Constructed.class);
+        if (communityLogo.getTag() != 0) {
+            throw new IOException("Expected tag [0] for communityLogos");
+        }
+
+        List<LogoTypeImage> images = new ArrayList<>();
+        Asn1Constructed communityLogoSeq = castObject(communityLogo.getChildren().iterator().next(),
+                Asn1Constructed.class);
+        for (Asn1Object logoTypeData : communityLogoSeq.getChildren()) {
+            if (logoTypeData.getTag() != 0) {
+                throw new IOException("Expected tag [0] for LogotypeData");
+            }
+            for (Asn1Object logoTypeImage : castObject(logoTypeData.getChildren().iterator().next(),
+                    Asn1Constructed.class).getChildren()) {
+                // only read the image SEQUENCE and skip any audio [1] tags
+                if (logoTypeImage.getAsn1Class() == Asn1Class.Universal) {
+                    images.add(new LogoTypeImage(castObject(logoTypeImage, Asn1Constructed.class)));
+                }
+            }
+        }
+        return images;
+    }
+
+    private void checkName(Asn1Constructed altName) throws IOException {
+        Map<String, I18Name> friendlyNames = new HashMap<>();
+        for (Asn1Object name : altName.getChildren()) {
+            if (name.getAsn1Class() == Asn1Class.Context && name.getTag() == OtherName) {
+                Asn1Constructed otherName = (Asn1Constructed) name;
+                Iterator<Asn1Object> children = otherName.getChildren().iterator();
+                if (children.hasNext()) {
+                    Asn1Object oidObject = children.next();
+                    if (OidMappings.sIdWfaHotspotFriendlyName.equals(oidObject) &&
+                            children.hasNext()) {
+                        Asn1Constructed value = castObject(children.next(), Asn1Constructed.class);
+                        String text = castObject(value.getChildren().iterator().next(),
+                                Asn1String.class).getString();
+                        I18Name friendlyName = new I18Name(text);
+                        friendlyNames.put(friendlyName.getLanguage(), friendlyName);
+                    }
+                }
+            }
+        }
+        Log.d(OSUManager.TAG, "Friendly names: " + friendlyNames.values());
+        for (I18Name osuName : mOSUInfo.getOSUProvider().getNames()) {
+            I18Name friendlyName = friendlyNames.get(osuName.getLanguage());
+            if (!osuName.equals(friendlyName)) {
+                throw new IOException("Friendly name '" + osuName + " not in certificate");
+            }
+        }
+    }
+
+    private static Asn1Object getExtension(X509Certificate certificate, String extension)
+            throws GeneralSecurityException, IOException {
+        byte[] data = certificate.getExtensionValue(extension);
+        if (data == null) {
+            return null;
+        }
+        Asn1Octets octetString = (Asn1Octets) Asn1Decoder.decode(ByteBuffer.wrap(data)).
+                iterator().next();
+        Asn1Constructed sequence = castObject(Asn1Decoder.decode(
+                        ByteBuffer.wrap(octetString.getOctets())).iterator().next(),
+                Asn1Constructed.class);
+        Log.d(OSUManager.TAG, "Extension " + extension + ": " + sequence);
+        return sequence;
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/UserInputListener.java b/packages/Osu/src/com/android/hotspot2/osu/UserInputListener.java
new file mode 100644
index 0000000..ca30e3d
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/UserInputListener.java
@@ -0,0 +1,46 @@
+package com.android.hotspot2.osu;
+
+import android.net.Network;
+
+import java.net.URL;
+
+public interface UserInputListener {
+    /**
+     * Launch an appropriate application to handle user input and HTTP exchanges to the target
+     * URL. Under normal circumstances this implies that a web-browser is started and pointed at
+     * the target URL from which it is supposed to perform an initial HTTP GET operation.
+     * This call must not block beyond the time it takes to launch the user agent, i.e. must return
+     * well before the HTTP exchange terminates.
+     * @param target A fully encoded URL to which to send an initial HTTP GET and then handle
+     *               subsequent HTTP exchanges.
+     * @param endRedirect A URL to which the user agent will be redirected upon completion of
+     *                    the HTTP exchange. This parameter is for informational purposes only
+     *                    as the redirect to the URL is the responsibility of the remote server.
+     */
+    public void requestUserInput(URL target, Network network, URL endRedirect);
+
+    /**
+     * Notification that status of the OSU operation has changed. The implementation may choose to
+     * return a string that will be passed to the user agent. Please note that the string is
+     * passed as the payload of (the redirect) HTTP connection to the agent and must be formatted
+     * appropriately (e.g. as well formed HTML).
+     * Returning a null string on the initial status update of UserInputComplete or UserInputAborted
+     * will cause the local "redirect" web-server to terminate and any further strings returned will
+     * be ignored.
+     * If programmatic termination of the user agent is desired, it should be initiated from within
+     * the implementation of this method.
+     * @param status
+     * @param message
+     * @return
+     */
+    public String operationStatus(String spIdentity, OSUOperationStatus status, String message);
+
+    /**
+     * Notify the user that a de-authentication event is imminent.
+     * @param ess set to indicate that the de-authentication is for an ESS instead of a BSS
+     * @param delay delay the number of seconds that the user will have to wait before
+     *              reassociating with the BSS or ESS.
+     * @param url a URL to which to redirect the user
+     */
+    public void deAuthNotification(String spIdentity, boolean ess, int delay, URL url);
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/WiFiKeyManager.java b/packages/Osu/src/com/android/hotspot2/osu/WiFiKeyManager.java
new file mode 100644
index 0000000..54a3c4d
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/WiFiKeyManager.java
@@ -0,0 +1,172 @@
+package com.android.hotspot2.osu;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.X509KeyManager;
+import javax.security.auth.x500.X500Principal;
+
+public class WiFiKeyManager implements X509KeyManager {
+    private final KeyStore mKeyStore;
+    private final Map<X500Principal, String[]> mAliases = new HashMap<>();
+
+    public WiFiKeyManager(KeyStore keyStore) throws IOException {
+        mKeyStore = keyStore;
+    }
+
+    public void enableClientAuth(List<String> issuerNames) throws GeneralSecurityException,
+            IOException {
+
+        Set<X500Principal> acceptedIssuers = new HashSet<>();
+        for (String issuerName : issuerNames) {
+            acceptedIssuers.add(new X500Principal(issuerName));
+        }
+
+        Enumeration<String> aliases = mKeyStore.aliases();
+        while (aliases.hasMoreElements()) {
+            String alias = aliases.nextElement();
+            Certificate cert = mKeyStore.getCertificate(alias);
+            if ((cert instanceof X509Certificate) && mKeyStore.getKey(alias, null) != null) {
+                X509Certificate x509Certificate = (X509Certificate) cert;
+                X500Principal issuer = x509Certificate.getIssuerX500Principal();
+                if (acceptedIssuers.contains(issuer)) {
+                    mAliases.put(issuer, new String[]{alias, cert.getPublicKey().getAlgorithm()});
+                }
+            }
+        }
+
+        if (mAliases.isEmpty()) {
+            throw new IOException("No aliases match requested issuers: " + issuerNames);
+        }
+    }
+
+    private static class AliasEntry implements Comparable<AliasEntry> {
+        private final int mPreference;
+        private final String mAlias;
+
+        private AliasEntry(int preference, String alias) {
+            mPreference = preference;
+            mAlias = alias;
+        }
+
+        public int getPreference() {
+            return mPreference;
+        }
+
+        public String getAlias() {
+            return mAlias;
+        }
+
+        @Override
+        public int compareTo(AliasEntry other) {
+            return Integer.compare(getPreference(), other.getPreference());
+        }
+    }
+
+    @Override
+    public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) {
+
+        Map<String, Integer> keyPrefs = new HashMap<>(keyTypes.length);
+        int pref = 0;
+        for (String keyType : keyTypes) {
+            keyPrefs.put(keyType, pref++);
+        }
+
+        List<AliasEntry> aliases = new ArrayList<>();
+        if (issuers != null) {
+            for (Principal issuer : issuers) {
+                if (issuer instanceof X500Principal) {
+                    String[] aliasAndKey = mAliases.get((X500Principal) issuer);
+                    if (aliasAndKey != null) {
+                        Integer preference = keyPrefs.get(aliasAndKey[1]);
+                        if (preference != null) {
+                            aliases.add(new AliasEntry(preference, aliasAndKey[0]));
+                        }
+                    }
+                }
+            }
+        } else {
+            for (String[] aliasAndKey : mAliases.values()) {
+                Integer preference = keyPrefs.get(aliasAndKey[1]);
+                if (preference != null) {
+                    aliases.add(new AliasEntry(preference, aliasAndKey[0]));
+                }
+            }
+        }
+        Collections.sort(aliases);
+        return aliases.isEmpty() ? null : aliases.get(0).getAlias();
+    }
+
+    @Override
+    public String[] getClientAliases(String keyType, Principal[] issuers) {
+        List<String> aliases = new ArrayList<>();
+        if (issuers != null) {
+            for (Principal issuer : issuers) {
+                if (issuer instanceof X500Principal) {
+                    String[] aliasAndKey = mAliases.get((X500Principal) issuer);
+                    if (aliasAndKey != null) {
+                        aliases.add(aliasAndKey[0]);
+                    }
+                }
+            }
+        } else {
+            for (String[] aliasAndKey : mAliases.values()) {
+                aliases.add(aliasAndKey[0]);
+            }
+        }
+        return aliases.isEmpty() ? null : aliases.toArray(new String[aliases.size()]);
+    }
+
+    @Override
+    public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String[] getServerAliases(String keyType, Principal[] issuers) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public X509Certificate[] getCertificateChain(String alias) {
+        try {
+            List<X509Certificate> certs = new ArrayList<>();
+            for (Certificate certificate : mKeyStore.getCertificateChain(alias)) {
+                if (certificate instanceof X509Certificate) {
+                    certs.add((X509Certificate) certificate);
+                }
+            }
+            return certs.toArray(new X509Certificate[certs.size()]);
+        } catch (KeyStoreException kse) {
+            Log.w(OSUManager.TAG, "Failed to retrieve certificates: " + kse);
+            return null;
+        }
+    }
+
+    @Override
+    public PrivateKey getPrivateKey(String alias) {
+        try {
+            return (PrivateKey) mKeyStore.getKey(alias, null);
+        } catch (GeneralSecurityException gse) {
+            Log.w(OSUManager.TAG, "Failed to retrieve private key: " + gse);
+            return null;
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/XMLParser.java b/packages/Osu/src/com/android/hotspot2/osu/XMLParser.java
new file mode 100644
index 0000000..b23e555
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/XMLParser.java
@@ -0,0 +1,71 @@
+package com.android.hotspot2.osu;
+
+import com.android.hotspot2.omadm.XMLNode;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+public class XMLParser extends DefaultHandler {
+    private final SAXParser mParser;
+    private final InputSource mInputSource;
+
+    private XMLNode mRoot;
+    private XMLNode mCurrent;
+
+    public XMLParser(InputStream in) throws ParserConfigurationException, SAXException {
+        mParser = SAXParserFactory.newInstance().newSAXParser();
+        mInputSource = new InputSource(new BufferedReader(
+                new InputStreamReader(in, StandardCharsets.UTF_8)));
+    }
+
+    public XMLNode getRoot() throws SAXException, IOException {
+        mParser.parse(mInputSource, this);
+        return mRoot;
+    }
+
+    @Override
+    public void startElement(String uri, String localName, String qName, Attributes attributes)
+            throws SAXException {
+        XMLNode parent = mCurrent;
+
+        mCurrent = new XMLNode(mCurrent, qName, attributes);
+        //System.out.println("Added " + mCurrent.getTag() + ", atts " + mCurrent.getAttributes());
+
+        if (mRoot == null)
+            mRoot = mCurrent;
+        else
+            parent.addChild(mCurrent);
+    }
+
+    @Override
+    public void endElement(String uri, String localName, String qName) throws SAXException {
+        if (!qName.equals(mCurrent.getTag()))
+            throw new SAXException("End tag '" + qName + "' doesn't match current node: " +
+                    mCurrent);
+
+        try {
+            mCurrent.close();
+        } catch (IOException ioe) {
+            throw new SAXException("Failed to close element", ioe);
+        }
+
+        mCurrent = mCurrent.getParent();
+    }
+
+    @Override
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        mCurrent.addText(ch, start, length);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/commands/BrowserURI.java b/packages/Osu/src/com/android/hotspot2/osu/commands/BrowserURI.java
new file mode 100644
index 0000000..137dbc9
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/commands/BrowserURI.java
@@ -0,0 +1,32 @@
+package com.android.hotspot2.osu.commands;
+
+import com.android.hotspot2.omadm.XMLNode;
+
+/*
+    <spp:sppPostDevDataResponse xmlns:spp="http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp"
+                                spp:sessionID="D74A7B03005645DAA516191DEE77B94F" spp:sppStatus="OK"
+                                spp:sppVersion="1.0">
+        <spp:exec>
+            <spp:launchBrowserToURI>
+                https://subscription-server.r2-testbed-rks.wi-fi.org:8443/web/ruckuswireles/home/-/onlinesignup/subscriberDetails?Credentials=USERNAME_PASSWORD&amp;SessionID=D74A7B03005645DAA516191DEE77B94F&amp;RedirectURI=http://127.0.0.1:12345/index.htm&amp;UpdateMethod=SPP-ClientInitiated
+            </spp:launchBrowserToURI>
+        </spp:exec>
+    </spp:sppPostDevDataResponse>
+ */
+
+public class BrowserURI implements OSUCommandData {
+    private final String mURI;
+
+    public BrowserURI(XMLNode commandNode) {
+        mURI = commandNode.getText();
+    }
+
+    public String getURI() {
+        return mURI;
+    }
+
+    @Override
+    public String toString() {
+        return "URI: " + mURI;
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/commands/ClientCertInfo.java b/packages/Osu/src/com/android/hotspot2/osu/commands/ClientCertInfo.java
new file mode 100644
index 0000000..f877353
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/commands/ClientCertInfo.java
@@ -0,0 +1,94 @@
+package com.android.hotspot2.osu.commands;
+
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.XMLNode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+<xsd:element name="useClientCertTLS">
+    <xsd:annotation>
+        <xsd:documentation>Command to mobile to re-negotiate the TLS connection using a client certificate of the accepted type or Issuer to authenticate with the Subscription server.</xsd:documentation>
+    </xsd:annotation>
+    <xsd:complexType>
+        <xsd:sequence>
+            <xsd:element name="providerIssuerName" minOccurs="0"
+                maxOccurs="unbounded">
+                <xsd:complexType>
+                    <xsd:attribute name="name" type="xsd:string">
+                    <xsd:annotation>
+                    <xsd:documentation>The issuer name of an acceptable provider-issued certificate.  The text of this element is formatted in accordance with the Issuer Name field in RFC-3280.  This element is present only when acceptProviderCerts is true.</xsd:documentation>
+                    </xsd:annotation>
+                    </xsd:attribute>
+                    <xsd:anyAttribute namespace="##other"/>
+                </xsd:complexType>
+            </xsd:element>
+            <xsd:any namespace="##other" minOccurs="0"
+                maxOccurs="unbounded"/>
+        </xsd:sequence>
+        <xsd:attribute name="acceptMfgCerts" type="xsd:boolean"
+            use="optional" default="false">
+            <xsd:annotation>
+                <xsd:documentation>When this boolean is true, IEEE 802.1ar manufacturing certificates are acceptable for mobile device authentication.</xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="acceptProviderCerts" type="xsd:boolean"
+            use="optional" default="true">
+            <xsd:annotation>
+                <xsd:documentation>When this boolean is true, X509v3 certificates issued by providers identified in the providerIssuerName child element(s) are acceptable for mobile device authentication.</xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:anyAttribute namespace="##other"/>
+    </xsd:complexType>
+</xsd:element>
+ */
+
+public class ClientCertInfo implements OSUCommandData {
+    private final boolean mAcceptMfgCerts;
+    private final boolean mAcceptProviderCerts;
+    /*
+     * The issuer name of an acceptable provider-issued certificate.
+     * The text of this element is formatted in accordance with the Issuer Name field in RFC-3280.
+     * This element is present only when acceptProviderCerts is true.
+     */
+    private final List<String> mIssuerNames;
+
+    public ClientCertInfo(XMLNode commandNode) throws OMAException {
+        mAcceptMfgCerts = Boolean.parseBoolean(commandNode.getAttributeValue("acceptMfgCerts"));
+        mAcceptProviderCerts =
+                Boolean.parseBoolean(commandNode.getAttributeValue("acceptProviderCerts"));
+
+        if (mAcceptMfgCerts) {
+            mIssuerNames = new ArrayList<>();
+            for (XMLNode node : commandNode.getChildren()) {
+                if (node.getStrippedTag().equals("providerIssuerName")) {
+                    mIssuerNames.add(node.getAttributeValue("name"));
+                }
+            }
+        } else {
+            mIssuerNames = null;
+        }
+    }
+
+    public boolean doesAcceptMfgCerts() {
+        return mAcceptMfgCerts;
+    }
+
+    public boolean doesAcceptProviderCerts() {
+        return mAcceptProviderCerts;
+    }
+
+    public List<String> getIssuerNames() {
+        return mIssuerNames;
+    }
+
+    @Override
+    public String toString() {
+        return "ClientCertInfo{" +
+                "acceptMfgCerts=" + mAcceptMfgCerts +
+                ", acceptProviderCerts=" + mAcceptProviderCerts +
+                ", issuerNames=" + mIssuerNames +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/commands/GetCertData.java b/packages/Osu/src/com/android/hotspot2/osu/commands/GetCertData.java
new file mode 100644
index 0000000..60a73fb
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/commands/GetCertData.java
@@ -0,0 +1,75 @@
+package com.android.hotspot2.osu.commands;
+
+import android.util.Base64;
+
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.XMLNode;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+/*
+    <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
+        <env:Header/>
+        <env:Body>
+            <spp:sppPostDevDataResponse xmlns:spp="http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp"
+                                        spp:sessionID="A40103ACEDE94C45BA127A41239BD60F" spp:sppStatus="OK"
+                                        spp:sppVersion="1.0">
+                <spp:exec>
+                    <spp:getCertificate enrollmentProtocol="EST">
+                        <spp:enrollmentServerURI>https://osu-server.r2-testbed-rks.wi-fi.org:9446/.well-known/est
+                        </spp:enrollmentServerURI>
+                        <spp:estUserID>a88c4830-aafd-420b-b790-c08f457a0fa3</spp:estUserID>
+                        <spp:estPassword>cnVja3VzMTIzNA==</spp:estPassword>
+                    </spp:getCertificate>
+                </spp:exec>
+            </spp:sppPostDevDataResponse>
+        </env:Body>
+    </env:Envelope>
+ */
+
+public class GetCertData implements OSUCommandData {
+    private final String mProtocol;
+    private final String mServer;
+    private final String mUserName;
+    private final byte[] mPassword;
+
+    public GetCertData(XMLNode commandNode) throws OMAException {
+        mProtocol = commandNode.getAttributeValue("enrollmentProtocol");
+
+        Map<String, String> values = new HashMap<>(3);
+        for (XMLNode node : commandNode.getChildren()) {
+            values.put(node.getStrippedTag(), node.getText());
+        }
+
+        mServer = values.get("enrollmentserveruri");
+        mUserName = values.get("estuserid");
+        mPassword = Base64.decode(values.get("estpassword"), Base64.DEFAULT);
+    }
+
+    public String getProtocol() {
+        return mProtocol;
+    }
+
+    public String getServer() {
+        return mServer;
+    }
+
+    public String getUserName() {
+        return mUserName;
+    }
+
+    public byte[] getPassword() {
+        return mPassword;
+    }
+
+    @Override
+    public String toString() {
+        return "GetCertData " +
+                "protocol='" + mProtocol + '\'' +
+                ", server='" + mServer + '\'' +
+                ", userName='" + mUserName + '\'' +
+                ", password='" + new String(mPassword, StandardCharsets.ISO_8859_1) + '\'';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/commands/MOData.java b/packages/Osu/src/com/android/hotspot2/osu/commands/MOData.java
new file mode 100644
index 0000000..758c0cb
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/commands/MOData.java
@@ -0,0 +1,51 @@
+package com.android.hotspot2.osu.commands;
+
+import android.net.wifi.PasspointManagementObjectDefinition;
+
+import com.android.hotspot2.omadm.MOTree;
+import com.android.hotspot2.omadm.OMAConstants;
+import com.android.hotspot2.omadm.OMAParser;
+import com.android.hotspot2.omadm.XMLNode;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+
+public class MOData implements OSUCommandData {
+    private final String mBaseURI;
+    private final String mURN;
+    private final MOTree mMOTree;
+
+    public MOData(XMLNode root) {
+        mBaseURI = root.getAttributeValue("spp:managementTreeURI");
+        mURN = root.getAttributeValue("spp:moURN");
+        mMOTree = root.getMOTree();
+    }
+
+    public MOData(PasspointManagementObjectDefinition moDef) throws IOException, SAXException {
+        mBaseURI = ""; //moDef.getmBaseUri();
+        mURN = ""; // moDef.getmUrn();
+        /*
+        OMAParser omaParser = new OMAParser();
+        mMOTree = omaParser.parse(moDef.getmMoTree(), OMAConstants.PPS_URN);
+        */
+        mMOTree = null;
+    }
+
+    public String getBaseURI() {
+        return mBaseURI;
+    }
+
+    public String getURN() {
+        return mURN;
+    }
+
+    public MOTree getMOTree() {
+        return mMOTree;
+    }
+
+    @Override
+    public String toString() {
+        return "Base URI: " + mBaseURI + ", MO: " + mMOTree;
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/commands/MOURN.java b/packages/Osu/src/com/android/hotspot2/osu/commands/MOURN.java
new file mode 100644
index 0000000..46394ef
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/commands/MOURN.java
@@ -0,0 +1,33 @@
+package com.android.hotspot2.osu.commands;
+
+/*
+<xsd:element name="uploadMO" maxOccurs="unbounded">
+    <xsd:annotation>
+        <xsd:documentation>Command to mobile to upload the MO named in the moURN attribute to the SPP server.</xsd:documentation>
+    </xsd:annotation>
+    <xsd:complexType>
+        <xsd:attribute ref="moURN"/>
+    </xsd:complexType>
+</xsd:element>
+ */
+
+import com.android.hotspot2.omadm.XMLNode;
+
+public class MOURN implements OSUCommandData {
+    private final String mURN;
+
+    public MOURN(XMLNode root) {
+        mURN = root.getAttributeValue("spp:moURN");
+    }
+
+    public String getURN() {
+        return mURN;
+    }
+
+    @Override
+    public String toString() {
+        return "MOURN{" +
+                "URN='" + mURN + '\'' +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/commands/OSUCommandData.java b/packages/Osu/src/com/android/hotspot2/osu/commands/OSUCommandData.java
new file mode 100644
index 0000000..06f81bf
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/commands/OSUCommandData.java
@@ -0,0 +1,7 @@
+package com.android.hotspot2.osu.commands;
+
+/**
+ * Marker interface
+ */
+public interface OSUCommandData {
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/service/RedirectListener.java b/packages/Osu/src/com/android/hotspot2/osu/service/RedirectListener.java
new file mode 100644
index 0000000..ce26afd
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/service/RedirectListener.java
@@ -0,0 +1,202 @@
+package com.android.hotspot2.osu.service;
+
+import android.util.Log;
+
+import com.android.hotspot2.osu.OSUManager;
+import com.android.hotspot2.osu.OSUOperationStatus;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Random;
+
+public class RedirectListener extends Thread {
+    private static final long ThreadTimeout = 3000L;
+    private static final long UserTimeout = 3600000L;
+    private static final int MaxRetry = 5;
+    private static final String TAG = "OSULSN";
+
+    private static final String HTTPResponseHeader =
+            "HTTP/1.1 304 Not Modified\r\n" +
+                    "Server: dummy\r\n" +
+                    "Keep-Alive: timeout=500, max=5\r\n\r\n";
+
+    private static final String GoodBye =
+            "<html>" +
+                    "<head><title>Goodbye</title></head>" +
+                    "<body>" +
+                    "<h3>Killing browser...</h3>" +
+                    "</body>" +
+                    "</html>\r\n";
+
+    private final OSUManager mOSUManager;
+    private final String mSpName;
+    private final ServerSocket mServerSocket;
+    private final String mPath;
+    private final URL mURL;
+    private final Object mLock = new Object();
+
+    private boolean mListening;
+    private OSUOperationStatus mUserStatus;
+    private volatile boolean mAborted;
+
+    public RedirectListener(OSUManager osuManager, String spName) throws IOException {
+        mOSUManager = osuManager;
+        mSpName = spName;
+        mServerSocket = new ServerSocket(0, 5, InetAddress.getLocalHost());
+        Random rnd = new Random(System.currentTimeMillis());
+        mPath = "rnd" + Integer.toString(Math.abs(rnd.nextInt()), Character.MAX_RADIX);
+        mURL = new URL("http", mServerSocket.getInetAddress().getHostAddress(),
+                mServerSocket.getLocalPort(), mPath);
+
+        Log.d(TAG, "Redirect URL: " + mURL);
+        setName("HS20-Redirect-Listener");
+        setDaemon(true);
+    }
+
+    public void startService() throws IOException {
+        start();
+        synchronized (mLock) {
+            long bail = System.currentTimeMillis() + ThreadTimeout;
+            long remainder = ThreadTimeout;
+            while (remainder > 0 && !mListening) {
+                try {
+                    mLock.wait(remainder);
+                } catch (InterruptedException ie) {
+                    /**/
+                }
+                if (mListening) {
+                    break;
+                }
+                remainder = bail - System.currentTimeMillis();
+            }
+            if (!mListening) {
+                throw new IOException("Failed to start listener");
+            } else {
+                Log.d(TAG, "OSU Redirect listener running");
+            }
+        }
+    }
+
+    public boolean waitForUser() {
+        boolean success;
+        synchronized (mLock) {
+            long bail = System.currentTimeMillis() + UserTimeout;
+            long remainder = UserTimeout;
+            while (remainder > 0 && mUserStatus == null) {
+                try {
+                    mLock.wait(remainder);
+                } catch (InterruptedException ie) {
+                    /**/
+                }
+                if (mUserStatus != null) {
+                    break;
+                }
+                remainder = bail - System.currentTimeMillis();
+            }
+            success = mUserStatus == OSUOperationStatus.UserInputComplete;
+        }
+        abort();
+        return success;
+    }
+
+    public void abort() {
+        try {
+            mAborted = true;
+            mServerSocket.close();
+        } catch (IOException ioe) {
+            /**/
+        }
+    }
+
+    public URL getURL() {
+        return mURL;
+    }
+
+    @Override
+    public void run() {
+        int count = 0;
+        synchronized (mLock) {
+            mListening = true;
+            mLock.notifyAll();
+        }
+
+        boolean terminate = false;
+
+        for (; ; ) {
+            count++;
+            try (Socket instance = mServerSocket.accept()) {
+                try (BufferedReader in = new BufferedReader(
+                        new InputStreamReader(instance.getInputStream(), StandardCharsets.UTF_8))) {
+                    boolean detected = false;
+                    StringBuilder sb = new StringBuilder();
+                    String s;
+                    while ((s = in.readLine()) != null) {
+                        sb.append(s).append('\n');
+                        if (!detected && s.startsWith("GET")) {
+                            String[] segments = s.split(" ");
+                            if (segments.length == 3 &&
+                                    segments[2].startsWith("HTTP/") &&
+                                    segments[1].regionMatches(1, mPath, 0, mPath.length())) {
+                                detected = true;
+                            }
+                        }
+                        if (s.length() == 0) {
+                            break;
+                        }
+                    }
+                    Log.d(TAG, "Redirect receive: " + sb);
+                    String response = null;
+                    if (detected) {
+                        response = status(OSUOperationStatus.UserInputComplete);
+                        if (response == null) {
+                            response = GoodBye;
+                            terminate = true;
+                        }
+                    }
+                    try (BufferedWriter out = new BufferedWriter(
+                            new OutputStreamWriter(instance.getOutputStream(),
+                                    StandardCharsets.UTF_8))) {
+
+                        out.write(HTTPResponseHeader);
+                        if (response != null) {
+                            out.write(response);
+                        }
+                    }
+                    if (terminate) {
+                        break;
+                    } else if (count > MaxRetry) {
+                        status(OSUOperationStatus.UserInputAborted);
+                        break;
+                    }
+                }
+            } catch (IOException ioe) {
+                if (mAborted) {
+                    return;
+                } else if (count > MaxRetry) {
+                    status(OSUOperationStatus.UserInputAborted);
+                    break;
+                }
+            }
+        }
+    }
+
+    private String status(OSUOperationStatus status) {
+        Log.d(TAG, "User input status: " + status);
+        synchronized (mLock) {
+            mUserStatus = status;
+            mLock.notifyAll();
+        }
+        String message = (status == OSUOperationStatus.UserInputAborted) ?
+                "Browser closed" : null;
+
+        return mOSUManager.notifyUser(status, message, mSpName);
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/osu/service/SubscriptionTimer.java b/packages/Osu/src/com/android/hotspot2/osu/service/SubscriptionTimer.java
new file mode 100644
index 0000000..783d14b
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/osu/service/SubscriptionTimer.java
@@ -0,0 +1,108 @@
+package com.android.hotspot2.osu.service;
+
+import android.content.Context;
+import android.os.Handler;
+import android.util.Log;
+
+import com.android.hotspot2.Utils;
+import com.android.hotspot2.WifiNetworkAdapter;
+import com.android.hotspot2.osu.OSUManager;
+import com.android.hotspot2.pps.HomeSP;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SubscriptionTimer implements Runnable {
+    private final Handler mHandler;
+    private final OSUManager mOSUManager;
+    private final WifiNetworkAdapter mWifiNetworkAdapter;
+    private final Map<HomeSP, UpdateAction> mOutstanding = new HashMap<>();
+
+    private static class UpdateAction {
+        private final long mRemediation;
+        private final long mPolicy;
+
+        private UpdateAction(HomeSP homeSP, long now) {
+            mRemediation = homeSP.getSubscriptionUpdate() != null ?
+                    now + homeSP.getSubscriptionUpdate().getInterval() : -1;
+            mPolicy = homeSP.getPolicy() != null ?
+                    now + homeSP.getPolicy().getPolicyUpdate().getInterval() : -1;
+
+            Log.d(OSUManager.TAG, "Timer set for " + homeSP.getFQDN() +
+                    ", remediation: " + Utils.toUTCString(mRemediation) +
+                    ", policy: " + Utils.toUTCString(mPolicy));
+        }
+
+        private boolean remediate(long now) {
+            return mRemediation > 0 && now >= mRemediation;
+        }
+
+        private boolean policyUpdate(long now) {
+            return mPolicy > 0 && now >= mPolicy;
+        }
+
+        private long nextExpiry(long now) {
+            long min = Long.MAX_VALUE;
+            if (mRemediation > now) {
+                min = mRemediation;
+            }
+            if (mPolicy > now) {
+                min = Math.min(min, mPolicy);
+            }
+            return min;
+        }
+    }
+
+    private static final String ACTION_TIMER =
+            "com.android.hotspot2.osu.service.SubscriptionTimer.action.TICK";
+
+    public SubscriptionTimer(OSUManager osuManager,
+                             WifiNetworkAdapter wifiNetworkAdapter, Context context) {
+        mOSUManager = osuManager;
+        mWifiNetworkAdapter = wifiNetworkAdapter;
+        mHandler = new Handler();
+    }
+
+    @Override
+    public void run() {
+        checkUpdates();
+    }
+
+    public void checkUpdates() {
+        mHandler.removeCallbacks(this);
+        long now = System.currentTimeMillis();
+        long next = Long.MAX_VALUE;
+        Collection<HomeSP> homeSPs = mWifiNetworkAdapter.getLoadedSPs();
+        if (homeSPs.isEmpty()) {
+            return;
+        }
+        for (HomeSP homeSP : homeSPs) {
+            UpdateAction updateAction = mOutstanding.get(homeSP);
+            try {
+                if (updateAction == null) {
+                    updateAction = new UpdateAction(homeSP, now);
+                    mOutstanding.put(homeSP, updateAction);
+                } else if (updateAction.remediate(now)) {
+                    mOSUManager.remediate(homeSP, false);
+                    mOutstanding.put(homeSP, new UpdateAction(homeSP, now));
+                } else if (updateAction.policyUpdate(now)) {
+                    mOSUManager.remediate(homeSP, true);
+                    mOutstanding.put(homeSP, new UpdateAction(homeSP, now));
+                }
+                next = Math.min(next, updateAction.nextExpiry(now));
+            } catch (IOException | SAXException e) {
+                Log.d(OSUManager.TAG, "Failed subscription update: " + e.getMessage());
+            }
+        }
+        setAlarm(next);
+    }
+
+    private void setAlarm(long tod) {
+        long delay = tod - System.currentTimeMillis();
+        mHandler.postAtTime(this, Math.max(1, delay));
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/pps/Credential.java b/packages/Osu/src/com/android/hotspot2/pps/Credential.java
new file mode 100644
index 0000000..15f0dcf
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/pps/Credential.java
@@ -0,0 +1,252 @@
+package com.android.hotspot2.pps;
+
+import android.text.TextUtils;
+import android.util.Base64;
+
+import com.android.anqp.eap.EAPMethod;
+import com.android.hotspot2.IMSIParameter;
+import com.android.hotspot2.Utils;
+import com.android.hotspot2.omadm.OMAException;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+public class Credential {
+    public enum CertType {IEEE, x509v3}
+
+    public static final String CertTypeX509 = "x509v3";
+    public static final String CertTypeIEEE = "802.1ar";
+
+    private final long mCtime;
+    private final long mExpTime;
+    private final String mRealm;
+    private final boolean mCheckAAACert;
+
+    private final String mUserName;
+    private final String mPassword;
+    private final boolean mDisregardPassword;
+    private final boolean mMachineManaged;
+    private final String mSTokenApp;
+    private final boolean mShare;
+    private final EAPMethod mEAPMethod;
+
+    private final CertType mCertType;
+    private final byte[] mFingerPrint;
+
+    private final IMSIParameter mImsi;
+
+    public Credential(long ctime, long expTime, String realm, boolean checkAAACert,
+                      EAPMethod eapMethod, String userName, String password,
+                      boolean machineManaged, String stApp, boolean share) {
+        mCtime = ctime;
+        mExpTime = expTime;
+        mRealm = realm;
+        mCheckAAACert = checkAAACert;
+        mEAPMethod = eapMethod;
+        mUserName = userName;
+
+        if (!TextUtils.isEmpty(password)) {
+            byte[] pwOctets = Base64.decode(password, Base64.DEFAULT);
+            mPassword = new String(pwOctets, StandardCharsets.UTF_8);
+        } else {
+            mPassword = null;
+        }
+        mDisregardPassword = false;
+
+        mMachineManaged = machineManaged;
+        mSTokenApp = stApp;
+        mShare = share;
+
+        mCertType = null;
+        mFingerPrint = null;
+
+        mImsi = null;
+    }
+
+    public Credential(long ctime, long expTime, String realm, boolean checkAAACert,
+                      EAPMethod eapMethod, Credential.CertType certType, byte[] fingerPrint) {
+        mCtime = ctime;
+        mExpTime = expTime;
+        mRealm = realm;
+        mCheckAAACert = checkAAACert;
+        mEAPMethod = eapMethod;
+        mCertType = certType;
+        mFingerPrint = fingerPrint;
+
+        mUserName = null;
+        mPassword = null;
+        mDisregardPassword = false;
+        mMachineManaged = false;
+        mSTokenApp = null;
+        mShare = false;
+
+        mImsi = null;
+    }
+
+    public Credential(long ctime, long expTime, String realm, boolean checkAAACert,
+                      EAPMethod eapMethod, IMSIParameter imsi) {
+        mCtime = ctime;
+        mExpTime = expTime;
+        mRealm = realm;
+        mCheckAAACert = checkAAACert;
+        mEAPMethod = eapMethod;
+        mImsi = imsi;
+
+        mCertType = null;
+        mFingerPrint = null;
+
+        mUserName = null;
+        mPassword = null;
+        mDisregardPassword = false;
+        mMachineManaged = false;
+        mSTokenApp = null;
+        mShare = false;
+    }
+
+    public Credential(Credential other, String password) {
+        mCtime = other.mCtime;
+        mExpTime = other.mExpTime;
+        mRealm = other.mRealm;
+        mCheckAAACert = other.mCheckAAACert;
+        mUserName = other.mUserName;
+        mPassword = password;
+        mDisregardPassword = other.mDisregardPassword;
+        mMachineManaged = other.mMachineManaged;
+        mSTokenApp = other.mSTokenApp;
+        mShare = other.mShare;
+        mEAPMethod = other.mEAPMethod;
+        mCertType = other.mCertType;
+        mFingerPrint = other.mFingerPrint;
+        mImsi = other.mImsi;
+    }
+
+    public static CertType mapCertType(String certType) throws OMAException {
+        if (certType.equalsIgnoreCase(CertTypeX509)) {
+            return CertType.x509v3;
+        } else if (certType.equalsIgnoreCase(CertTypeIEEE)) {
+            return CertType.IEEE;
+        } else {
+            throw new OMAException("Invalid cert type: '" + certType + "'");
+        }
+    }
+
+    public EAPMethod getEAPMethod() {
+        return mEAPMethod;
+    }
+
+    public String getRealm() {
+        return mRealm;
+    }
+
+    public IMSIParameter getImsi() {
+        return mImsi;
+    }
+
+    public String getUserName() {
+        return mUserName;
+    }
+
+    public String getPassword() {
+        return mPassword;
+    }
+
+    public boolean hasDisregardPassword() {
+        return mDisregardPassword;
+    }
+
+    public CertType getCertType() {
+        return mCertType;
+    }
+
+    public byte[] getFingerPrint() {
+        return mFingerPrint;
+    }
+
+    public long getCtime() {
+        return mCtime;
+    }
+
+    public long getExpTime() {
+        return mExpTime;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Credential that = (Credential) o;
+
+        if (mCheckAAACert != that.mCheckAAACert) return false;
+        if (mCtime != that.mCtime) return false;
+        if (mExpTime != that.mExpTime) return false;
+        if (mMachineManaged != that.mMachineManaged) return false;
+        if (mShare != that.mShare) return false;
+        if (mCertType != that.mCertType) return false;
+        if (!mEAPMethod.equals(that.mEAPMethod)) return false;
+        if (!Arrays.equals(mFingerPrint, that.mFingerPrint)) return false;
+        if (!safeEquals(mImsi, that.mImsi)) {
+            return false;
+        }
+
+        if (!mDisregardPassword && !safeEquals(mPassword, that.mPassword)) {
+            return false;
+        }
+
+        if (!mRealm.equals(that.mRealm)) return false;
+        if (!safeEquals(mSTokenApp, that.mSTokenApp)) {
+            return false;
+        }
+        if (!safeEquals(mUserName, that.mUserName)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private static boolean safeEquals(Object s1, Object s2) {
+        if (s1 == null) {
+            return s2 == null;
+        } else {
+            return s2 != null && s1.equals(s2);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        int result = (int) (mCtime ^ (mCtime >>> 32));
+        result = 31 * result + (int) (mExpTime ^ (mExpTime >>> 32));
+        result = 31 * result + mRealm.hashCode();
+        result = 31 * result + (mCheckAAACert ? 1 : 0);
+        result = 31 * result + (mUserName != null ? mUserName.hashCode() : 0);
+        result = 31 * result + (mPassword != null ? mPassword.hashCode() : 0);
+        result = 31 * result + (mMachineManaged ? 1 : 0);
+        result = 31 * result + (mSTokenApp != null ? mSTokenApp.hashCode() : 0);
+        result = 31 * result + (mShare ? 1 : 0);
+        result = 31 * result + mEAPMethod.hashCode();
+        result = 31 * result + (mCertType != null ? mCertType.hashCode() : 0);
+        result = 31 * result + (mFingerPrint != null ? Arrays.hashCode(mFingerPrint) : 0);
+        result = 31 * result + (mImsi != null ? mImsi.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "Credential{" +
+                "mCtime=" + Utils.toUTCString(mCtime) +
+                ", mExpTime=" + Utils.toUTCString(mExpTime) +
+                ", mRealm='" + mRealm + '\'' +
+                ", mCheckAAACert=" + mCheckAAACert +
+                ", mUserName='" + mUserName + '\'' +
+                ", mPassword='" + mPassword + '\'' +
+                ", mDisregardPassword=" + mDisregardPassword +
+                ", mMachineManaged=" + mMachineManaged +
+                ", mSTokenApp='" + mSTokenApp + '\'' +
+                ", mShare=" + mShare +
+                ", mEAPMethod=" + mEAPMethod +
+                ", mCertType=" + mCertType +
+                ", mFingerPrint=" + Utils.toHexString(mFingerPrint) +
+                ", mImsi='" + mImsi + '\'' +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/pps/DomainMatcher.java b/packages/Osu/src/com/android/hotspot2/pps/DomainMatcher.java
new file mode 100644
index 0000000..10768d6
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/pps/DomainMatcher.java
@@ -0,0 +1,149 @@
+package com.android.hotspot2.pps;
+
+import com.android.hotspot2.Utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class DomainMatcher {
+
+    public enum Match {None, Primary, Secondary}
+
+    private final Label mRoot;
+
+    private static class Label {
+        private final Map<String, Label> mSubDomains;
+        private final Match mMatch;
+
+        private Label(Match match) {
+            mMatch = match;
+            mSubDomains = match == Match.None ? new HashMap<String, Label>() : null;
+        }
+
+        private void addDomain(Iterator<String> labels, Match match) {
+            String labelName = labels.next();
+            if (labels.hasNext()) {
+                Label subLabel = new Label(Match.None);
+                mSubDomains.put(labelName, subLabel);
+                subLabel.addDomain(labels, match);
+            } else {
+                mSubDomains.put(labelName, new Label(match));
+            }
+        }
+
+        private Label getSubLabel(String labelString) {
+            return mSubDomains.get(labelString);
+        }
+
+        public Match getMatch() {
+            return mMatch;
+        }
+
+        private void toString(StringBuilder sb) {
+            if (mSubDomains != null) {
+                sb.append(".{");
+                for (Map.Entry<String, Label> entry : mSubDomains.entrySet()) {
+                    sb.append(entry.getKey());
+                    entry.getValue().toString(sb);
+                }
+                sb.append('}');
+            } else {
+                sb.append('=').append(mMatch);
+            }
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            toString(sb);
+            return sb.toString();
+        }
+    }
+
+    public DomainMatcher(List<String> primary, List<List<String>> secondary) {
+        mRoot = new Label(Match.None);
+        for (List<String> secondaryLabel : secondary) {
+            mRoot.addDomain(secondaryLabel.iterator(), Match.Secondary);
+        }
+        // Primary overwrites secondary.
+        mRoot.addDomain(primary.iterator(), Match.Primary);
+    }
+
+    /**
+     * Check if domain is either a the same or a sub-domain of any of the domains in the domain tree
+     * in this matcher, i.e. all or or a sub-set of the labels in domain matches a path in the tree.
+     *
+     * @param domain Domain to be checked.
+     * @return None if domain is not a sub-domain, Primary if it matched one of the primary domains
+     * or Secondary if it matched on of the secondary domains.
+     */
+    public Match isSubDomain(List<String> domain) {
+
+        Label label = mRoot;
+        for (String labelString : domain) {
+            label = label.getSubLabel(labelString);
+            if (label == null) {
+                return Match.None;
+            } else if (label.getMatch() != Match.None) {
+                return label.getMatch();
+            }
+        }
+        return Match.None;  // Domain is a super domain
+    }
+
+    public static boolean arg2SubdomainOfArg1(List<String> arg1, List<String> arg2) {
+        if (arg2.size() < arg1.size()) {
+            return false;
+        }
+
+        Iterator<String> l1 = arg1.iterator();
+        Iterator<String> l2 = arg2.iterator();
+
+        while (l1.hasNext()) {
+            if (!l1.next().equals(l2.next())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "Domain matcher " + mRoot;
+    }
+
+    private static final String[] TestDomains = {
+            "garbage.apple.com",
+            "apple.com",
+            "com",
+            "jan.android.google.com.",
+            "jan.android.google.com",
+            "android.google.com",
+            "google.com",
+            "jan.android.google.net.",
+            "jan.android.google.net",
+            "android.google.net",
+            "google.net",
+            "net.",
+            "."
+    };
+
+    public static void main(String[] args) {
+        DomainMatcher dm1 = new DomainMatcher(Utils.splitDomain("android.google.com"),
+                Collections.<List<String>>emptyList());
+        for (String domain : TestDomains) {
+            System.out.println(domain + ": " + dm1.isSubDomain(Utils.splitDomain(domain)));
+        }
+        List<List<String>> secondaries = new ArrayList<List<String>>();
+        secondaries.add(Utils.splitDomain("apple.com"));
+        secondaries.add(Utils.splitDomain("net"));
+        DomainMatcher dm2 = new DomainMatcher(Utils.splitDomain("android.google.com"), secondaries);
+        for (String domain : TestDomains) {
+            System.out.println(domain + ": " + dm2.isSubDomain(Utils.splitDomain(domain)));
+        }
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/pps/HomeSP.java b/packages/Osu/src/com/android/hotspot2/pps/HomeSP.java
new file mode 100644
index 0000000..cfbf9d1
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/pps/HomeSP.java
@@ -0,0 +1,211 @@
+package com.android.hotspot2.pps;
+
+import com.android.hotspot2.Utils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class HomeSP {
+    private final Map<String, Long> mSSIDs;        // SSID, HESSID, [0,N]
+    private final String mFQDN;
+    private final DomainMatcher mDomainMatcher;
+    private final Set<String> mOtherHomePartners;
+    private final HashSet<Long> mRoamingConsortiums;    // [0,N]
+    private final Set<Long> mMatchAnyOIs;           // [0,N]
+    private final List<Long> mMatchAllOIs;          // [0,N]
+
+    private final Credential mCredential;
+
+    // Informational:
+    private final String mFriendlyName;             // [1]
+    private final String mIconURL;                  // [0,1]
+
+    private final Policy mPolicy;
+    private final int mCredentialPriority;
+    private final Map<String, String> mAAATrustRoots;
+    private final UpdateInfo mSubscriptionUpdate;
+    private final SubscriptionParameters mSubscriptionParameters;
+    private final int mUpdateIdentifier;
+
+    @Deprecated
+    public HomeSP(Map<String, Long> ssidMap,
+                   /*@NotNull*/ String fqdn,
+                   /*@NotNull*/ HashSet<Long> roamingConsortiums,
+                   /*@NotNull*/ Set<String> otherHomePartners,
+                   /*@NotNull*/ Set<Long> matchAnyOIs,
+                   /*@NotNull*/ List<Long> matchAllOIs,
+                   String friendlyName,
+                   String iconURL,
+                   Credential credential) {
+
+        mSSIDs = ssidMap;
+        List<List<String>> otherPartners = new ArrayList<>(otherHomePartners.size());
+        for (String otherPartner : otherHomePartners) {
+            otherPartners.add(Utils.splitDomain(otherPartner));
+        }
+        mOtherHomePartners = otherHomePartners;
+        mFQDN = fqdn;
+        mDomainMatcher = new DomainMatcher(Utils.splitDomain(fqdn), otherPartners);
+        mRoamingConsortiums = roamingConsortiums;
+        mMatchAnyOIs = matchAnyOIs;
+        mMatchAllOIs = matchAllOIs;
+        mFriendlyName = friendlyName;
+        mIconURL = iconURL;
+        mCredential = credential;
+
+        mPolicy = null;
+        mCredentialPriority = -1;
+        mAAATrustRoots = null;
+        mSubscriptionUpdate = null;
+        mSubscriptionParameters = null;
+        mUpdateIdentifier = -1;
+    }
+
+    public HomeSP(Map<String, Long> ssidMap,
+                   /*@NotNull*/ String fqdn,
+                   /*@NotNull*/ HashSet<Long> roamingConsortiums,
+                   /*@NotNull*/ Set<String> otherHomePartners,
+                   /*@NotNull*/ Set<Long> matchAnyOIs,
+                   /*@NotNull*/ List<Long> matchAllOIs,
+                   String friendlyName,
+                   String iconURL,
+                   Credential credential,
+
+                   Policy policy,
+                   int credentialPriority,
+                   Map<String, String> AAATrustRoots,
+                   UpdateInfo subscriptionUpdate,
+                   SubscriptionParameters subscriptionParameters,
+                   int updateIdentifier) {
+
+        mSSIDs = ssidMap;
+        List<List<String>> otherPartners = new ArrayList<>(otherHomePartners.size());
+        for (String otherPartner : otherHomePartners) {
+            otherPartners.add(Utils.splitDomain(otherPartner));
+        }
+        mOtherHomePartners = otherHomePartners;
+        mFQDN = fqdn;
+        mDomainMatcher = new DomainMatcher(Utils.splitDomain(fqdn), otherPartners);
+        mRoamingConsortiums = roamingConsortiums;
+        mMatchAnyOIs = matchAnyOIs;
+        mMatchAllOIs = matchAllOIs;
+        mFriendlyName = friendlyName;
+        mIconURL = iconURL;
+        mCredential = credential;
+
+        mPolicy = policy;
+        mCredentialPriority = credentialPriority;
+        mAAATrustRoots = AAATrustRoots;
+        mSubscriptionUpdate = subscriptionUpdate;
+        mSubscriptionParameters = subscriptionParameters;
+        mUpdateIdentifier = updateIdentifier;
+    }
+
+    public int getUpdateIdentifier() {
+        return mUpdateIdentifier;
+    }
+
+    public UpdateInfo getSubscriptionUpdate() {
+        return mSubscriptionUpdate;
+    }
+
+    public Policy getPolicy() {
+        return mPolicy;
+    }
+
+    private String imsiMatch(List<String> imsis, String mccMnc) {
+        if (mCredential.getImsi().matchesMccMnc(mccMnc)) {
+            for (String imsi : imsis) {
+                if (imsi.startsWith(mccMnc)) {
+                    return imsi;
+                }
+            }
+        }
+        return null;
+    }
+
+    public String getFQDN() {
+        return mFQDN;
+    }
+
+    public String getFriendlyName() {
+        return mFriendlyName;
+    }
+
+    public HashSet<Long> getRoamingConsortiums() {
+        return mRoamingConsortiums;
+    }
+
+    public Credential getCredential() {
+        return mCredential;
+    }
+
+    public Map<String, Long> getSSIDs() {
+        return mSSIDs;
+    }
+
+    public Collection<String> getOtherHomePartners() {
+        return mOtherHomePartners;
+    }
+
+    public Set<Long> getMatchAnyOIs() {
+        return mMatchAnyOIs;
+    }
+
+    public List<Long> getMatchAllOIs() {
+        return mMatchAllOIs;
+    }
+
+    public String getIconURL() {
+        return mIconURL;
+    }
+
+    public boolean deepEquals(HomeSP other) {
+        return mFQDN.equals(other.mFQDN) &&
+                mSSIDs.equals(other.mSSIDs) &&
+                mOtherHomePartners.equals(other.mOtherHomePartners) &&
+                mRoamingConsortiums.equals(other.mRoamingConsortiums) &&
+                mMatchAnyOIs.equals(other.mMatchAnyOIs) &&
+                mMatchAllOIs.equals(other.mMatchAllOIs) &&
+                mFriendlyName.equals(other.mFriendlyName) &&
+                Utils.compare(mIconURL, other.mIconURL) == 0 &&
+                mCredential.equals(other.mCredential);
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (this == thatObject) {
+            return true;
+        } else if (thatObject == null || getClass() != thatObject.getClass()) {
+            return false;
+        }
+
+        HomeSP that = (HomeSP) thatObject;
+        return mFQDN.equals(that.mFQDN);
+    }
+
+    @Override
+    public int hashCode() {
+        return mFQDN.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "HomeSP{" +
+                "SSIDs=" + mSSIDs +
+                ", FQDN='" + mFQDN + '\'' +
+                ", DomainMatcher=" + mDomainMatcher +
+                ", RoamingConsortiums={" + Utils.roamingConsortiumsToString(mRoamingConsortiums) +
+                '}' +
+                ", MatchAnyOIs={" + Utils.roamingConsortiumsToString(mMatchAnyOIs) + '}' +
+                ", MatchAllOIs={" + Utils.roamingConsortiumsToString(mMatchAllOIs) + '}' +
+                ", Credential=" + mCredential +
+                ", FriendlyName='" + mFriendlyName + '\'' +
+                ", IconURL='" + mIconURL + '\'' +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/pps/Policy.java b/packages/Osu/src/com/android/hotspot2/pps/Policy.java
new file mode 100644
index 0000000..5180436
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/pps/Policy.java
@@ -0,0 +1,195 @@
+package com.android.hotspot2.pps;
+
+import com.android.hotspot2.Utils;
+import com.android.hotspot2.omadm.MOManager;
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.OMANode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.android.hotspot2.omadm.MOManager.TAG_Country;
+import static com.android.hotspot2.omadm.MOManager.TAG_DLBandwidth;
+import static com.android.hotspot2.omadm.MOManager.TAG_FQDN_Match;
+import static com.android.hotspot2.omadm.MOManager.TAG_IPProtocol;
+import static com.android.hotspot2.omadm.MOManager.TAG_MaximumBSSLoadValue;
+import static com.android.hotspot2.omadm.MOManager.TAG_MinBackhaulThreshold;
+import static com.android.hotspot2.omadm.MOManager.TAG_NetworkType;
+import static com.android.hotspot2.omadm.MOManager.TAG_PolicyUpdate;
+import static com.android.hotspot2.omadm.MOManager.TAG_PortNumber;
+import static com.android.hotspot2.omadm.MOManager.TAG_PreferredRoamingPartnerList;
+import static com.android.hotspot2.omadm.MOManager.TAG_Priority;
+import static com.android.hotspot2.omadm.MOManager.TAG_RequiredProtoPortTuple;
+import static com.android.hotspot2.omadm.MOManager.TAG_SPExclusionList;
+import static com.android.hotspot2.omadm.MOManager.TAG_SSID;
+import static com.android.hotspot2.omadm.MOManager.TAG_ULBandwidth;
+
+public class Policy {
+    private final List<PreferredRoamingPartner> mPreferredRoamingPartners;
+    private final List<MinBackhaul> mMinBackhaulThresholds;
+    private final UpdateInfo mPolicyUpdate;
+    private final List<String> mSPExclusionList;
+    private final Map<Integer, List<Integer>> mRequiredProtos;
+    private final int mMaxBSSLoad;
+
+    public Policy(OMANode node) throws OMAException {
+
+        OMANode rpNode = node.getChild(TAG_PreferredRoamingPartnerList);
+        if (rpNode == null) {
+            mPreferredRoamingPartners = null;
+        } else {
+            mPreferredRoamingPartners = new ArrayList<>(rpNode.getChildren().size());
+            for (OMANode instance : rpNode.getChildren()) {
+                if (instance.isLeaf()) {
+                    throw new OMAException("Not expecting leaf node in " +
+                            TAG_PreferredRoamingPartnerList);
+                }
+                mPreferredRoamingPartners.add(new PreferredRoamingPartner(instance));
+            }
+        }
+
+        OMANode bhtNode = node.getChild(TAG_MinBackhaulThreshold);
+        if (bhtNode == null) {
+            mMinBackhaulThresholds = null;
+        } else {
+            mMinBackhaulThresholds = new ArrayList<>(bhtNode.getChildren().size());
+            for (OMANode instance : bhtNode.getChildren()) {
+                if (instance.isLeaf()) {
+                    throw new OMAException("Not expecting leaf node in " +
+                            TAG_MinBackhaulThreshold);
+                }
+                mMinBackhaulThresholds.add(new MinBackhaul(instance));
+            }
+        }
+
+        mPolicyUpdate = new UpdateInfo(node.getChild(TAG_PolicyUpdate));
+
+        OMANode sxNode = node.getChild(TAG_SPExclusionList);
+        if (sxNode == null) {
+            mSPExclusionList = null;
+        } else {
+            mSPExclusionList = new ArrayList<>(sxNode.getChildren().size());
+            for (OMANode instance : sxNode.getChildren()) {
+                if (instance.isLeaf()) {
+                    throw new OMAException("Not expecting leaf node in " + TAG_SPExclusionList);
+                }
+                mSPExclusionList.add(MOManager.getString(instance, TAG_SSID));
+            }
+        }
+
+        OMANode rptNode = node.getChild(TAG_RequiredProtoPortTuple);
+        if (rptNode == null) {
+            mRequiredProtos = null;
+        } else {
+            mRequiredProtos = new HashMap<>(rptNode.getChildren().size());
+            for (OMANode instance : rptNode.getChildren()) {
+                if (instance.isLeaf()) {
+                    throw new OMAException("Not expecting leaf node in " +
+                            TAG_RequiredProtoPortTuple);
+                }
+                int protocol = (int) MOManager.getLong(instance, TAG_IPProtocol, null);
+                String[] portSegments = MOManager.getString(instance, TAG_PortNumber).split(",");
+                List<Integer> ports = new ArrayList<>(portSegments.length);
+                for (String portSegment : portSegments) {
+                    try {
+                        ports.add(Integer.parseInt(portSegment));
+                    } catch (NumberFormatException nfe) {
+                        throw new OMAException("Port is not a number: " + portSegment);
+                    }
+                }
+                mRequiredProtos.put(protocol, ports);
+            }
+        }
+
+        mMaxBSSLoad = (int) MOManager.getLong(node, TAG_MaximumBSSLoadValue, Long.MAX_VALUE);
+    }
+
+    public List<PreferredRoamingPartner> getPreferredRoamingPartners() {
+        return mPreferredRoamingPartners;
+    }
+
+    public List<MinBackhaul> getMinBackhaulThresholds() {
+        return mMinBackhaulThresholds;
+    }
+
+    public UpdateInfo getPolicyUpdate() {
+        return mPolicyUpdate;
+    }
+
+    public List<String> getSPExclusionList() {
+        return mSPExclusionList;
+    }
+
+    public Map<Integer, List<Integer>> getRequiredProtos() {
+        return mRequiredProtos;
+    }
+
+    public int getMaxBSSLoad() {
+        return mMaxBSSLoad;
+    }
+
+    private static class PreferredRoamingPartner {
+        private final List<String> mDomain;
+        private final Boolean mIncludeSubDomains;
+        private final int mPriority;
+        private final String mCountry;
+
+        private PreferredRoamingPartner(OMANode node)
+                throws OMAException {
+
+            String[] segments = MOManager.getString(node, TAG_FQDN_Match).split(",");
+            if (segments.length != 2) {
+                throw new OMAException("Bad FQDN match string: " + TAG_FQDN_Match);
+            }
+            mDomain = Utils.splitDomain(segments[0]);
+            mIncludeSubDomains = MOManager.getSelection(TAG_FQDN_Match, segments[1]);
+            mPriority = (int) MOManager.getLong(node, TAG_Priority, null);
+            mCountry = MOManager.getString(node, TAG_Country);
+        }
+
+        @Override
+        public String toString() {
+            return "PreferredRoamingPartner{" +
+                    "domain=" + mDomain +
+                    ", includeSubDomains=" + mIncludeSubDomains +
+                    ", priority=" + mPriority +
+                    ", country='" + mCountry + '\'' +
+                    '}';
+        }
+    }
+
+    private static class MinBackhaul {
+        private final Boolean mHome;
+        private final long mDL;
+        private final long mUL;
+
+        private MinBackhaul(OMANode node) throws OMAException {
+            mHome = MOManager.getSelection(node, TAG_NetworkType);
+            mDL = MOManager.getLong(node, TAG_DLBandwidth, Long.MAX_VALUE);
+            mUL = MOManager.getLong(node, TAG_ULBandwidth, Long.MAX_VALUE);
+        }
+
+        @Override
+        public String toString() {
+            return "MinBackhaul{" +
+                    "home=" + mHome +
+                    ", DL=" + mDL +
+                    ", UL=" + mUL +
+                    '}';
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "Policy{" +
+                "preferredRoamingPartners=" + mPreferredRoamingPartners +
+                ", minBackhaulThresholds=" + mMinBackhaulThresholds +
+                ", policyUpdate=" + mPolicyUpdate +
+                ", SPExclusionList=" + mSPExclusionList +
+                ", requiredProtos=" + mRequiredProtos +
+                ", maxBSSLoad=" + mMaxBSSLoad +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/pps/SubscriptionParameters.java b/packages/Osu/src/com/android/hotspot2/pps/SubscriptionParameters.java
new file mode 100644
index 0000000..e073ad7
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/pps/SubscriptionParameters.java
@@ -0,0 +1,81 @@
+package com.android.hotspot2.pps;
+
+import com.android.hotspot2.Utils;
+import com.android.hotspot2.omadm.MOManager;
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.OMANode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.hotspot2.omadm.MOManager.TAG_CreationDate;
+import static com.android.hotspot2.omadm.MOManager.TAG_DataLimit;
+import static com.android.hotspot2.omadm.MOManager.TAG_ExpirationDate;
+import static com.android.hotspot2.omadm.MOManager.TAG_StartDate;
+import static com.android.hotspot2.omadm.MOManager.TAG_TimeLimit;
+import static com.android.hotspot2.omadm.MOManager.TAG_TypeOfSubscription;
+import static com.android.hotspot2.omadm.MOManager.TAG_UsageLimits;
+import static com.android.hotspot2.omadm.MOManager.TAG_UsageTimePeriod;
+
+public class SubscriptionParameters {
+    private final long mCDate;
+    private final long mXDate;
+    private final String mType;
+    private final List<Limit> mLimits;
+
+    public SubscriptionParameters(OMANode node) throws OMAException {
+        mCDate = MOManager.getTime(node.getChild(TAG_CreationDate));
+        mXDate = MOManager.getTime(node.getChild(TAG_ExpirationDate));
+        mType = MOManager.getString(node.getChild(TAG_TypeOfSubscription));
+
+        OMANode ulNode = node.getChild(TAG_UsageLimits);
+        if (ulNode == null) {
+            mLimits = null;
+        } else {
+            mLimits = new ArrayList<>(ulNode.getChildren().size());
+            for (OMANode instance : ulNode.getChildren()) {
+                if (instance.isLeaf()) {
+                    throw new OMAException("Not expecting leaf node in " +
+                            TAG_UsageLimits);
+                }
+                mLimits.add(new Limit(instance));
+            }
+        }
+
+    }
+
+    private static class Limit {
+        private final long mDataLimit;
+        private final long mStartDate;
+        private final long mTimeLimit;
+        private final long mUsageTimePeriod;
+
+        private Limit(OMANode node) throws OMAException {
+            mDataLimit = MOManager.getLong(node, TAG_DataLimit, Long.MAX_VALUE);
+            mStartDate = MOManager.getTime(node.getChild(TAG_StartDate));
+            mTimeLimit = MOManager.getLong(node, TAG_TimeLimit, Long.MAX_VALUE) *
+                    MOManager.IntervalFactor;
+            mUsageTimePeriod = MOManager.getLong(node, TAG_UsageTimePeriod, null);
+        }
+
+        @Override
+        public String toString() {
+            return "Limit{" +
+                    "dataLimit=" + mDataLimit +
+                    ", startDate=" + Utils.toUTCString(mStartDate) +
+                    ", timeLimit=" + mTimeLimit +
+                    ", usageTimePeriod=" + mUsageTimePeriod +
+                    '}';
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "SubscriptionParameters{" +
+                "cDate=" + Utils.toUTCString(mCDate) +
+                ", xDate=" + Utils.toUTCString(mXDate) +
+                ", type='" + mType + '\'' +
+                ", limits=" + mLimits +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/pps/UpdateInfo.java b/packages/Osu/src/com/android/hotspot2/pps/UpdateInfo.java
new file mode 100644
index 0000000..e32f6c3
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/pps/UpdateInfo.java
@@ -0,0 +1,103 @@
+package com.android.hotspot2.pps;
+
+import android.util.Base64;
+
+import com.android.hotspot2.Utils;
+import com.android.hotspot2.omadm.MOManager;
+import com.android.hotspot2.omadm.OMAException;
+import com.android.hotspot2.omadm.OMANode;
+
+import java.nio.charset.StandardCharsets;
+
+import static com.android.hotspot2.omadm.MOManager.TAG_CertSHA256Fingerprint;
+import static com.android.hotspot2.omadm.MOManager.TAG_CertURL;
+import static com.android.hotspot2.omadm.MOManager.TAG_Password;
+import static com.android.hotspot2.omadm.MOManager.TAG_Restriction;
+import static com.android.hotspot2.omadm.MOManager.TAG_TrustRoot;
+import static com.android.hotspot2.omadm.MOManager.TAG_URI;
+import static com.android.hotspot2.omadm.MOManager.TAG_UpdateInterval;
+import static com.android.hotspot2.omadm.MOManager.TAG_UpdateMethod;
+import static com.android.hotspot2.omadm.MOManager.TAG_Username;
+import static com.android.hotspot2.omadm.MOManager.TAG_UsernamePassword;
+
+public class UpdateInfo {
+    public enum UpdateRestriction {HomeSP, RoamingPartner, Unrestricted}
+
+    private final long mInterval;
+    private final boolean mSPPClientInitiated;
+    private final UpdateRestriction mUpdateRestriction;
+    private final String mURI;
+    private final String mUsername;
+    private final String mPassword;
+    private final String mCertURL;
+    private final String mCertFP;
+
+    public UpdateInfo(OMANode policyUpdate) throws OMAException {
+        mInterval = MOManager.getLong(policyUpdate, TAG_UpdateInterval, null) *
+                MOManager.IntervalFactor;
+        mSPPClientInitiated = MOManager.getSelection(policyUpdate, TAG_UpdateMethod);
+        mUpdateRestriction = MOManager.getSelection(policyUpdate, TAG_Restriction);
+        mURI = MOManager.getString(policyUpdate, TAG_URI);
+
+        OMANode unp = policyUpdate.getChild(TAG_UsernamePassword);
+        if (unp != null) {
+            mUsername = MOManager.getString(unp.getChild(TAG_Username));
+            String pw = MOManager.getString(unp.getChild(TAG_Password));
+            mPassword = new String(Base64.decode(pw.getBytes(StandardCharsets.US_ASCII),
+                    Base64.DEFAULT), StandardCharsets.UTF_8);
+        } else {
+            mUsername = null;
+            mPassword = null;
+        }
+
+        OMANode trustRoot = MOManager.getChild(policyUpdate, TAG_TrustRoot);
+        mCertURL = MOManager.getString(trustRoot, TAG_CertURL);
+        mCertFP = MOManager.getString(trustRoot, TAG_CertSHA256Fingerprint);
+    }
+
+    public long getInterval() {
+        return mInterval;
+    }
+
+    public boolean isSPPClientInitiated() {
+        return mSPPClientInitiated;
+    }
+
+    public UpdateRestriction getUpdateRestriction() {
+        return mUpdateRestriction;
+    }
+
+    public String getURI() {
+        return mURI;
+    }
+
+    public String getUsername() {
+        return mUsername;
+    }
+
+    public String getPassword() {
+        return mPassword;
+    }
+
+    public String getCertURL() {
+        return mCertURL;
+    }
+
+    public String getCertFP() {
+        return mCertFP;
+    }
+
+    @Override
+    public String toString() {
+        return "UpdateInfo{" +
+                "interval=" + Utils.toHMS(mInterval) +
+                ", SPPClientInitiated=" + mSPPClientInitiated +
+                ", updateRestriction=" + mUpdateRestriction +
+                ", URI='" + mURI + '\'' +
+                ", username='" + mUsername + '\'' +
+                ", password=" + mPassword +
+                ", certURL='" + mCertURL + '\'' +
+                ", certFP='" + mCertFP + '\'' +
+                '}';
+    }
+}
diff --git a/packages/Osu/src/com/android/hotspot2/utils/HTTPMessage.java b/packages/Osu/src/com/android/hotspot2/utils/HTTPMessage.java
new file mode 100644
index 0000000..c675efd
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/utils/HTTPMessage.java
@@ -0,0 +1,36 @@
+package com.android.hotspot2.utils;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Map;
+
+public interface HTTPMessage {
+    public static final String HTTPVersion = "HTTP/1.1";
+    public static final String AgentHeader = "User-Agent";
+    public static final String AgentName = "Android HS Client";
+    public static final String HostHeader = "Host";
+    public static final String AcceptHeader = "Accept";
+    public static final String LengthHeader = "Content-Length";
+    public static final String ContentTypeHeader = "Content-Type";
+    public static final String ContentLengthHeader = "Content-Length";
+    public static final String ContentEncodingHeader = "Content-Transfer-Encoding";
+    public static final String AuthHeader = "WWW-Authenticate";
+    public static final String AuthorizationHeader = "Authorization";
+
+    public static final String ContentTypeSOAP = "application/soap+xml";
+
+    public static final int RX_BUFFER = 32768;
+    public static final String CRLF = "\r\n";
+    public static final int BODY_SEPARATOR = 0x0d0a0d0a;
+    public static final int BODY_SEPARATOR_LENGTH = 4;
+
+    public enum Method {GET, PUT, POST}
+
+    public Map<String, String> getHeaders();
+
+    public InputStream getPayloadStream();
+
+    public ByteBuffer getPayload();
+
+    public ByteBuffer getBinaryPayload();
+}
diff --git a/packages/Osu/src/com/android/hotspot2/utils/HTTPRequest.java b/packages/Osu/src/com/android/hotspot2/utils/HTTPRequest.java
new file mode 100644
index 0000000..e97c15a
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/utils/HTTPRequest.java
@@ -0,0 +1,307 @@
+package com.android.hotspot2.utils;
+
+import android.util.Base64;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class HTTPRequest implements HTTPMessage {
+    private static final Charset HeaderCharset = StandardCharsets.US_ASCII;
+    private static final int HTTPS_PORT = 443;
+
+    private final String mMethodLine;
+    private final Map<String, String> mHeaderFields;
+    private final byte[] mBody;
+
+    public HTTPRequest(Method method, URL url) {
+        this(null, null, method, url, null, false);
+    }
+
+    public HTTPRequest(String payload, Charset charset, Method method, URL url, String contentType,
+                       boolean base64) {
+        mBody = payload != null ? payload.getBytes(charset) : null;
+
+        mHeaderFields = new LinkedHashMap<>();
+        mHeaderFields.put(AgentHeader, AgentName);
+        if (url.getPort() != HTTPS_PORT) {
+            mHeaderFields.put(HostHeader, url.getHost() + ':' + url.getPort());
+        } else {
+            mHeaderFields.put(HostHeader, url.getHost());
+        }
+        mHeaderFields.put(AcceptHeader, "*/*");
+        if (payload != null) {
+            if (base64) {
+                mHeaderFields.put(ContentTypeHeader, contentType);
+                mHeaderFields.put(ContentEncodingHeader, "base64");
+            } else {
+                mHeaderFields.put(ContentTypeHeader, contentType + "; charset=" +
+                        charset.displayName().toLowerCase());
+            }
+            mHeaderFields.put(ContentLengthHeader, Integer.toString(mBody.length));
+        }
+
+        mMethodLine = method.name() + ' ' + url.getPath() + ' ' + HTTPVersion + CRLF;
+    }
+
+    public void doAuthenticate(HTTPResponse httpResponse, String userName, byte[] password,
+                               URL url, int sequence) throws IOException, GeneralSecurityException {
+        mHeaderFields.put(HTTPMessage.AuthorizationHeader,
+                generateAuthAnswer(httpResponse, userName, password, url, sequence));
+    }
+
+    private static String generateAuthAnswer(HTTPResponse httpResponse, String userName,
+                                             byte[] password, URL url, int sequence)
+            throws IOException, GeneralSecurityException {
+
+        String authRequestLine = httpResponse.getHeader(HTTPMessage.AuthHeader);
+        if (authRequestLine == null) {
+            throw new IOException("Missing auth line");
+        }
+        String[] tokens = authRequestLine.split("[ ,]+");
+        //System.out.println("Tokens: " + Arrays.toString(tokens));
+        if (tokens.length < 3 || !tokens[0].equalsIgnoreCase("digest")) {
+            throw new IOException("Bad " + HTTPMessage.AuthHeader + ": '" + authRequestLine + "'");
+        }
+
+        Map<String, String> itemMap = new HashMap<>();
+        for (int n = 1; n < tokens.length; n++) {
+            String s = tokens[n];
+            int split = s.indexOf('=');
+            if (split < 0) {
+                continue;
+            }
+            itemMap.put(s.substring(0, split).trim().toLowerCase(),
+                    unquote(s.substring(split + 1).trim()));
+        }
+
+        Set<String> qops = splitValue(itemMap.remove("qop"));
+        if (!qops.contains("auth")) {
+            throw new IOException("Unsupported quality of protection value(s): '" + qops + "'");
+        }
+        String algorithm = itemMap.remove("algorithm");
+        if (algorithm != null && !algorithm.equalsIgnoreCase("md5")) {
+            throw new IOException("Unsupported algorithm: '" + algorithm + "'");
+        }
+        String realm = itemMap.remove("realm");
+        String nonceText = itemMap.remove("nonce");
+        if (realm == null || nonceText == null) {
+            throw new IOException("realm and/or nonce missing: '" + authRequestLine + "'");
+        }
+        //System.out.println("Remaining tokens: " + itemMap);
+
+        byte[] cnonce = new byte[16];
+        SecureRandom prng = new SecureRandom();
+        prng.nextBytes(cnonce);
+
+        /*
+         * H(data) = MD5(data)
+         * KD(secret, data) = H(concat(secret, ":", data))
+         *
+         * A1 = unq(username-value) ":" unq(realm-value) ":" passwd
+         * A2 = Method ":" digest-uri-value
+         *
+         * response = KD ( H(A1), unq(nonce-value) ":" nc-value ":" unq(cnonce-value) ":"
+          * unq(qop-value) ":" H(A2) )
+         */
+
+        String nc = String.format("%08d", sequence);
+
+        /*
+         * This bears witness to the ingenuity of the emerging "web generation" and the authors of
+         * RFC-2617: Strings are treated as a sequence of octets in blind ignorance of character
+         * encoding, whereas octets strings apparently aren't "good enough" and expanded to
+         * "hex strings"...
+         * As a wild guess I apply UTF-8 below.
+         */
+        String passwordString = new String(password, StandardCharsets.UTF_8);
+        String cNonceString = bytesToHex(cnonce);
+
+        byte[] a1 = hash(userName, realm, passwordString);
+        byte[] a2 = hash("POST", url.getPath());
+        byte[] response = hash(a1, nonceText, nc, cNonceString, "auth", a2);
+
+        StringBuilder authLine = new StringBuilder();
+        authLine.append("Digest ")
+                .append("username=\"").append(userName).append("\", ")
+                .append("realm=\"").append(realm).append("\", ")
+                .append("nonce=\"").append(nonceText).append("\", ")
+                .append("uri=\"").append(url.getPath()).append("\", ")
+                .append("qop=\"auth\", ")
+                .append("nc=").append(nc).append(", ")
+                .append("cnonce=\"").append(cNonceString).append("\", ")
+                .append("response=\"").append(bytesToHex(response)).append('"');
+        String opaque = itemMap.get("opaque");
+        if (opaque != null) {
+            authLine.append(", \"").append(opaque).append('"');
+        }
+
+        return authLine.toString();
+    }
+
+    private static Set<String> splitValue(String value) {
+        Set<String> result = new HashSet<>();
+        if (value != null) {
+            for (String s : value.split(",")) {
+                result.add(s.trim());
+            }
+        }
+        return result;
+    }
+
+    private static byte[] hash(Object... objects) throws GeneralSecurityException {
+        MessageDigest hash = MessageDigest.getInstance("MD5");
+
+        //System.out.println("<Hash>");
+        boolean first = true;
+        for (Object object : objects) {
+            byte[] octets;
+            if (object.getClass() == String.class) {
+                //System.out.println("+= '" + object + "'");
+                octets = ((String) object).getBytes(StandardCharsets.UTF_8);
+            } else {
+                octets = bytesToHexBytes((byte[]) object);
+                //System.out.println("+= " + new String(octets, StandardCharsets.ISO_8859_1));
+            }
+            if (first) {
+                first = false;
+            } else {
+                hash.update((byte) ':');
+            }
+            hash.update(octets);
+        }
+        //System.out.println("</Hash>");
+        return hash.digest();
+    }
+
+    private static String unquote(String s) {
+        return s.startsWith("\"") ? s.substring(1, s.length() - 1) : s;
+    }
+
+    private static byte[] bytesToHexBytes(byte[] octets) {
+        return bytesToHex(octets).getBytes(StandardCharsets.ISO_8859_1);
+    }
+
+    private static String bytesToHex(byte[] octets) {
+        StringBuilder sb = new StringBuilder(octets.length * 2);
+        for (byte b : octets) {
+            sb.append(String.format("%02x", b & 0xff));
+        }
+        return sb.toString();
+    }
+
+    private byte[] buildHeader() {
+        StringBuilder header = new StringBuilder();
+        header.append(mMethodLine);
+        for (Map.Entry<String, String> entry : mHeaderFields.entrySet()) {
+            header.append(entry.getKey()).append(": ").append(entry.getValue()).append(CRLF);
+        }
+        header.append(CRLF);
+
+        //System.out.println("HTTP Request:");
+        StringBuilder sb2 = new StringBuilder();
+        sb2.append(header);
+        if (mBody != null) {
+            sb2.append(new String(mBody, StandardCharsets.ISO_8859_1));
+        }
+        //System.out.println(sb2);
+        //System.out.println("End HTTP Request.");
+
+        return header.toString().getBytes(HeaderCharset);
+    }
+
+    public void send(OutputStream out) throws IOException {
+        out.write(buildHeader());
+        if (mBody != null) {
+            out.write(mBody);
+        }
+        out.flush();
+    }
+
+    @Override
+    public Map<String, String> getHeaders() {
+        return Collections.unmodifiableMap(mHeaderFields);
+    }
+
+    @Override
+    public InputStream getPayloadStream() {
+        return mBody != null ? new ByteArrayInputStream(mBody) : null;
+    }
+
+    @Override
+    public ByteBuffer getPayload() {
+        return mBody != null ? ByteBuffer.wrap(mBody) : null;
+    }
+
+    @Override
+    public ByteBuffer getBinaryPayload() {
+        byte[] binary = Base64.decode(mBody, Base64.DEFAULT);
+        return ByteBuffer.wrap(binary);
+    }
+
+    public static void main(String[] args) throws GeneralSecurityException {
+        test("Mufasa", "testrealm@host.com", "Circle Of Life", "GET", "/dir/index.html",
+                "dcd98b7102dd2f0e8b11d0f600bfb0c093", "0a4f113b", "00000001", "auth",
+                "6629fae49393a05397450978507c4ef1");
+
+        // WWW-Authenticate: Digest realm="wi-fi.org", qop="auth",
+        // nonce="MTQzMTg1MTIxMzUyNzo0OGFhNGU5ZTg4Y2M4YmFhYzM2MzAwZDg5MGNiYTJlNw=="
+        // Authorization: Digest
+        //  username="1c7e1582-604d-4c00-b411-bb73735cbcb0"
+        //  realm="wi-fi.org"
+        //  nonce="MTQzMTg1MTIxMzUyNzo0OGFhNGU5ZTg4Y2M4YmFhYzM2MzAwZDg5MGNiYTJlNw=="
+        //  uri="/.well-known/est/simpleenroll"
+        //  cnonce="NzA3NDk0"
+        //  nc=00000001
+        //  qop="auth"
+        //  response="2c485d24076452e712b77f4e70776463"
+
+        String nonce = "MTQzMTg1MTIxMzUyNzo0OGFhNGU5ZTg4Y2M4YmFhYzM2MzAwZDg5MGNiYTJlNw==";
+        String cnonce = "NzA3NDk0";
+        test("1c7e1582-604d-4c00-b411-bb73735cbcb0", "wi-fi.org", "ruckus1234", "POST",
+                "/.well-known/est/simpleenroll",
+                /*new String(Base64.getDecoder().decode(nonce), StandardCharsets.ISO_8859_1)*/
+                nonce,
+                /*new String(Base64.getDecoder().decode(cnonce), StandardCharsets.ISO_8859_1)*/
+                cnonce, "00000001", "auth", "2c485d24076452e712b77f4e70776463");
+    }
+
+    private static void test(String user, String realm, String password, String method, String path,
+                             String nonce, String cnonce, String nc, String qop, String expect)
+            throws GeneralSecurityException {
+        byte[] a1 = hash(user, realm, password);
+        System.out.println("HA1: " + bytesToHex(a1));
+        byte[] a2 = hash(method, path);
+        System.out.println("HA2: " + bytesToHex(a2));
+        byte[] response = hash(a1, nonce, nc, cnonce, qop, a2);
+
+        StringBuilder authLine = new StringBuilder();
+        String responseString = bytesToHex(response);
+        authLine.append("Digest ")
+                .append("username=\"").append(user).append("\", ")
+                .append("realm=\"").append(realm).append("\", ")
+                .append("nonce=\"").append(nonce).append("\", ")
+                .append("uri=\"").append(path).append("\", ")
+                .append("qop=\"").append(qop).append("\", ")
+                .append("nc=").append(nc).append(", ")
+                .append("cnonce=\"").append(cnonce).append("\", ")
+                .append("response=\"").append(responseString).append('"');
+
+        System.out.println(authLine);
+        System.out.println("Success: " + responseString.equals(expect));
+    }
+}
\ No newline at end of file
diff --git a/packages/Osu/src/com/android/hotspot2/utils/HTTPResponse.java b/packages/Osu/src/com/android/hotspot2/utils/HTTPResponse.java
new file mode 100644
index 0000000..ba1b1671
--- /dev/null
+++ b/packages/Osu/src/com/android/hotspot2/utils/HTTPResponse.java
@@ -0,0 +1,185 @@
+package com.android.hotspot2.utils;
+
+import android.util.Base64;
+import android.util.Log;
+
+import com.android.hotspot2.osu.OSUManager;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class HTTPResponse implements HTTPMessage {
+    private final int mStatusCode;
+    private final Map<String, String> mHeaders = new LinkedHashMap<>();
+    private final ByteBuffer mBody;
+
+    private static final String csIndicator = "charset=";
+
+    public HTTPResponse(InputStream in) throws IOException {
+        int expected = Integer.MAX_VALUE;
+        int offset = 0;
+        int body = -1;
+        byte[] input = new byte[RX_BUFFER];
+
+        int statusCode = -1;
+        int bodyPattern = 0;
+
+        while (offset < expected) {
+            int amount = in.read(input, offset, input.length - offset);
+            Log.d(OSUManager.TAG, String.format("Reading into %d from %d, amount %d -> %d",
+                    input.length, offset, input.length - offset, amount));
+            if (amount < 0) {
+                throw new EOFException();
+            }
+            //Log.d("ZXZ", "HTTP response: '"
+            // + new String(input, 0, offset + amount, StandardCharsets.ISO_8859_1));
+
+            if (body < 0) {
+                for (int n = offset; n < offset + amount; n++) {
+                    bodyPattern = (bodyPattern << 8) | (input[n] & 0xff);
+                    if (bodyPattern == 0x0d0a0d0a) {
+                        body = n + 1;
+                        statusCode = parseHeader(input, body, mHeaders);
+                        expected = calculateLength(body, mHeaders);
+                        if (expected > input.length) {
+                            input = Arrays.copyOf(input, expected);
+                        }
+                        break;
+                    }
+                }
+            }
+            offset += amount;
+            if (offset < expected && offset == input.length) {
+                input = Arrays.copyOf(input, input.length * 2);
+            }
+        }
+        mStatusCode = statusCode;
+        mBody = ByteBuffer.wrap(input, body, expected - body);
+    }
+
+    private static int parseHeader(byte[] input, int body, Map<String, String> headers)
+            throws IOException {
+        String headerText = new String(input, 0, body - BODY_SEPARATOR_LENGTH,
+                StandardCharsets.ISO_8859_1);
+        //System.out.println("Received header: " + headerText);
+        Iterator<String> headerLines = Arrays.asList(headerText.split(CRLF)).iterator();
+        if (!headerLines.hasNext()) {
+            throw new IOException("Bad HTTP Request");
+        }
+
+        int statusCode;
+        String line0 = headerLines.next();
+        String[] status = line0.split(" ");
+        if (status.length != 3 || !"HTTP/1.1".equals(status[0])) {
+            throw new IOException("Bad HTTP Result: " + line0);
+        }
+        try {
+            statusCode = Integer.parseInt(status[1].trim());
+        } catch (NumberFormatException nfe) {
+            throw new IOException("Bad HTTP header line: '" + line0 + "'");
+        }
+
+        while (headerLines.hasNext()) {
+            String line = headerLines.next();
+            int keyEnd = line.indexOf(':');
+            if (keyEnd < 0) {
+                throw new IOException("Bad header line: '" + line + "'");
+            }
+            String key = line.substring(0, keyEnd).trim();
+            String value = line.substring(keyEnd + 1).trim();
+            headers.put(key, value);
+        }
+        return statusCode;
+    }
+
+    private static int calculateLength(int body, Map<String, String> headers) throws IOException {
+        String contentLength = headers.get(LengthHeader);
+        if (contentLength == null) {
+            throw new IOException("No " + LengthHeader);
+        }
+        try {
+            return body + Integer.parseInt(contentLength);
+        } catch (NumberFormatException nfe) {
+            throw new IOException("Bad " + LengthHeader + ": " + contentLength);
+        }
+    }
+
+    public int getStatusCode() {
+        return mStatusCode;
+    }
+
+    @Override
+    public Map<String, String> getHeaders() {
+        return Collections.unmodifiableMap(mHeaders);
+    }
+
+    public String getHeader(String key) {
+        return mHeaders.get(key);
+    }
+
+    @Override
+    public InputStream getPayloadStream() {
+        return new ByteArrayInputStream(mBody.array(), mBody.position(),
+                mBody.limit() - mBody.position());
+    }
+
+    @Override
+    public ByteBuffer getPayload() {
+        return mBody.duplicate();
+    }
+
+    @Override
+    public ByteBuffer getBinaryPayload() {
+        byte[] data = new byte[mBody.remaining()];
+        mBody.duplicate().get(data);
+        byte[] binary = Base64.decode(data, Base64.DEFAULT);
+        return ByteBuffer.wrap(binary);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Status: ").append(mStatusCode).append(CRLF);
+        for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
+            sb.append(entry.getKey()).append(": ").append(entry.getValue()).append(CRLF);
+        }
+        sb.append(CRLF);
+        Charset charset;
+        try {
+            charset = Charset.forName(getCharset());
+        } catch (IllegalArgumentException iae) {
+            charset = StandardCharsets.ISO_8859_1;
+        }
+        sb.append(new String(mBody.array(), mBody.position(),
+                mBody.limit() - mBody.position(), charset));
+        return sb.toString();
+    }
+
+    public String getCharset() {
+        String contentType = mHeaders.get(ContentTypeHeader);
+        if (contentType == null) {
+            return null;
+        }
+        int csPos = contentType.indexOf(csIndicator);
+        return csPos < 0 ? null : contentType.substring(csPos + csIndicator.length()).trim();
+    }
+
+    private static boolean equals(byte[] b1, int offset, byte[] pattern) {
+        for (int n = 0; n < pattern.length; n++) {
+            if (b1[n + offset] != pattern[n]) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/packages/PrintSpooler/res/drawable/ic_info.xml b/packages/PrintSpooler/res/drawable/ic_info.xml
index 2ecd1c7..d64435b 100644
--- a/packages/PrintSpooler/res/drawable/ic_info.xml
+++ b/packages/PrintSpooler/res/drawable/ic_info.xml
@@ -16,9 +16,9 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="24dp"
         android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportWidth="24"
+        android:viewportHeight="24">
     <path
-        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"
-        android:fillColor="#757575"/>
+        android:fillColor="@android:color/white"
+        android:pathData="M11,17l2,0l0,-6l-2,0l0,6.0zm1,-15.0C6.48,2 2,6.48 2,12.0s4.48,10 10,10 10,-4.48 10,-10.0S17.52,2 12,2.0zm0,18.0c-4.41,0 -8,-3.59 -8,-8.0s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8.0zM11,9l2,0L13,7l-2,0l0,2.0z"/>
 </vector>
\ No newline at end of file
diff --git a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
index e0efbc4..defbf8d 100644
--- a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
+++ b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
@@ -28,7 +28,6 @@
         android:layout_width="32dip"
         android:layout_height="32dip"
         android:layout_gravity="center_vertical"
-        android:layout_marginEnd="8dip"
         android:duplicateParentState="true"
         android:contentDescription="@null"
         android:visibility="invisible">
@@ -38,6 +37,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="vertical"
+        android:layout_marginStart="8dip"
         android:duplicateParentState="true">
 
         <TextView
diff --git a/packages/PrintSpooler/res/layout/printer_list_item.xml b/packages/PrintSpooler/res/layout/printer_list_item.xml
index 50f44c2..1209aa6 100644
--- a/packages/PrintSpooler/res/layout/printer_list_item.xml
+++ b/packages/PrintSpooler/res/layout/printer_list_item.xml
@@ -25,20 +25,22 @@
 
     <ImageView
         android:id="@+id/icon"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
+        android:layout_width="40dip"
+        android:layout_height="40dip"
         android:layout_gravity="center_vertical"
-        android:layout_marginEnd="8dip"
+        android:layout_marginTop="8dip"
+        android:layout_marginBottom="8dip"
         android:duplicateParentState="true"
         android:contentDescription="@null"
         android:visibility="invisible">
     </ImageView>
 
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
+    <RelativeLayout
+        android:layout_width="0dip"
         android:layout_weight="1"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:layout_marginStart="16dip"
         android:duplicateParentState="true">
 
         <TextView
@@ -49,7 +51,10 @@
             android:singleLine="true"
             android:ellipsize="end"
             android:textIsSelectable="false"
-            android:gravity="top|start"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentStart="true"
+            android:fadingEdge="horizontal"
+            android:textAlignment="viewStart"
             android:textColor="?android:attr/textColorPrimary"
             android:duplicateParentState="true">
         </TextView>
@@ -58,24 +63,30 @@
             android:id="@+id/subtitle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_below="@id/title"
+            android:layout_alignParentStart="true"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:singleLine="true"
             android:ellipsize="end"
             android:textIsSelectable="false"
             android:visibility="gone"
             android:textColor="?android:attr/textColorSecondary"
+            android:textAlignment="viewStart"
             android:duplicateParentState="true">
         </TextView>
 
-    </LinearLayout>
+    </RelativeLayout>
 
     <ImageView
         android:id="@+id/more_info"
-        android:layout_width="24dip"
-        android:layout_height="24dip"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
+        android:paddingLeft="16dip"
         android:contentDescription="@string/printer_info_desc"
         android:src="@drawable/ic_info"
+        android:tint="?android:attr/colorControlNormal"
+        android:tintMode="src_in"
         android:visibility="gone">
     </ImageView>
 
diff --git a/packages/PrintSpooler/res/values-ca/arrays.xml b/packages/PrintSpooler/res/values-ca/arrays.xml
deleted file mode 100644
index c1b149c..0000000
--- a/packages/PrintSpooler/res/values-ca/arrays.xml
+++ /dev/null
@@ -1,33 +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>
-
-    <string-array name="pdf_printer_media_sizes" translatable="false">
-        <item>NA_LETTER</item>
-        <item>NA_GOVT_LETTER</item>
-        <item>NA_LEGAL</item>
-        <item>NA_JUNIOR_LEGAL</item>
-        <item>NA_LEDGER</item>
-        <item>NA_TABLOID</item>
-        <item>NA_INDEX_3X5</item>
-        <item>NA_INDEX_4X6</item>
-        <item>NA_INDEX_5X8</item>
-        <item>NA_MONARCH</item>
-        <item>NA_QUARTO</item>
-        <item>NA_FOOLSCAP</item>
-    </string-array>
-
-</resources>
diff --git a/packages/PrintSpooler/res/values-en-rCA/arrays.xml b/packages/PrintSpooler/res/values-en-rCA/arrays.xml
deleted file mode 100644
index d40278c..0000000
--- a/packages/PrintSpooler/res/values-en-rCA/arrays.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<resources>
-
-    <string-array name="pdf_printer_media_sizes" translatable="false">
-        <item>NA_LETTER</item>
-        <item>NA_GOVT_LETTER</item>
-        <item>NA_LEGAL</item>
-        <item>NA_JUNIOR_LEGAL</item>
-        <item>NA_LEDGER</item>
-        <item>NA_TABLOID</item>
-        <item>NA_INDEX_3X5</item>
-        <item>NA_INDEX_4X6</item>
-        <item>NA_INDEX_5X8</item>
-        <item>NA_MONARCH</item>
-        <item>NA_QUARTO</item>
-        <item>NA_FOOLSCAP</item>
-    </string-array>
-
-</resources>
diff --git a/packages/PrintSpooler/res/values-en-rUS/arrays.xml b/packages/PrintSpooler/res/values-en-rUS/arrays.xml
deleted file mode 100644
index d40278c..0000000
--- a/packages/PrintSpooler/res/values-en-rUS/arrays.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<resources>
-
-    <string-array name="pdf_printer_media_sizes" translatable="false">
-        <item>NA_LETTER</item>
-        <item>NA_GOVT_LETTER</item>
-        <item>NA_LEGAL</item>
-        <item>NA_JUNIOR_LEGAL</item>
-        <item>NA_LEDGER</item>
-        <item>NA_TABLOID</item>
-        <item>NA_INDEX_3X5</item>
-        <item>NA_INDEX_4X6</item>
-        <item>NA_INDEX_5X8</item>
-        <item>NA_MONARCH</item>
-        <item>NA_QUARTO</item>
-        <item>NA_FOOLSCAP</item>
-    </string-array>
-
-</resources>
diff --git a/packages/PrintSpooler/res/values-es-rUS/arrays.xml b/packages/PrintSpooler/res/values-es-rUS/arrays.xml
deleted file mode 100644
index c1b149c..0000000
--- a/packages/PrintSpooler/res/values-es-rUS/arrays.xml
+++ /dev/null
@@ -1,33 +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>
-
-    <string-array name="pdf_printer_media_sizes" translatable="false">
-        <item>NA_LETTER</item>
-        <item>NA_GOVT_LETTER</item>
-        <item>NA_LEGAL</item>
-        <item>NA_JUNIOR_LEGAL</item>
-        <item>NA_LEDGER</item>
-        <item>NA_TABLOID</item>
-        <item>NA_INDEX_3X5</item>
-        <item>NA_INDEX_4X6</item>
-        <item>NA_INDEX_5X8</item>
-        <item>NA_MONARCH</item>
-        <item>NA_QUARTO</item>
-        <item>NA_FOOLSCAP</item>
-    </string-array>
-
-</resources>
diff --git a/packages/PrintSpooler/res/values-ja/arrays.xml b/packages/PrintSpooler/res/values-ja/arrays.xml
deleted file mode 100644
index 3187cbe..0000000
--- a/packages/PrintSpooler/res/values-ja/arrays.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<resources>
-
-    <string-array name="pdf_printer_media_sizes" translatable="false">
-        <item>JIS_B10</item>
-        <item>JIS_B9</item>
-        <item>JIS_B8</item>
-        <item>JIS_B7</item>
-        <item>JIS_B6</item>
-        <item>JIS_B5</item>
-        <item>JIS_B4</item>
-        <item>JIS_B3</item>
-        <item>JIS_B2</item>
-        <item>JIS_B1</item>
-        <item>JIS_B0</item>
-        <item>JIS_EXEC</item>
-        <item>JPN_CHOU4</item>
-        <item>JPN_CHOU3</item>
-        <item>JPN_CHOU2</item>
-        <item>JPN_HAGAKI</item>
-        <item>JPN_OUFUKU</item>
-        <item>JPN_KAHU</item>
-        <item>JPN_KAKU2</item>
-        <item>JPN_YOU4</item>
-    </string-array>
-
-</resources>
diff --git a/packages/PrintSpooler/res/values/arrays.xml b/packages/PrintSpooler/res/values/arrays.xml
index afe3c71..8658be4 100644
--- a/packages/PrintSpooler/res/values/arrays.xml
+++ b/packages/PrintSpooler/res/values/arrays.xml
@@ -121,38 +121,4 @@
         <!-- Everything else is ISO -->
     </string-array>
 
-    <string-array name="pdf_printer_media_sizes" translatable="false">
-        <item>ISO_A0</item>
-        <item>ISO_A1</item>
-        <item>ISO_A2</item>
-        <item>ISO_A3</item>
-        <item>ISO_A4</item>
-        <item>ISO_A5</item>
-        <item>ISO_A6</item>
-        <item>ISO_A7</item>
-        <item>ISO_A8</item>
-        <item>ISO_A9</item>
-        <item>ISO_A10</item>
-        <item>ISO_B1</item>
-        <item>ISO_B2</item>
-        <item>ISO_B3</item>
-        <item>ISO_B4</item>
-        <item>ISO_B5</item>
-        <item>ISO_B6</item>
-        <item>ISO_B7</item>
-        <item>ISO_B8</item>
-        <item>ISO_B9</item>
-        <item>ISO_B10</item>
-        <item>ISO_C1</item>
-        <item>ISO_C2</item>
-        <item>ISO_C3</item>
-        <item>ISO_C4</item>
-        <item>ISO_C5</item>
-        <item>ISO_C6</item>
-        <item>ISO_C7</item>
-        <item>ISO_C8</item>
-        <item>ISO_C9</item>
-        <item>ISO_C10</item>
-    </string-array>
-
 </resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 743df99..d0cf635 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -61,7 +61,9 @@
 import android.text.TextUtils.SimpleStringSplitter;
 import android.text.TextWatcher;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
@@ -167,6 +169,8 @@
 
     public static final PageRange[] ALL_PAGES_ARRAY = new PageRange[]{PageRange.ALL_PAGES};
 
+    private boolean mIsOptionsUiBound = false;
+
     private final PrinterAvailabilityDetector mPrinterAvailabilityDetector =
             new PrinterAvailabilityDetector();
 
@@ -261,7 +265,14 @@
                 new Runnable() {
             @Override
             public void run() {
-                onConnectedToPrintSpooler(adapter);
+                if (isFinishing()) {
+                    // onPause might have not been able to cancel the job, see PrintActivity#onPause
+                    // To be sure, cancel the job again. Double canceling does no harm.
+                    mSpoolerProvider.getSpooler().setPrintJobState(mPrintJob.getId(),
+                            PrintJobInfo.STATE_CANCELED, null);
+                } else {
+                    onConnectedToPrintSpooler(adapter);
+                }
             }
         });
     }
@@ -337,7 +348,7 @@
     @Override
     public void onStart() {
         super.onStart();
-        if (mState != STATE_INITIALIZING && mCurrentPrinter != null) {
+        if (mPrinterRegistry != null && mCurrentPrinter != null) {
             mPrinterRegistry.setTrackedPrinter(mCurrentPrinter.getId());
         }
         MetricsLogger.count(this, "print_preview", 1);
@@ -349,7 +360,9 @@
 
         if (mState == STATE_INITIALIZING) {
             if (isFinishing()) {
-                spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_CANCELED, null);
+                if (spooler != null) {
+                    spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_CANCELED, null);
+                }
             }
             super.onPause();
             return;
@@ -384,7 +397,10 @@
     @Override
     protected void onStop() {
         mPrinterAvailabilityDetector.cancel();
-        mPrinterRegistry.setTrackedPrinter(null);
+
+        if (mPrinterRegistry != null) {
+            mPrinterRegistry.setTrackedPrinter(null);
+        }
 
         super.onStop();
     }
@@ -1214,6 +1230,9 @@
         mPrintButton = (ImageView) findViewById(R.id.print_button);
         mPrintButton.setOnClickListener(clickListener);
 
+        // The UI is now initialized
+        mIsOptionsUiBound = true;
+
         // Special prompt instead of destination spinner for the first time the user printed
         if (!hasUserEverPrinted()) {
             mShowDestinationPrompt = true;
@@ -1390,6 +1409,10 @@
     }
 
     void updateOptionsUi() {
+        if (!mIsOptionsUiBound) {
+            return;
+        }
+
         // Always update the summary.
         updateSummary();
 
@@ -1725,6 +1748,10 @@
     }
 
     private void updateSummary() {
+        if (!mIsOptionsUiBound) {
+            return;
+        }
+
         CharSequence copiesText = null;
         CharSequence mediaSizeText = null;
 
@@ -1912,9 +1939,12 @@
     }
 
     private void doFinish() {
+        if (mPrinterRegistry != null) {
+            mPrinterRegistry.setTrackedPrinter(null);
+        }
+
         if (mState != STATE_INITIALIZING) {
             mProgressMessageController.cancel();
-            mPrinterRegistry.setTrackedPrinter(null);
             mSpoolerProvider.destroy();
             mPrintedDocument.finish();
             mPrintedDocument.destroy();
@@ -2233,10 +2263,17 @@
 
             ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
             if (icon != null) {
-                iconView.setImageDrawable(icon);
                 iconView.setVisibility(View.VISIBLE);
+                if (!isEnabled(position)) {
+                    icon.mutate();
+
+                    TypedValue value = new TypedValue();
+                    getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true);
+                    icon.setAlpha((int)(value.getFloat() * 255));
+                }
+                iconView.setImageDrawable(icon);
             } else {
-                iconView.setVisibility(View.INVISIBLE);
+                iconView.setVisibility(View.GONE);
             }
 
             return convertView;
@@ -2334,6 +2371,7 @@
         }
 
         private PrinterInfo createFakePdfPrinter() {
+            ArraySet<MediaSize> allMediaSizes = MediaSize.getAllPredefinedSizes();
             MediaSize defaultMediaSize = MediaSizeUtils.getDefault(PrintActivity.this);
 
             PrinterId printerId = new PrinterId(getComponentName(), "PDF printer");
@@ -2341,11 +2379,9 @@
             PrinterCapabilitiesInfo.Builder builder =
                     new PrinterCapabilitiesInfo.Builder(printerId);
 
-            String[] mediaSizeIds = getResources().getStringArray(R.array.pdf_printer_media_sizes);
-            final int mediaSizeIdCount = mediaSizeIds.length;
-            for (int i = 0; i < mediaSizeIdCount; i++) {
-                String id = mediaSizeIds[i];
-                MediaSize mediaSize = MediaSize.getStandardMediaSizeById(id);
+            final int mediaSizeCount = allMediaSizes.size();
+            for (int i = 0; i < mediaSizeCount; i++) {
+                MediaSize mediaSize = allMediaSizes.valueAt(i);
                 builder.addMediaSize(mediaSize, mediaSize.equals(defaultMediaSize));
             }
 
@@ -2423,6 +2459,7 @@
             }
 
             updateOptionsUi();
+            updateSummary();
         }
 
         private boolean capabilitiesChanged(PrinterCapabilitiesInfo oldCapabilities,
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index 1aec253..4f7624a 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -37,6 +37,7 @@
 import android.database.ContentObserver;
 import android.database.DataSetObserver;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -47,6 +48,7 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.Menu;
@@ -544,7 +546,10 @@
                         final int printerCount = mPrinters.size();
                         for (int i = 0; i < printerCount; i++) {
                             PrinterInfo printer = mPrinters.get(i);
-                            if (printer.getName().toLowerCase().contains(constraintLowerCase)) {
+                            String description = printer.getDescription();
+                            if (printer.getName().toLowerCase().contains(constraintLowerCase)
+                                    || description != null && description.toLowerCase()
+                                            .contains(constraintLowerCase)) {
                                 filteredPrinters.add(printer);
                             }
                         }
@@ -663,18 +668,28 @@
                     @Override
                     public void onClick(View v) {
                         try {
-                            startIntentSender(printer.getInfoIntent().getIntentSender(), null, 0, 0, 0);
+                            startIntentSender(printer.getInfoIntent().getIntentSender(), null, 0, 0,
+                                    0);
                         } catch (SendIntentException e) {
                             Log.e(LOG_TAG, "Could not execute pending info intent: %s", e);
                         }
                     }
                 });
+            } else {
+                moreInfoView.setVisibility(View.GONE);
             }
 
             ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
             if (icon != null) {
-                iconView.setImageDrawable(icon);
                 iconView.setVisibility(View.VISIBLE);
+                if (!isActionable(position)) {
+                    icon.mutate();
+
+                    TypedValue value = new TypedValue();
+                    getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true);
+                    icon.setAlpha((int)(value.getFloat() * 255));
+                }
+                iconView.setImageDrawable(icon);
             } else {
                 iconView.setVisibility(View.GONE);
             }
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index e7ae858..a7bed29 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Gedeaktiveer deur administrateur"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index beac0a1..ed91fbe 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"ባትሪ እየሞላ አይደለም"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ኃይል  እየሞላ አይደለም"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ሙሉነው"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"በአስተዳዳሪ የተሰናከለ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 2386cb6..11b4012 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"لا يتم الشحن"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"لا يتم الشحن"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ممتلئة"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"تم التعطيل بواسطة المشرف"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index 273ea30..25bf1d9 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administrator tərəfindən deaktiv edildi"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 4f95052..ba3e4d2 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogućio je administrator"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 74c58a5..e7aee37 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Не се зарежда"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се зарежда"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Пълна"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Деактивирано от администратора"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 9e42f71..b82e0aa 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"চার্জ হচ্ছে না"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"চার্জ হচ্ছে না"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"পূর্ণ"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"প্রশাসক দ্বারা অক্ষমিত"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
new file mode 100644
index 0000000..8aae5bb
--- /dev/null
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -0,0 +1,391 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2015 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for wifi_fail_to_scan (1265540342578081461) -->
+    <skip />
+    <!-- no translation found for wifi_security_none (7985461072596594400) -->
+    <skip />
+    <!-- no translation found for wifi_remembered (4955746899347821096) -->
+    <skip />
+    <!-- no translation found for wifi_disabled_generic (4259794910584943386) -->
+    <skip />
+    <!-- no translation found for wifi_disabled_network_failure (2364951338436007124) -->
+    <skip />
+    <!-- no translation found for wifi_disabled_wifi_failure (3081668066612876581) -->
+    <skip />
+    <!-- no translation found for wifi_disabled_password_failure (8659805351763133575) -->
+    <skip />
+    <!-- no translation found for wifi_not_in_range (1136191511238508967) -->
+    <skip />
+    <!-- no translation found for wifi_no_internet (9151470775868728896) -->
+    <skip />
+    <!-- no translation found for saved_network (4352716707126620811) -->
+    <skip />
+    <!-- no translation found for connected_via_wfa (3805736726317410714) -->
+    <skip />
+    <!-- no translation found for connected_via_passpoint (2826205693803088747) -->
+    <skip />
+    <!-- no translation found for available_via_passpoint (1617440946846329613) -->
+    <skip />
+    <!-- no translation found for wifi_connected_no_internet (3149853966840874992) -->
+    <skip />
+    <!-- no translation found for bluetooth_disconnected (6557104142667339895) -->
+    <skip />
+    <!-- no translation found for bluetooth_disconnecting (8913264760027764974) -->
+    <skip />
+    <!-- no translation found for bluetooth_connecting (8555009514614320497) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected (6038755206916626419) -->
+    <skip />
+    <!-- no translation found for bluetooth_pairing (1426882272690346242) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset (2866994875046035609) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_a2dp (4576188601581440337) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_map (6504436917057479986) -->
+    <skip />
+    <!-- no translation found for bluetooth_connected_no_headset_no_a2dp (9195757766755553810) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_a2dp (2031475486179830674) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_headset (8658779596261212609) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_opp (9168139293654233697) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_hid (3680729023366986480) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_pan (3391606497945147673) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_pbap (5372051906968576809) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_pbap_summary (6605229608108852198) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_pan_nap (8429049285027482959) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_map (5465271250454324383) -->
+    <skip />
+    <!-- no translation found for bluetooth_profile_sap (5764222021851283125) -->
+    <skip />
+    <!-- no translation found for bluetooth_a2dp_profile_summary_connected (963376081347721598) -->
+    <skip />
+    <!-- no translation found for bluetooth_headset_profile_summary_connected (7661070206715520671) -->
+    <skip />
+    <!-- no translation found for bluetooth_opp_profile_summary_connected (2611913495968309066) -->
+    <skip />
+    <!-- no translation found for bluetooth_map_profile_summary_connected (8191407438851351713) -->
+    <skip />
+    <!-- no translation found for bluetooth_sap_profile_summary_connected (8561765057453083838) -->
+    <skip />
+    <!-- no translation found for bluetooth_opp_profile_summary_not_connected (1267091356089086285) -->
+    <skip />
+    <!-- no translation found for bluetooth_hid_profile_summary_connected (3381760054215168689) -->
+    <skip />
+    <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"Pov. na ur. za pris. int."</string>
+    <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"Dij. lok. int. veze s ur."</string>
+    <!-- no translation found for bluetooth_pan_profile_summary_use_for (5664884523822068653) -->
+    <skip />
+    <!-- no translation found for bluetooth_map_profile_summary_use_for (5154200119919927434) -->
+    <skip />
+    <!-- no translation found for bluetooth_sap_profile_summary_use_for (7085362712786907993) -->
+    <skip />
+    <!-- no translation found for bluetooth_a2dp_profile_summary_use_for (4630849022250168427) -->
+    <skip />
+    <!-- no translation found for bluetooth_headset_profile_summary_use_for (8705753622443862627) -->
+    <skip />
+    <!-- no translation found for bluetooth_opp_profile_summary_use_for (1255674547144769756) -->
+    <skip />
+    <!-- no translation found for bluetooth_hid_profile_summary_use_for (232727040453645139) -->
+    <skip />
+    <!-- no translation found for bluetooth_pairing_accept (6163520056536604875) -->
+    <skip />
+    <!-- no translation found for bluetooth_pairing_accept_all_caps (6061699265220789149) -->
+    <skip />
+    <!-- no translation found for bluetooth_pairing_decline (4185420413578948140) -->
+    <skip />
+    <!-- no translation found for bluetooth_pairing_will_share_phonebook (4982239145676394429) -->
+    <skip />
+    <!-- no translation found for bluetooth_pairing_error_message (3748157733635947087) -->
+    <skip />
+    <!-- no translation found for bluetooth_pairing_pin_error_message (8337234855188925274) -->
+    <skip />
+    <!-- no translation found for bluetooth_pairing_device_down_error_message (7870998403045801381) -->
+    <skip />
+    <!-- no translation found for bluetooth_pairing_rejected_error_message (1648157108520832454) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_off (1166761729660614716) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wifi (8834610636137374508) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_one_bar (4869376278894301820) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_two_bars (3569851234710034416) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_three_bars (8134185644861380311) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_signal_full (7061045677694702) -->
+    <skip />
+    <string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
+    <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string>
+    <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string>
+    <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB dijeljenje veze"</string>
+    <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prenosna pristupna tačka"</string>
+    <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Dijeljenje Bluetooth veze"</string>
+    <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Dijeljenje veze"</string>
+    <string name="tether_settings_title_all" msgid="8356136101061143841">"Dijeljenje internetske veze i prenosna pristupna tačka"</string>
+    <string name="managed_user_title" msgid="8101244883654409696">"Profil za Work"</string>
+    <string name="user_guest" msgid="8475274842845401871">"Gost"</string>
+    <string name="unknown" msgid="1592123443519355854">"Nepoznato"</string>
+    <string name="running_process_item_user_label" msgid="3129887865552025943">"Korisnik: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
+    <string name="launch_defaults_some" msgid="313159469856372621">"Neke zadane vrijednosti su postavljene"</string>
+    <string name="launch_defaults_none" msgid="4241129108140034876">"Nema postavljenih zadanih vrijednosti"</string>
+    <string name="tts_settings" msgid="8186971894801348327">"Postavke za pretvaranje teksta u govor"</string>
+    <string name="tts_settings_title" msgid="1237820681016639683">"Izlaz za pretvaranje teksta u govor"</string>
+    <string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
+    <string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
+    <string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
+    <string name="tts_lang_use_system" msgid="2679252467416513208">"Koristi sistemski jezik"</string>
+    <string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije izabran"</string>
+    <string name="tts_default_lang_summary" msgid="5219362163902707785">"Postavlja glas za dati jezik za izgovoreni tekst"</string>
+    <string name="tts_play_example_title" msgid="7094780383253097230">"Poslušajte primjer"</string>
+    <string name="tts_play_example_summary" msgid="8029071615047894486">"Reproduciraj kratku demonstraciju sintetiziranja govora"</string>
+    <string name="tts_install_data_title" msgid="4264378440508149986">"Instaliraj glasovne podatke"</string>
+    <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalirajte glasovne podatke potrebne za sintetiziranje govora"</string>
+    <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ovaj program za sintetiziranje govora može biti u mogućnosti da prikuplja sav tekst koji se izgovara, uključujući lične podatke kao što su lozinke i brojevi kreditnih kartica. Potiče od aplikacije <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Da li želite koristiti ovaj program za sintetiziranje govora?"</string>
+    <string name="tts_engine_network_required" msgid="1190837151485314743">"Ovaj jezik zahtijeva mrežnu vezu radi za izlaz tekst-u-govor."</string>
+    <string name="tts_default_sample_string" msgid="4040835213373086322">"Ovo je primjer sinteze govora"</string>
+    <string name="tts_status_title" msgid="7268566550242584413">"Zadani status jezika"</string>
+    <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> je u potpunosti podržan"</string>
+    <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> zahtjeva mrežnu vezu"</string>
+    <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> nije podržan"</string>
+    <!-- no translation found for tts_status_checking (5339150797940483592) -->
+    <skip />
+    <string name="tts_engine_settings_title" msgid="3499112142425680334">"Postavke za <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+    <string name="tts_engine_settings_button" msgid="1030512042040722285">"Pokreni postavke programa"</string>
+    <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Željeni program"</string>
+    <string name="tts_general_section_title" msgid="4402572014604490502">"Opće"</string>
+    <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+    <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+    <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+    <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+    <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+    <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+    <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+    <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+    <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
+    <string name="choose_profile" msgid="8229363046053568878">"Odaberite profil"</string>
+    <string name="category_personal" msgid="1299663247844969448">"Lično"</string>
+    <string name="category_work" msgid="8699184680584175622">"Posao"</string>
+    <string name="development_settings_title" msgid="215179176067683667">"Opcije za programere"</string>
+    <!-- no translation found for development_settings_enable (542530994778109538) -->
+    <skip />
+    <string name="development_settings_summary" msgid="1815795401632854041">"Postavi opcije za razvoj aplikacija"</string>
+    <string name="development_settings_not_available" msgid="4308569041701535607">"Opcije za programere nisu dostupne za ovog korisnika"</string>
+    <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN postavke nisu dostupne za ovog korisnika"</string>
+    <string name="tethering_settings_not_available" msgid="6765770438438291012">"Postavke za privezivanje nisu dostupne za ovog korisnika"</string>
+    <string name="apn_settings_not_available" msgid="7873729032165324000">"Postavke za naziv pristupne tačke nisu dostupne za ovog korisnika"</string>
+    <string name="enable_adb" msgid="7982306934419797485">"USB otklanjanje grešaka"</string>
+    <string name="enable_adb_summary" msgid="4881186971746056635">"Način rada za uklanjanje grešaka kada je povezan USB"</string>
+    <string name="clear_adb_keys" msgid="4038889221503122743">"Ukini odobrenja otklanjanja grešaka USB-om"</string>
+    <string name="bugreport_in_power" msgid="7923901846375587241">"Prečica za izvještaj o greškama"</string>
+    <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Prikaži tipku za prijavu grešaka u izborniku za potrošnju energije"</string>
+    <string name="keep_screen_on" msgid="1146389631208760344">"Ostani aktivan"</string>
+    <string name="keep_screen_on_summary" msgid="2173114350754293009">"Ekran neće prelaziti u stanje mirovanja tokom punjenja"</string>
+    <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Omogući Bluetooth HCI snoop zapis"</string>
+    <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"Smjesti sve Bluetooth HCI pakete u datoteku"</string>
+    <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM otključavanje"</string>
+    <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Dozvoli otključavanje bootloadera"</string>
+    <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"Želite li dozvoliti OEM otključavanje?"</string>
+    <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"UPOZORENJE: Funkcije zaštite ovog uređaja neće funkcionisati dok je ova postavka uključena."</string>
+    <string name="mock_location_app" msgid="7966220972812881854">"Odaberite aplikaciju za lažne lokacije"</string>
+    <string name="mock_location_app_not_set" msgid="809543285495344223">"Aplikacija za lažnu lokaciju nije postavljena"</string>
+    <string name="mock_location_app_set" msgid="8966420655295102685">"Aplikacija za lažne lokacije: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
+    <string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string>
+    <string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogućiti Wi-Fi Verbose zapisivanje"</string>
+    <string name="wifi_aggressive_handover" msgid="9194078645887480917">"Agresivni Wi-Fi u mobilnoj primopredaji"</string>
+    <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopustiti Wi-Fi lutajuće skeniranje"</string>
+    <string name="legacy_dhcp_client" msgid="694426978909127287">"Koristi zastareli DHCP klijent"</string>
+    <string name="mobile_data_always_on" msgid="7745605759775320362">"Mobilni podaci uvijek aktivni"</string>
+    <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži opcije za certifikaciju Bežičnog prikaza"</string>
+    <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećajte nivo Wi-Fi zapisivanja, pokazati po SSID RSSI Wi-Fi Picker"</string>
+    <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kada je omogućeno, Wi-Fi će biti agresivniji u predavanju podatkovne veze mobilnoj, kada je Wi-Fi signal slab"</string>
+    <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/Zabrani Wi-Fi lutajuće skeniranje na osnovu količine podatkovnog prometa prisutnog na sučelju"</string>
+    <string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera za zapisnik"</string>
+    <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izaberite veličine za Logger prema međumemoriji evidencije"</string>
+    <string name="select_usb_configuration_title" msgid="2649938511506971843">"Odaberite USB konfiguraciju"</string>
+    <string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Odaberite konfiguraciju USB-a"</string>
+    <string name="allow_mock_location" msgid="2787962564578664888">"Dozvoli lažne lokacije"</string>
+    <string name="allow_mock_location_summary" msgid="317615105156345626">"Dozvoli lažne lokacije"</string>
+    <string name="debug_view_attributes" msgid="6485448367803310384">"Omogući pregled atributa prikaza"</string>
+    <string name="legacy_dhcp_client_summary" msgid="163383566317652040">"Koristi DHCP klijent iz Lollipopa umjesto novog Android DHCP klijenta."</string>
+    <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Uvijek drži mobilne podatke aktivnim, čak i kada je Wi-Fi je aktivan (za brzo prebacivanje između mreža)."</string>
+    <string name="adb_warning_title" msgid="6234463310896563253">"Omogućiti USB otklanjanje grešaka?"</string>
+    <string name="adb_warning_message" msgid="7316799925425402244">"USB otklanjanje grešaka je namijenjeno samo u svrhe razvoja aplikacija. Koristite ga za kopiranje podataka između računara i uređaja, instaliranje aplikacija na uređaj bez obavještenja te čitanje podataka iz dnevnika rada."</string>
+    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Opozvati pristup otklanjanju grešaka USB-om za sve računare koje ste prethodno ovlastili?"</string>
+    <string name="dev_settings_warning_title" msgid="7244607768088540165">"Dopustiti postavke za razvoj?"</string>
+    <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ove postavke su namijenjene samo za svrhe razvoja. Mogu izazvati pogrešno ponašanje uređaja i aplikacija na njemu."</string>
+    <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifikuj aplikacije putem USB-a"</string>
+    <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Provjerava da li se u aplikacijama instaliranim putem ADB-a/ADT-a javlja zlonamerno ponašanje."</string>
+    <string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string>
+    <string name="enable_terminal_summary" msgid="67667852659359206">"Omogući terminalnu aplik. koja nudi pristup lok. kom. okruženju"</string>
+    <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP provjeravanje"</string>
+    <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Pos. ponaš. kod HDCP pr."</string>
+    <string name="debug_debugging_category" msgid="6781250159513471316">"Otklanjanje grešaka"</string>
+    <string name="debug_app" msgid="8349591734751384446">"Odaberi aplikaciju za otklanjanje grešaka"</string>
+    <string name="debug_app_not_set" msgid="718752499586403499">"Nema postavljenih aplikac. za otklanjanje grešaka"</string>
+    <string name="debug_app_set" msgid="2063077997870280017">"Aplikacija za otklanjanje grešaka: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="select_application" msgid="5156029161289091703">"Odaberite aplikaciju"</string>
+    <string name="no_application" msgid="2813387563129153880">"Ništa"</string>
+    <string name="wait_for_debugger" msgid="1202370874528893091">"Pričekajte na program za otklanjanje grešaka"</string>
+    <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Aplikacija u kojoj se otklanjaju greške čeka da se priloži program za otklanjanje grešaka prije izvršavanja"</string>
+    <string name="debug_input_category" msgid="1811069939601180246">"Ulaz"</string>
+    <string name="debug_drawing_category" msgid="6755716469267367852">"Crtanje"</string>
+    <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Prikaz s hardverskom akceleracijom"</string>
+    <string name="media_category" msgid="4388305075496848353">"Mediji"</string>
+    <string name="debug_monitoring_category" msgid="7640508148375798343">"Praćenje"</string>
+    <string name="strict_mode" msgid="1938795874357830695">"Omogućen strogi režim"</string>
+    <string name="strict_mode_summary" msgid="142834318897332338">"Prikaži ekran uz treptanje kada aplikacije vrše duge operacije u glavnoj niti"</string>
+    <string name="pointer_location" msgid="6084434787496938001">"Lokacija pokazivača"</string>
+    <string name="pointer_location_summary" msgid="840819275172753713">"Trenutni podaci o dodirivanju prikazuje se u nadsloju preko ekrana"</string>
+    <string name="show_touches" msgid="1356420386500834339">"Prikaži dodire"</string>
+    <string name="show_touches_summary" msgid="6684407913145150041">"Prikaži vizuelne povratne informacije za dodire"</string>
+    <string name="show_screen_updates" msgid="5470814345876056420">"Prikaži ažuriranja za površinu"</string>
+    <string name="show_screen_updates_summary" msgid="2569622766672785529">"Prikazi cijele površine prozora uz treptanje prilikom ažuriranja"</string>
+    <string name="show_hw_screen_updates" msgid="5036904558145941590">"Pok. ažur. za GPU prikaz"</string>
+    <string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"Prikazi uz treptanje unutar prozora kada se crta koristeći GPU"</string>
+    <string name="show_hw_layers_updates" msgid="5645728765605699821">"Prikaži dodatne informacije za ažuriranja za hardver"</string>
+    <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Trepći hardverske slojeve zeleno kada se ažuriraju"</string>
+    <string name="debug_hw_overdraw" msgid="2968692419951565417">"Otkl. GPU overdraw greške"</string>
+    <string name="disable_overlays" msgid="2074488440505934665">"Onemog. HW preklapanja"</string>
+    <string name="disable_overlays_summary" msgid="3578941133710758592">"Uvijek koristi GPU za kompoziciju ekrana"</string>
+    <string name="simulate_color_space" msgid="6745847141353345872">"Simuliraj prostor boje"</string>
+    <string name="enable_opengl_traces_title" msgid="6790444011053219871">"Omogući OpenGL zapise"</string>
+    <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Isključi USB audio usmjeravanje"</string>
+    <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Onemogući autom. usmjerav. na USB audio periferije"</string>
+    <string name="debug_layout" msgid="5981361776594526155">"Prikaži granice rasporeda"</string>
+    <string name="debug_layout_summary" msgid="2001775315258637682">"Prikaži granice isječka, margine itd."</string>
+    <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Prisilno postavi raspored s desna u lijevo"</string>
+    <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Prisilno postavi raspored ekrana s desna u lijevo za sve regije"</string>
+    <string name="show_cpu_usage" msgid="2389212910758076024">"Prikaži korištenje CPU-a"</string>
+    <string name="show_cpu_usage_summary" msgid="2113341923988958266">"Trenutno korištenje CPU-a prikazuje se u nadsloju preko ekrana"</string>
+    <string name="force_hw_ui" msgid="6426383462520888732">"Prisili GPU iscrtavanje"</string>
+    <string name="force_hw_ui_summary" msgid="5535991166074861515">"Prisilno koristite GPU za 2d crtanje"</string>
+    <string name="force_msaa" msgid="7920323238677284387">"Prinudno primjeni 4x MSAA"</string>
+    <string name="force_msaa_summary" msgid="9123553203895817537">"Omogući 4x MSAA u OpenGL ES 2.0 aplikacijama"</string>
+    <string name="show_non_rect_clip" msgid="505954950474595172">"Ispravi pogreške na nepravougaonim operacijama isecanja"</string>
+    <string name="track_frame_time" msgid="6146354853663863443">"Iscrtavanje GPU profila"</string>
+    <string name="window_animation_scale_title" msgid="6162587588166114700">"Skala animacije prozora"</string>
+    <string name="transition_animation_scale_title" msgid="387527540523595875">"Skaliranje animacije prelaza"</string>
+    <string name="animator_duration_scale_title" msgid="3406722410819934083">"Skala trajanja animatora"</string>
+    <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simuliraj sekundarne ekrane"</string>
+    <string name="debug_applications_category" msgid="4206913653849771549">"Aplikacije"</string>
+    <string name="immediately_destroy_activities" msgid="1579659389568133959">"Ne čuvaj aktivnosti"</string>
+    <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Obustavi svaku aktivnosti čim je korisnik napusti"</string>
+    <string name="app_process_limit_title" msgid="4280600650253107163">"Ograničenje procesa u pozadini"</string>
+    <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
+    <string name="show_all_anrs_summary" msgid="641908614413544127">"Prik. dijalog Aplikacija ne reagira za apl. u poz."</string>
+    <!-- no translation found for force_allow_on_external (3215759785081916381) -->
+    <skip />
+    <!-- no translation found for force_allow_on_external_summary (3191952505860343233) -->
+    <skip />
+    <!-- no translation found for force_resizable_activities (8615764378147824985) -->
+    <skip />
+    <!-- no translation found for force_resizable_activities_summary (4508217476997182216) -->
+    <skip />
+    <!-- no translation found for enable_freeform_support (1461893351278940416) -->
+    <skip />
+    <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
+    <skip />
+    <string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka za rezervnu kopiju za radnu površinu"</string>
+    <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Potpune sigurnosne kopije za računare trenutno nisu zaštićene"</string>
+    <string name="local_backup_password_summary_change" msgid="2731163425081172638">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije za radnu površinu"</string>
+    <string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova lozinka za rezervnu kopiju postavljena"</string>
+    <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"Nova lozinka i potvrda se ne podudaraju"</string>
+    <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Nije uspjelo postavljanje lozinke za rezervnu kopiju"</string>
+  <string-array name="color_mode_names">
+    <item msgid="2425514299220523812">"Živopisan (zadano)"</item>
+    <item msgid="8446070607501413455">"Prirodan"</item>
+    <item msgid="6553408765810699025">"Standardni"</item>
+  </string-array>
+  <string-array name="color_mode_descriptions">
+    <item msgid="4979629397075120893">"Unaprijeđene boje"</item>
+    <item msgid="8280754435979370728">"Prirodne boje onako kako ih oko vidi"</item>
+    <item msgid="5363960654009010371">"Boje optimizirane za digitalni sadržaj"</item>
+  </string-array>
+    <string name="inactive_apps_title" msgid="1317817863508274533">"Neaktivne aplikacije"</string>
+    <string name="inactive_app_inactive_summary" msgid="6768756967594202411">"Neaktivna je. Dodirnite da biste promenili."</string>
+    <string name="inactive_app_active_summary" msgid="4512911571954375968">"Aktivna je. Dodirnite da biste promenili."</string>
+    <string name="runningservices_settings_title" msgid="8097287939865165213">"Pokrenute usluge"</string>
+    <string name="runningservices_settings_summary" msgid="854608995821032748">"Prikažite trenutno pokrenute usluge i upravljajte njima"</string>
+    <!-- no translation found for night_mode_title (2594133148531256513) -->
+    <skip />
+    <string name="night_mode_summary" msgid="9196605054622017193">"%s"</string>
+    <!-- no translation found for night_mode_no (9171772244775838901) -->
+    <skip />
+    <!-- no translation found for night_mode_yes (2218157265997633432) -->
+    <skip />
+    <string name="night_mode_auto" msgid="7508348175804304327">"Automatski"</string>
+    <!-- no translation found for select_webview_provider_title (4628592979751918907) -->
+    <skip />
+    <!-- no translation found for select_webview_provider_dialog_title (4370551378720004872) -->
+    <skip />
+    <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+    <skip />
+    <!-- no translation found for convert_to_file_encryption (3060156730651061223) -->
+    <skip />
+    <!-- no translation found for convert_to_file_encryption_enabled (2861258671151428346) -->
+    <skip />
+    <!-- no translation found for convert_to_file_encryption_done (7859766358000523953) -->
+    <skip />
+    <!-- no translation found for title_convert_fbe (1263622876196444453) -->
+    <skip />
+    <!-- no translation found for convert_to_fbe_warning (6139067817148865527) -->
+    <skip />
+    <!-- no translation found for button_convert_fbe (5152671181309826405) -->
+    <skip />
+    <string name="picture_color_mode" msgid="4560755008730283695">"Režim boja Slika"</string>
+    <string name="picture_color_mode_desc" msgid="1141891467675548590">"Koristi sRGB"</string>
+    <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Onemogućeno"</string>
+    <string name="daltonizer_mode_monochromacy" msgid="8485709880666106721">"Crno-bijelo"</string>
+    <string name="daltonizer_mode_deuteranomaly" msgid="5475532989673586329">"Deuteranomalija (crveno-zeleno)"</string>
+    <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"Protanomalija (crveno-zeleno)"</string>
+    <string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"Tritanomalija (plavo-žuta)"</string>
+    <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Ispravka boje"</string>
+    <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_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>
+    <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>
+    <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>
+    <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>
+    <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>
+    <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>
+    <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string>
+    <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično 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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogućio administrator"</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 2f81098..e837ae6 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Opció desactivada per l\'administrador"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index f1c9e27..e1f9266 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Zakázáno administrátorem"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 90ea69a..62f920c 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Deaktiveret af administratoren"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index f768dc3..a14cf3e 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Vom Administrator deaktiviert"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index dddd780..3fbe9bb 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Δεν φορτίζει"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Δεν φορτίζει"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Πλήρης"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Απενεργοποιήθηκε από το διαχειριστή"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index b938ace..9c11343 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Disabled by administrator"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index b938ace..9c11343 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Disabled by administrator"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index b938ace..9c11343 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Disabled by administrator"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index ea97ada..fafccf8 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Inhabilitada por el administrador"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 901dc25..3e52101 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Inhabilitada por el administrador"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index 970812a..308dd0e 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administraator on keelanud"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index 64a1410..aba1523 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administratzaileak desgaitu du"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 5380651..6307ee8 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"شارژ نمی‌شود"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"شارژ نمی‌شود"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"پر"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"سرپرست آن را غیرفعال کرده است"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 4b555ac..652e2b7 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Järjestelmänvalvojan käytöstä poistama"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 96d2e7b..1be9849 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Désactivé par l\'administrateur"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 6dabba8..9c1b89d 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Désactivé par l\'administrateur"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index d3773f6..c56fd57 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desactivado polo administrador"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 9e2ec7e..b9ff7f5 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"ચાર્જ થઈ રહ્યું નથી"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ચાર્જ થઈ રહ્યું નથી"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"પૂર્ણ"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"વ્યવસ્થાપક દ્વારા અક્ષમ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index b6b8eac..ae91aad 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज नहीं हो रही है"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज नहीं हो रही है"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"पूरी"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"व्यवस्थापक के द्वारा अक्षम किया गया"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 69b71fe..5947ef4 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogućio administrator"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 26d65fb..00076f0 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Letiltva a rendszergazda által"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 0caa981..639e0e6 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Չի լիցքավորվում"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Չի լիցքավորվում"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Լիցքավորված"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Կասեցված է ադմինիստրատորի կողմից"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 7aba923..ded51a4 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Dinonaktifkan oleh administrator"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index a534db6..345ad44 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Stjórnandi gerði óvirkt"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index eedfa33..874ebcc 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Disattivata dall\'amministratore"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index eb26eaf..0fd0466 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"לא בטעינה"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"לא טוען"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"מלא"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"הושבת על ידי מנהל המערכת"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index dfa7456..c881ca1 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -310,4 +310,5 @@
     <!-- String.format failed for translation -->
     <!-- no translation found for battery_info_status_full (2824614753861462808) -->
     <skip />
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"管理者によって無効にされています"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 0f0428f..f6d713e 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"არ იტენება"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"არ იტენება"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ბატარეა დატენილია"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"გათიშულია ადმინისტრატორის მიერ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 2f2ffbc..c839a0b 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Зарядталу орындалып жатқан жоқ"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Зарядталып тұрған жоқ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Толық"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Әкімші өшірген"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 6feb93d..4aa4d0d 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"មិនកំពុង​បញ្ចូល​ថ្ម"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"មិន​បញ្ចូលថ្ម"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ពេញ"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"បានបិទដំណើរការដោយអ្នកគ្រប់គ្រង"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 948c665315..ee4b254 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"ಚಾರ್ಜ್‌ ಆಗುತ್ತಿಲ್ಲ"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ಭರ್ತಿ"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ನಿರ್ವಾಹಕರಿಂದ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index ae82263..51a8a6f 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"충전 안함"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"충전 안함"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"충전 완료"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"관리자가 사용 중지함"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index fcd7b8f..66a83ca 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Кубат алган жок"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Кубатталган жок"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Толук"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Администратор өчүрүп койгон"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index c29b9ab..ed7b61a 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"ບໍ່ໄດ້ສາກໄຟ"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ບໍ່ໄດ້ສາກໄຟ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ເຕັມ"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ຖືກປິດໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index a75c24e..0790304 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Išjungė administratorius"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 23aa537..0333d58 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Atspējojis administrators"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index 32d276e..5a01bb7 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Не се полни"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се полни"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Целосна"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Оневозможено од администраторот"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 9684b7b..ac14b99 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"ചാർജ്ജുചെയ്യുന്നില്ല"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ചാർജ്ജുചെയ്യുന്നില്ല"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"നിറഞ്ഞു"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"അഡ്‌മിനിസ്ട്രേറ്റർ പ്രവർത്തനരഹിതമാക്കി"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index a3f9dfa..be9f520 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Цэнэглэхгүй байна"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Цэнэглэхгүй байна"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Дүүрэн"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Админ идэвхгүй болгосон"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index 804fab0..717543e 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज होत नाही"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज होत नाही"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"प्रशासकाद्वारे अक्षम केलेले"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 7020409..0206558 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Dilumpuhkan oleh pentadbir"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index e40da23..6153694 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"အားသွင်းမနေပါ"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"အားသွင်းမနေပါ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"အပြည့်"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"စီမံခန့်ခွဲသူမှ ပိတ်ထားသည်"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index e39cf30..0532dd4 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Avslått av administratoren"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index b8beecf..48cefce 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज भइरहेको छैन"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज हुँदै छैन"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"प्रशासकद्वारा असक्षम गरिएको"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 4873ac3..a0fb3100 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Uitgeschakeld door beheerder"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index 61f187d..8715438 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"ਪੂਰੀ"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 9e0abfa..786860f 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Wyłączone przez administratora"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index db6b326..e88ce8e 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desativada pelo administrador"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 2f25ae2..1124b3d 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desativado pelo administrador"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index db6b326..e88ce8e 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Desativada pelo administrador"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 141f877..30d6cf3 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -86,7 +86,7 @@
     <item msgid="2219332261255416635">"Animație la scara 1x"</item>
     <item msgid="3544428804137048509">"Animație la scara 1,5x"</item>
     <item msgid="3110710404225974514">"Animație la scara 2x"</item>
-    <item msgid="4402738611528318731">"Animaţie la scara 5x"</item>
+    <item msgid="4402738611528318731">"Animație la scara 5x"</item>
     <item msgid="6189539267968330656">"Animație la scara 10x"</item>
   </string-array>
   <string-array name="transition_animation_scale_entries">
@@ -99,13 +99,13 @@
     <item msgid="6660750935954853365">"Animație la scara 10x"</item>
   </string-array>
   <string-array name="animator_duration_scale_entries">
-    <item msgid="6039901060648228241">"Animaţie dezactivată"</item>
-    <item msgid="1138649021950863198">"Animaţie la scara 0,5x"</item>
-    <item msgid="4394388961370833040">"Animaţie la scara 1x"</item>
-    <item msgid="8125427921655194973">"Animaţie la scara 1,5x"</item>
-    <item msgid="3334024790739189573">"Animaţie la scara 2x"</item>
-    <item msgid="3170120558236848008">"Animaţie la scara 5x"</item>
-    <item msgid="1069584980746680398">"Animaţie la scara 10x"</item>
+    <item msgid="6039901060648228241">"Animație dezactivată"</item>
+    <item msgid="1138649021950863198">"Animație la scara 0,5x"</item>
+    <item msgid="4394388961370833040">"Animație la scara 1x"</item>
+    <item msgid="8125427921655194973">"Animație la scara 1,5x"</item>
+    <item msgid="3334024790739189573">"Animație la scara 2x"</item>
+    <item msgid="3170120558236848008">"Animație la scara 5x"</item>
+    <item msgid="1069584980746680398">"Animație la scara 10x"</item>
   </string-array>
   <string-array name="overlay_display_devices_entries">
     <item msgid="1606809880904982133">"Niciuna"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index e6a45a7..97bdd51 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -181,7 +181,7 @@
     <string name="adb_warning_title" msgid="6234463310896563253">"Permiteți depanarea USB?"</string>
     <string name="adb_warning_message" msgid="7316799925425402244">"Depanarea USB are exclusiv scopuri de dezvoltare. Utilizați-o pentru a copia date de pe computer pe dispozitiv, pentru a instala aplicații pe dispozitiv fără notificare și pentru a citi datele din jurnale."</string>
     <string name="adb_keys_warning_message" msgid="5659849457135841625">"Revocați accesul la remedierea erorilor prin USB de pe toate computerele pe care le-ați autorizat anterior?"</string>
-    <string name="dev_settings_warning_title" msgid="7244607768088540165">"Permiteţi setările pentru dezvoltare?"</string>
+    <string name="dev_settings_warning_title" msgid="7244607768088540165">"Permiteți setările pentru dezvoltare?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"Aceste setări sunt destinate exclusiv utilizării pentru dezvoltare. Din cauza lor, este posibil ca dispozitivul dvs. și aplicațiile de pe acesta să nu mai funcţioneze sau să funcţioneze necorespunzător."</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificați aplicațiile prin USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificaţi aplicațiile instalate utilizând ADB/ADT, pentru a detecta un comportament dăunător."</string>
@@ -191,7 +191,7 @@
     <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Configurați verific. HDCP"</string>
     <string name="debug_debugging_category" msgid="6781250159513471316">"Depanare"</string>
     <string name="debug_app" msgid="8349591734751384446">"Selectați aplicația de depanare"</string>
-    <string name="debug_app_not_set" msgid="718752499586403499">"Nu aţi setat o aplicație de depanare"</string>
+    <string name="debug_app_not_set" msgid="718752499586403499">"Nu ați setat o aplicație de depanare"</string>
     <string name="debug_app_set" msgid="2063077997870280017">"Aplicaţie de depanare: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="select_application" msgid="5156029161289091703">"Selectaţi o aplicație"</string>
     <string name="no_application" msgid="2813387563129153880">"Niciuna"</string>
@@ -251,7 +251,7 @@
     <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Activează compatibilitatea pentru ferestrele experimentale cu formă liberă."</string>
     <string name="local_backup_password_title" msgid="3860471654439418822">"Parolă copie rez. desktop"</string>
     <string name="local_backup_password_summary_none" msgid="6951095485537767956">"În prezent, copiile de rezervă complete pe desktop nu sunt protejate"</string>
-    <string name="local_backup_password_summary_change" msgid="2731163425081172638">"Atingeţi pentru a modifica sau pentru a elimina parola pentru copiile de rezervă complete pe desktop"</string>
+    <string name="local_backup_password_summary_change" msgid="2731163425081172638">"Atingeți pentru a modifica sau pentru a elimina parola pentru copiile de rezervă complete pe desktop"</string>
     <string name="local_backup_password_toast_success" msgid="582016086228434290">"A fost setată o parolă de rezervă nouă"</string>
     <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"Parola nouă și confirmarea acesteia nu se potrivesc."</string>
     <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Setarea parolei de rezervă a eșuat"</string>
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Dezactivată de administrator"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 2bb3fdb3..9f08ca7 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряжается"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряжается"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Батарея заряжена"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Отключено администратором"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index bd9426c..19fa2be 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"ආරෝපණය නොවේ"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ආරෝපණය නොවෙමින්"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"පූර්ණ"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"පරිපාලක විසින් අබල කරන ලදී"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 8df02ea..ee83b81 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Zakázané správcom"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 57495e6..02a6f73 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Onemogočil skrbnik"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 1835b39..3704ee5 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Çaktivizuar nga administratori"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index c39682a..bc04d26 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Не пуни се"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не пуни се"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Пуно"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Онемогућио је администратор"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 1bdf6b2..1fb9acbd 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Har inaktiverats av administratören"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 9cf0db7..c8cce1f 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Msimamizi amezima mapendeleo ya mipangilio"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index c21db5b..aded7da 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"சார்ஜ் செய்யப்படவில்லை"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"சார்ஜ் ஏறவில்லை"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"முழுமை"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"நிர்வாகி முடக்கியுள்ளார்"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 04f0ca0..0acd8d5 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"ఛార్జ్ కావడం లేదు"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ఛార్జ్ కావడం లేదు"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"నిండింది"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"నిర్వాహకుడు నిలిపివేసారు"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index acde81e..316472c 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"ไม่ได้ชาร์จ"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ไม่ได้ชาร์จ"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"เต็ม"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"ปิดใช้โดยผู้ดูแลระบบ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 7e856e85..452afa6 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Na-disable ng administrator"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 8577f7d..0e4445c 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Yönetici tarafından devre dışı bırakıldı"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 3e89cce..a0ffb2b 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряджається"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряджається"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"Акумулятор заряджено"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Вимкнено адміністратором"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index a565ab7..e3e0a9e 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"چارج نہیں ہو رہا ہے"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"چارج نہیں ہو رہا ہے"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"مکمل"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"منتظم نے غیر فعال کر دیا"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index 246287a..182c84c 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"Quvvatlantirilmayapti"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Quvvatlanmayapti"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"To‘la"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Administrator tomonidan o‘chirib qo‘yilgan"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index f07c8a0..57e2573 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Bị tắt bởi quản trị viên"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 5c4f733..20c7874 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"未在充电"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"未在充电"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"电量充足"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"已被管理员禁用"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 952b198..583db26 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"未開始充電"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"電量已滿"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"管理員已停用此設定"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index f66f093..3bb2176 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -308,4 +308,5 @@
     <string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string>
     <string name="battery_info_status_not_charging" msgid="2820070506621483576">"非充電中"</string>
     <string name="battery_info_status_full" msgid="2824614753861462808">"電力充足"</string>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"已由管理員停用"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index f42abbc..ca9d867 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -308,4 +308,5 @@
     <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>
+    <string name="disabled_by_admin_summary_text" msgid="7787027069207263048">"Ikhutshazwe umlawuli"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index d3c8416..38d8907 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -515,9 +515,9 @@
     <string name="pointer_location_summary">Screen overlay showing current touch data</string>
 
     <!-- UI debug setting: show touches? [CHAR LIMIT=25] -->
-    <string name="show_touches">Show touches</string>
+    <string name="show_touches">Show taps</string>
     <!-- UI debug setting: show touches location summary [CHAR LIMIT=50] -->
-    <string name="show_touches_summary">Show visual feedback for touches</string>
+    <string name="show_touches_summary">Show visual feedback for taps</string>
 
     <!-- UI debug setting: show where surface updates happen? [CHAR LIMIT=25] -->
     <string name="show_screen_updates">Show surface updates</string>
@@ -634,7 +634,7 @@
     <!-- Summary text of the "local backup password" setting when the user has not supplied a password -->
     <string name="local_backup_password_summary_none">Desktop full backups aren\u2019t currently protected</string>
     <!-- Summary text of the "local backup password" setting when the user has already supplied a password -->
-    <string name="local_backup_password_summary_change">Touch to change or remove the password for desktop full backups</string>
+    <string name="local_backup_password_summary_change">Tap to change or remove the password for desktop full backups</string>
 
     <!-- Toast message shown when the user successfully sets a new local backup password [CHAR LIMIT=80] -->
     <string name="local_backup_password_toast_success">New backup password set</string>
@@ -660,9 +660,9 @@
     <!-- Settings item title for inactive apps [CHAR LIMIT=35] -->
     <string name="inactive_apps_title">Inactive apps</string>
     <!-- Settings item summary for inactive app [CHAR LIMIT=100] -->
-    <string name="inactive_app_inactive_summary">Inactive. Touch to toggle.</string>
+    <string name="inactive_app_inactive_summary">Inactive. Tap to toggle.</string>
     <!-- Settings item summary for active app [CHAR LIMIT=100] -->
-    <string name="inactive_app_active_summary">Active. Touch to toggle.</string>
+    <string name="inactive_app_active_summary">Active. Tap to toggle.</string>
 
     <!-- Services settings screen, setting option name for the user to go to the screen to view running services -->
     <string name="runningservices_settings_title">Running services</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 85cc3e4..f885110 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -155,7 +155,7 @@
             for (UserInfo userInfo : um.getProfiles(userId)) {
                 final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
                 if (admins == null) {
-                    return null;
+                    continue;
                 }
                 final boolean isSeparateProfileChallengeEnabled =
                         lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
@@ -209,16 +209,7 @@
         IPackageManager ipm = AppGlobals.getPackageManager();
         try {
             if (ipm.getBlockUninstallForUser(packageName, userId)) {
-                DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
-                        Context.DEVICE_POLICY_SERVICE);
-                if (dpm == null) {
-                    return null;
-                }
-                ComponentName admin = dpm.getProfileOwner();
-                if (admin == null) {
-                    admin = dpm.getDeviceOwnerComponentOnCallingUser();
-                }
-                return new EnforcedAdmin(admin, UserHandle.myUserId());
+                return getProfileOrDeviceOwner(context, userId);
             }
         } catch (RemoteException e) {
             // Nothing to do
@@ -238,7 +229,7 @@
         try {
             ApplicationInfo ai = ipm.getApplicationInfo(packageName, 0, userId);
             if (ai != null && ((ai.flags & ApplicationInfo.FLAG_SUSPENDED) != 0)) {
-                return getProfileOrDeviceOwnerOnCallingUser(context);
+                return getProfileOrDeviceOwner(context, userId);
             }
         } catch (RemoteException e) {
             // Nothing to do
@@ -246,6 +237,80 @@
         return null;
     }
 
+    public static EnforcedAdmin checkIfInputMethodDisallowed(Context context,
+            String packageName, int userId) {
+        DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        if (dpm == null) {
+            return null;
+        }
+        EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId);
+        boolean permitted = true;
+        if (admin != null) {
+            permitted = dpm.isInputMethodPermittedByAdmin(admin.component,
+                    packageName, userId);
+        }
+        int managedProfileId = getManagedProfileId(context, userId);
+        EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId);
+        boolean permittedByProfileAdmin = true;
+        if (profileAdmin != null) {
+            permittedByProfileAdmin = dpm.isInputMethodPermittedByAdmin(profileAdmin.component,
+                    packageName, managedProfileId);
+        }
+        if (!permitted && !permittedByProfileAdmin) {
+            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+        } else if (!permitted) {
+            return admin;
+        } else if (!permittedByProfileAdmin) {
+            return profileAdmin;
+        }
+        return null;
+    }
+
+    public static EnforcedAdmin checkIfAccessibilityServiceDisallowed(Context context,
+            String packageName, int userId) {
+        DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        if (dpm == null) {
+            return null;
+        }
+        EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId);
+        boolean permitted = true;
+        if (admin != null) {
+            permitted = dpm.isAccessibilityServicePermittedByAdmin(admin.component,
+                    packageName, userId);
+        }
+        int managedProfileId = getManagedProfileId(context, userId);
+        EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId);
+        boolean permittedByProfileAdmin = true;
+        if (profileAdmin != null) {
+            permittedByProfileAdmin = dpm.isAccessibilityServicePermittedByAdmin(
+                    profileAdmin.component, packageName, managedProfileId);
+        }
+        if (!permitted && !permittedByProfileAdmin) {
+            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+        } else if (!permitted) {
+            return admin;
+        } else if (!permittedByProfileAdmin) {
+            return profileAdmin;
+        }
+        return null;
+    }
+
+    private static int getManagedProfileId(Context context, int userId) {
+        UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        List<UserInfo> userProfiles = um.getProfiles(userId);
+        for (UserInfo uInfo : userProfiles) {
+            if (uInfo.id == userId) {
+                continue;
+            }
+            if (uInfo.isManagedProfile()) {
+                return uInfo.id;
+            }
+        }
+        return UserHandle.USER_NULL;
+    }
+
     /**
      * Check if account management for a specific type of account is disabled by admin.
      * Only a profile or device owner can disable account management. So, we check if account
@@ -255,7 +320,7 @@
      * or {@code null} if the account management is not disabled.
      */
     public static EnforcedAdmin checkIfAccountManagementDisabled(Context context,
-            String accountType) {
+            String accountType, int userId) {
         if (accountType == null) {
             return null;
         }
@@ -265,7 +330,7 @@
             return null;
         }
         boolean isAccountTypeDisabled = false;
-        String[] disabledTypes = dpm.getAccountTypesWithManagementDisabled();
+        String[] disabledTypes = dpm.getAccountTypesWithManagementDisabledAsUser(userId);
         for (String type : disabledTypes) {
             if (accountType.equals(type)) {
                 isAccountTypeDisabled = true;
@@ -275,7 +340,7 @@
         if (!isAccountTypeDisabled) {
             return null;
         }
-        return getProfileOrDeviceOwnerOnCallingUser(context);
+        return getProfileOrDeviceOwner(context, userId);
     }
 
     /**
@@ -296,7 +361,7 @@
     }
 
     /**
-     * Checks if an admin has enforced minimum password quality requirements on the device.
+     * Checks if an admin has enforced minimum password quality requirements on the given user.
      *
      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
      * or {@code null} if no quality requirements are set. If the requirements are set by
@@ -304,35 +369,73 @@
      * {@link UserHandle#USER_NULL}.
      *
      */
-    public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context) {
+    public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context, int userId) {
         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
         if (dpm == null) {
             return null;
         }
-        boolean isDisabledByMultipleAdmins = false;
-        ComponentName adminComponent = null;
-        List<ComponentName> admins = dpm.getActiveAdmins();
-        int quality;
-        if (admins != null) {
+
+        LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
+        EnforcedAdmin enforcedAdmin = null;
+        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);
+            if (admins == null) {
+                return null;
+            }
             for (ComponentName admin : admins) {
-                quality = dpm.getPasswordQuality(admin);
-                if (quality >= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
-                    if (adminComponent == null) {
-                        adminComponent = admin;
+                if (dpm.getPasswordQuality(admin, userId)
+                        > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+                    if (enforcedAdmin == null) {
+                        enforcedAdmin = new EnforcedAdmin(admin, userId);
                     } else {
-                        isDisabledByMultipleAdmins = true;
-                        break;
+                        return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
                     }
                 }
             }
-        }
-        EnforcedAdmin enforcedAdmin = null;
-        if (adminComponent != null) {
-            if (!isDisabledByMultipleAdmins) {
-                enforcedAdmin = new EnforcedAdmin(adminComponent, UserHandle.myUserId());
-            } else {
-                enforcedAdmin = new EnforcedAdmin();
+        } 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) {
+                    continue;
+                }
+                final boolean isSeparateProfileChallengeEnabled =
+                        lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
+                for (ComponentName admin : admins) {
+                    if (!isSeparateProfileChallengeEnabled) {
+                        if (dpm.getPasswordQuality(admin, userInfo.id)
+                                > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+                            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.getPasswordQuality(admin, userInfo.id)
+                                > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+                            if (enforcedAdmin == null) {
+                                enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
+                            } else {
+                                return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+                            }
+                        }
+                    }
+                }
             }
         }
         return enforcedAdmin;
@@ -352,7 +455,8 @@
         EnforcedAdmin enforcedAdmin = null;
         final int userId = UserHandle.myUserId();
         if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
-            // If the user has a separate challenge, only consider the admins in that user.
+            // userId is managed profile and has a separate challenge, only consider
+            // the admins in that user.
             final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
             if (admins == null) {
                 return null;
@@ -373,7 +477,7 @@
             for (UserInfo userInfo : um.getProfiles(userId)) {
                 final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
                 if (admins == null) {
-                    return null;
+                    continue;
                 }
                 final boolean isSeparateProfileChallengeEnabled =
                         lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
@@ -410,19 +514,37 @@
         return enforcedAdmin;
     }
 
-    public static EnforcedAdmin getProfileOrDeviceOwnerOnCallingUser(Context context) {
+    public static EnforcedAdmin getProfileOrDeviceOwner(Context context, int userId) {
+        if (userId == UserHandle.USER_NULL) {
+            return null;
+        }
         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
         if (dpm == null) {
             return null;
         }
-        ComponentName adminComponent = dpm.getDeviceOwnerComponentOnCallingUser();
+        ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
         if (adminComponent != null) {
-            return new EnforcedAdmin(adminComponent, UserHandle.myUserId());
+            return new EnforcedAdmin(adminComponent, userId);
         }
-        adminComponent = dpm.getProfileOwner();
+        if (dpm.getDeviceOwnerUserId() == userId) {
+            adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
+            if (adminComponent != null) {
+                return new EnforcedAdmin(adminComponent, userId);
+            }
+        }
+        return null;
+    }
+
+    public static EnforcedAdmin getDeviceOwner(Context context) {
+        final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        if (dpm == null) {
+            return null;
+        }
+        ComponentName adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
         if (adminComponent != null) {
-            return new EnforcedAdmin(adminComponent, UserHandle.myUserId());
+            return new EnforcedAdmin(adminComponent, dpm.getDeviceOwnerUserId());
         }
         return null;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
index f5a2aae..d368de9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
@@ -15,40 +15,19 @@
  */
 package com.android.settingslib;
 
-import android.app.ActivityManager;
-import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.content.res.Resources;
-import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
 import android.os.SystemProperties;
-import android.os.UserManager;
-import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
 
 public class TetherUtil {
 
-    // Extras used for communicating with the TetherService.
-    public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
-    public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
-    public static final String EXTRA_SET_ALARM = "extraSetAlarm";
-    /**
-     * Tells the service to run a provision check now.
-     */
-    public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
-
     public static boolean setWifiTethering(boolean enable, Context context) {
         final WifiManager wifiManager =
                 (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
         return wifiManager.setWifiApEnabled(null, enable);
     }
 
-    public static boolean isWifiTetherEnabled(Context context) {
-        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-        return wifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED;
-    }
-
     private static boolean isEntitlementCheckRequired(Context context) {
         final CarrierConfigManager configManager = (CarrierConfigManager) context
              .getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -71,13 +50,4 @@
         }
         return (provisionApp.length == 2);
     }
-
-    public static boolean isTetheringSupported(Context context) {
-        final ConnectivityManager cm =
-                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
-        final boolean isAdminUser =
-                UserManager.get(context).isUserAdmin(ActivityManager.getCurrentUser());
-        return isAdminUser && cm.isTetheringSupported();
-    }
-
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 7ee53a2..c075703 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -835,7 +835,7 @@
     public int getConnectionSummary() {
         boolean profileConnected = false;       // at least one profile is connected
         boolean a2dpNotConnected = false;       // A2DP is preferred but not connected
-        boolean headsetNotConnected = false;    // Headset is preferred but not connected
+        boolean hfpNotConnected = false;    // HFP is preferred but not connected
 
         for (LocalBluetoothProfile profile : getProfiles()) {
             int connectionStatus = getProfileConnectionState(profile);
@@ -851,11 +851,12 @@
 
                 case BluetoothProfile.STATE_DISCONNECTED:
                     if (profile.isProfileReady()) {
-                        if ((profile instanceof A2dpProfile)||
+                        if ((profile instanceof A2dpProfile) ||
                             (profile instanceof A2dpSinkProfile)){
                             a2dpNotConnected = true;
-                        } else if (profile instanceof HeadsetProfile) {
-                            headsetNotConnected = true;
+                        } else if ((profile instanceof HeadsetProfile) ||
+                                   (profile instanceof HfpClientProfile)) {
+                            hfpNotConnected = true;
                         }
                     }
                     break;
@@ -863,11 +864,11 @@
         }
 
         if (profileConnected) {
-            if (a2dpNotConnected && headsetNotConnected) {
+            if (a2dpNotConnected && hfpNotConnected) {
                 return R.string.bluetooth_connected_no_headset_no_a2dp;
             } else if (a2dpNotConnected) {
                 return R.string.bluetooth_connected_no_a2dp;
-            } else if (headsetNotConnected) {
+            } else if (hfpNotConnected) {
                 return R.string.bluetooth_connected_no_headset;
             } else {
                 return R.string.bluetooth_connected;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
new file mode 100755
index 0000000..9b699bc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothHeadsetClient;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Handles the Handsfree HF role.
+ */
+final class HfpClientProfile implements LocalBluetoothProfile {
+    private static final String TAG = "HfpClientProfile";
+    private static boolean V = false;
+
+    private BluetoothHeadsetClient mService;
+    private boolean mIsProfileReady;
+
+    private final LocalBluetoothAdapter mLocalAdapter;
+    private final CachedBluetoothDeviceManager mDeviceManager;
+
+    static final ParcelUuid[] SRC_UUIDS = {
+        BluetoothUuid.HSP_AG,
+        BluetoothUuid.Handsfree_AG,
+    };
+
+    static final String NAME = "HEADSET_CLIENT";
+    private final LocalBluetoothProfileManager mProfileManager;
+
+    // Order of this profile in device profiles list
+    private static final int ORDINAL = 0;
+
+    // These callbacks run on the main thread.
+    private final class HfpClientServiceListener
+            implements BluetoothProfile.ServiceListener {
+
+        @Override
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            if (V) Log.d(TAG,"Bluetooth service connected");
+            mService = (BluetoothHeadsetClient) proxy;
+            // We just bound to the service, so refresh the UI for any connected HFP devices.
+            List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+            while (!deviceList.isEmpty()) {
+                BluetoothDevice nextDevice = deviceList.remove(0);
+                CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+                // we may add a new device here, but generally this should not happen
+                if (device == null) {
+                    Log.w(TAG, "HfpClient profile found new device: " + nextDevice);
+                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                }
+                device.onProfileStateChanged(
+                    HfpClientProfile.this, BluetoothProfile.STATE_CONNECTED);
+                device.refresh();
+            }
+            mIsProfileReady=true;
+        }
+
+        @Override
+        public void onServiceDisconnected(int profile) {
+            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            mIsProfileReady=false;
+        }
+    }
+
+    @Override
+    public boolean isProfileReady() {
+        return mIsProfileReady;
+    }
+
+    HfpClientProfile(Context context, LocalBluetoothAdapter adapter,
+            CachedBluetoothDeviceManager deviceManager,
+            LocalBluetoothProfileManager profileManager) {
+        mLocalAdapter = adapter;
+        mDeviceManager = deviceManager;
+        mProfileManager = profileManager;
+        mLocalAdapter.getProfileProxy(context, new HfpClientServiceListener(),
+                BluetoothProfile.HEADSET_CLIENT);
+    }
+
+    @Override
+    public boolean isConnectable() {
+        return true;
+    }
+
+    @Override
+    public boolean isAutoConnectable() {
+        return true;
+    }
+
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        return mService.getDevicesMatchingConnectionStates(
+              new int[] {BluetoothProfile.STATE_CONNECTED,
+                         BluetoothProfile.STATE_CONNECTING,
+                         BluetoothProfile.STATE_DISCONNECTING});
+    }
+
+    @Override
+    public boolean connect(BluetoothDevice device) {
+        if (mService == null) return false;
+        List<BluetoothDevice> srcs = getConnectedDevices();
+        if (srcs != null) {
+            for (BluetoothDevice src : srcs) {
+                if (src.equals(device)) {
+                    // Connect to same device, Ignore it
+                    Log.d(TAG,"Ignoring Connect");
+                    return true;
+                }
+            }
+            // Handsfree HF only supports one source connection and hence it is OK to disconnect
+            // the only connected device here.
+            for (BluetoothDevice src : srcs) {
+                mService.disconnect(src);
+            }
+        }
+        return mService.connect(device);
+    }
+
+    @Override
+    public boolean disconnect(BluetoothDevice device) {
+        if (mService == null) return false;
+        // Downgrade priority as user is disconnecting the headset.
+        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
+            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        }
+        return mService.disconnect(device);
+    }
+
+    @Override
+    public int getConnectionStatus(BluetoothDevice device) {
+        if (mService == null) {
+            return BluetoothProfile.STATE_DISCONNECTED;
+        }
+        return mService.getConnectionState(device);
+    }
+
+    @Override
+    public boolean isPreferred(BluetoothDevice device) {
+        if (mService == null) return false;
+        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+    }
+
+    @Override
+    public int getPreferred(BluetoothDevice device) {
+        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        return mService.getPriority(device);
+    }
+
+    @Override
+    public void setPreferred(BluetoothDevice device, boolean preferred) {
+        if (mService == null) return;
+        if (preferred) {
+            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            }
+        } else {
+            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return NAME;
+    }
+
+    @Override
+    public int getOrdinal() {
+        return ORDINAL;
+    }
+
+    @Override
+    public int getNameResource(BluetoothDevice device) {
+        return R.string.bluetooth_profile_headset;
+    }
+
+    @Override
+    public int getSummaryResourceForDevice(BluetoothDevice device) {
+        int state = getConnectionStatus(device);
+        switch (state) {
+            case BluetoothProfile.STATE_DISCONNECTED:
+                return R.string.bluetooth_headset_profile_summary_use_for;
+
+            case BluetoothProfile.STATE_CONNECTED:
+                return R.string.bluetooth_headset_profile_summary_connected;
+
+            default:
+                return Utils.getConnectionStateSummary(state);
+        }
+    }
+
+    @Override
+    public int getDrawableResource(BluetoothClass btClass) {
+        return R.drawable.ic_bt_headset_hfp;
+    }
+
+    protected void finalize() {
+        if (V) Log.d(TAG, "finalize()");
+        if (mService != null) {
+            try {
+                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
+                    BluetoothProfile.HEADSET_CLIENT, mService);
+                mService = null;
+            } catch (Throwable t) {
+                Log.w(TAG, "Error cleaning up HfpClient proxy", t);
+            }
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index b05e34c..6226b23 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -20,6 +20,7 @@
 import android.bluetooth.BluetoothA2dpSink;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHeadsetClient;
 import android.bluetooth.BluetoothMap;
 import android.bluetooth.BluetoothInputDevice;
 import android.bluetooth.BluetoothPan;
@@ -76,6 +77,7 @@
     private A2dpProfile mA2dpProfile;
     private A2dpSinkProfile mA2dpSinkProfile;
     private HeadsetProfile mHeadsetProfile;
+    private HfpClientProfile mHfpClientProfile;
     private MapProfile mMapProfile;
     private final HidProfile mHidProfile;
     private OppProfile mOppProfile;
@@ -150,6 +152,7 @@
             Log.w(TAG, "Warning: A2DP profile was previously added but the UUID is now missing.");
         }
 
+        // A2DP SINK
         if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
             if (mA2dpSinkProfile == null) {
                 if(DEBUG) Log.d(TAG, "Adding local A2DP Sink profile");
@@ -175,6 +178,22 @@
             Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing.");
         }
 
+        // Headset HF
+        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) {
+            if (mHfpClientProfile == null) {
+                if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
+                mHfpClientProfile =
+                    new HfpClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
+                addProfile(mHfpClientProfile, HfpClientProfile.NAME,
+                        BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
+            }
+        } else if (mHfpClientProfile != null) {
+            Log.w(TAG,
+                "Warning: Hfp Client profile was previously added but the UUID is now missing.");
+        } else {
+            Log.d(TAG, "Handsfree Uuid not found.");
+        }
+
         // OPP
         if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
             if (mOppProfile == null) {
@@ -312,17 +331,26 @@
         return mA2dpProfile;
     }
 
-    A2dpSinkProfile getA2dpSinkProfile() {
-        if ((mA2dpSinkProfile != null)&&(mA2dpSinkProfile.isProfileReady()))
-        return mA2dpSinkProfile;
-        else
+    public A2dpSinkProfile getA2dpSinkProfile() {
+        if ((mA2dpSinkProfile != null) && (mA2dpSinkProfile.isProfileReady())) {
+            return mA2dpSinkProfile;
+        } else {
             return null;
+        }
     }
 
     public HeadsetProfile getHeadsetProfile() {
         return mHeadsetProfile;
     }
 
+    public HfpClientProfile getHfpClientProfile() {
+        if ((mHfpClientProfile != null) && (mHfpClientProfile.isProfileReady())) {
+            return mHfpClientProfile;
+        } else {
+          return null;
+        }
+    }
+
     public PbapServerProfile getPbapProfile(){
         return mPbapProfile;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 56c4edb..5ffa581 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -141,6 +141,16 @@
         mCategoryListeners.remove(listener);
     }
 
+    public void setIsDrawerPresent(boolean isPresent) {
+        if (isPresent) {
+            mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+            updateDrawer();
+        } else {
+            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
+            mDrawerLayout = null;
+        }
+    }
+
     public void openDrawer() {
         if (mDrawerLayout != null) {
             mDrawerLayout.openDrawer(Gravity.START);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/NetworkPolicySerializer.java b/packages/SettingsProvider/src/com/android/providers/settings/NetworkPolicySerializer.java
deleted file mode 100644
index 4b87da4..0000000
--- a/packages/SettingsProvider/src/com/android/providers/settings/NetworkPolicySerializer.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package com.android.providers.settings;
-
-import android.net.NetworkPolicy;
-import android.net.NetworkTemplate;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-/**
- * Backup/Restore Serializer Class for android.net.NetworkPolicy
- */
-public class NetworkPolicySerializer {
-    private static final boolean DEBUG = false;
-    private static final String TAG = "NetworkPolicySerializer";
-
-    private static final int NULL = 0;
-    private static final int NOT_NULL = 1;
-    /**
-     * Current Version of the Serializer.
-     */
-    private static int STATE_VERSION = 1;
-
-    /**
-     * Marshals an array of NetworkPolicy objects into a byte-array.
-     *
-     * @param policies - NetworkPolicies to be Marshaled
-     * @return byte array
-     */
-
-    public static byte[] marshalNetworkPolicies(NetworkPolicy policies[]) {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        if (policies != null && policies.length != 0) {
-            DataOutputStream out = new DataOutputStream(baos);
-            try {
-                out.writeInt(STATE_VERSION);
-                out.writeInt(policies.length);
-                for (NetworkPolicy policy : policies) {
-                    byte[] marshaledPolicy = marshalNetworkPolicy(policy);
-                    if (marshaledPolicy != null) {
-                        out.writeByte(NOT_NULL);
-                        out.writeInt(marshaledPolicy.length);
-                        out.write(marshaledPolicy);
-                    } else {
-                        out.writeByte(NULL);
-                    }
-                }
-            } catch (IOException ioe) {
-                Log.e(TAG, "Failed to Convert NetworkPolicies to byte array", ioe);
-                baos.reset();
-            }
-        }
-        return baos.toByteArray();
-    }
-
-    /**
-     * Unmarshals a byte array into an array of NetworkPolicy Objects
-     *
-     * @param data - marshaled NetworkPolicies Array
-     * @return NetworkPolicy[] array
-     */
-    public static NetworkPolicy[] unmarshalNetworkPolicies(byte[] data) {
-        if (data == null || data.length == 0) {
-            return new NetworkPolicy[0];
-        }
-        DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
-        try {
-            int version = in.readInt();
-            int length = in.readInt();
-            NetworkPolicy[] policies = new NetworkPolicy[length];
-            for (int i = 0; i < length; i++) {
-                byte isNull = in.readByte();
-                if (isNull == NULL) continue;
-                int byteLength = in.readInt();
-                byte[] policyData = new byte[byteLength];
-                in.read(policyData, 0, byteLength);
-                policies[i] = unmarshalNetworkPolicy(policyData);
-            }
-            return policies;
-        } catch (IOException ioe) {
-            Log.e(TAG, "Failed to Convert byte array to NetworkPolicies", ioe);
-            return new NetworkPolicy[0];
-        }
-    }
-
-    /**
-     * Marshals a NetworkPolicy object into a byte-array.
-     *
-     * @param networkPolicy - NetworkPolicy to be Marshaled
-     * @return byte array
-     */
-    public static byte[] marshalNetworkPolicy(NetworkPolicy networkPolicy) {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        if (networkPolicy != null) {
-            DataOutputStream out = new DataOutputStream(baos);
-            try {
-                out.writeInt(STATE_VERSION);
-                writeNetworkTemplate(out, networkPolicy.template);
-                out.writeInt(networkPolicy.cycleDay);
-                writeString(out, networkPolicy.cycleTimezone);
-                out.writeLong(networkPolicy.warningBytes);
-                out.writeLong(networkPolicy.limitBytes);
-                out.writeLong(networkPolicy.lastWarningSnooze);
-                out.writeLong(networkPolicy.lastLimitSnooze);
-                out.writeInt(networkPolicy.metered ? 1 : 0);
-                out.writeInt(networkPolicy.inferred ? 1 : 0);
-            } catch (IOException ioe) {
-                Log.e(TAG, "Failed to Convert NetworkPolicy to byte array", ioe);
-                baos.reset();
-            }
-        }
-        return baos.toByteArray();
-    }
-
-    /**
-     * Unmarshals a byte array into a NetworkPolicy Object
-     *
-     * @param data - marshaled NetworkPolicy Object
-     * @return NetworkPolicy Object
-     */
-    public static NetworkPolicy unmarshalNetworkPolicy(byte[] data) {
-        if (data == null || data.length == 0) {
-            return null;
-        }
-        DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
-        try {
-            int version = in.readInt();
-            NetworkTemplate template = readNetworkTemplate(in, version);
-            int cycleDay = in.readInt();
-            String cycleTimeZone = readString(in, version);
-            long warningBytes = in.readLong();
-            long limitBytes = in.readLong();
-            long lastWarningSnooze = in.readLong();
-            long lastLimitSnooze = in.readLong();
-            boolean metered = in.readInt() == 1;
-            boolean inferred = in.readInt() == 1;
-            return new NetworkPolicy(template, cycleDay, cycleTimeZone, warningBytes, limitBytes,
-                    lastWarningSnooze, lastLimitSnooze, metered, inferred);
-        } catch (IOException ioe) {
-            Log.e(TAG, "Failed to Convert byte array to NetworkPolicy", ioe);
-            return null;
-        }
-    }
-
-    private static NetworkTemplate readNetworkTemplate(DataInputStream in, int version)
-            throws IOException {
-        byte isNull = in.readByte();
-        if (isNull == NULL) return null;
-        int matchRule = in.readInt();
-        String subscriberId = readString(in, version);
-        String networkId = readString(in, version);
-        return new NetworkTemplate(matchRule, subscriberId, networkId);
-    }
-
-    private static void writeNetworkTemplate(DataOutputStream out, NetworkTemplate template)
-            throws IOException {
-        if (template != null) {
-            out.writeByte(NOT_NULL);
-            out.writeInt(template.getMatchRule());
-            writeString(out, template.getSubscriberId());
-            writeString(out, template.getNetworkId());
-        } else {
-            out.writeByte(NULL);
-        }
-    }
-
-    private static String readString(DataInputStream in, int version) throws IOException {
-        byte isNull = in.readByte();
-        if (isNull == NOT_NULL) {
-            return in.readUTF();
-        }
-        return null;
-    }
-
-    private static void writeString(DataOutputStream out, String val) throws IOException {
-        if (val != null) {
-            out.writeByte(NOT_NULL);
-            out.writeUTF(val);
-        } else {
-            out.writeByte(NULL);
-        }
-    }
-}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 185a03f..b270dd8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -24,7 +24,6 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
-import android.net.NetworkPolicyManager;
 import android.net.Uri;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -82,13 +81,10 @@
     private static final String KEY_GLOBAL = "global";
     private static final String KEY_LOCALE = "locale";
     private static final String KEY_LOCK_SETTINGS = "lock_settings";
-    private static final String KEY_SOFTAP_CONFIG = "softap_config";
-    private static final String KEY_NET_POLICIES = "network_policies";
-
 
     // Versioning of the state file.  Increment this version
     // number any time the set of state items is altered.
-    private static final int STATE_VERSION = 6;
+    private static final int STATE_VERSION = 4;
 
     // Slots in the checksum array.  Never insert new items in the middle
     // of this array; new slots must be appended.
@@ -99,28 +95,22 @@
     private static final int STATE_WIFI_CONFIG     = 4;
     private static final int STATE_GLOBAL          = 5;
     private static final int STATE_LOCK_SETTINGS   = 6;
-    private static final int STATE_SOFTAP_CONFIG   = 7;
-    private static final int STATE_NET_POLICIES    = 8;
 
-    private static final int STATE_SIZE            = 9; // The current number of state items
+    private static final int STATE_SIZE            = 7; // The current number of state items
 
     // Number of entries in the checksum array at various version numbers
     private static final int STATE_SIZES[] = {
-            0,
-            4,              // version 1
-            5,              // version 2 added STATE_WIFI_CONFIG
-            6,              // version 3 added STATE_GLOBAL
-            7,              // version 4 added STATE_LOCK_SETTINGS
-            8,              // version 5 added STATE_SOFTAP_CONFIG
-            STATE_SIZE      // version 6 added STATE_NET_POLICIES
+        0,
+        4,              // version 1
+        5,              // version 2 added STATE_WIFI_CONFIG
+        6,              // version 3 added STATE_GLOBAL
+        STATE_SIZE      // version 4 added STATE_LOCK_SETTINGS
     };
 
     // Versioning of the 'full backup' format
     private static final int FULL_BACKUP_VERSION = 3;
     private static final int FULL_BACKUP_ADDED_GLOBAL = 2;  // added the "global" entry
     private static final int FULL_BACKUP_ADDED_LOCK_SETTINGS = 3; // added the "lock_settings" entry
-    private static final int FULL_BACKUP_ADDED_SOFTAP_CONF = 4; //added the "softap_config" entry
-    private static final int FULL_BACKUP_ADDED_NET_POLICIES = 5; //added the "network_policies" entry
 
     private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
 
@@ -129,8 +119,8 @@
     private static final String TAG = "SettingsBackupAgent";
 
     private static final String[] PROJECTION = {
-            Settings.NameValueTable.NAME,
-            Settings.NameValueTable.VALUE
+        Settings.NameValueTable.NAME,
+        Settings.NameValueTable.VALUE
     };
 
     private static final String FILE_WIFI_SUPPLICANT = "/data/misc/wifi/wpa_supplicant.conf";
@@ -406,7 +396,7 @@
 
     @Override
     public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
-                         ParcelFileDescriptor newState) throws IOException {
+            ParcelFileDescriptor newState) throws IOException {
 
         byte[] systemSettingsData = getSystemSettings();
         byte[] secureSettingsData = getSecureSettings();
@@ -415,34 +405,26 @@
         byte[] locale = mSettingsHelper.getLocaleData();
         byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
         byte[] wifiConfigData = getFileData(mWifiConfigFile);
-        byte[] softApConfigData = getSoftAPConfiguration();
-        byte[] netPoliciesData = getNetworkPolicies();
 
         long[] stateChecksums = readOldChecksums(oldState);
 
         stateChecksums[STATE_SYSTEM] =
-                writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
+            writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
         stateChecksums[STATE_SECURE] =
-                writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
+            writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
         stateChecksums[STATE_GLOBAL] =
-                writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data);
+            writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data);
         stateChecksums[STATE_LOCALE] =
-                writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
+            writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
         stateChecksums[STATE_WIFI_SUPPLICANT] =
-                writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
-                        wifiSupplicantData, data);
+            writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
+                    wifiSupplicantData, data);
         stateChecksums[STATE_WIFI_CONFIG] =
-                writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
-                        data);
+            writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
+                    data);
         stateChecksums[STATE_LOCK_SETTINGS] =
-                writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS,
-                        lockSettingsData, data);
-        stateChecksums[STATE_SOFTAP_CONFIG] =
-                writeIfChanged(stateChecksums[STATE_SOFTAP_CONFIG], KEY_SOFTAP_CONFIG,
-                        softApConfigData, data);
-        stateChecksums[STATE_NET_POLICIES] =
-                writeIfChanged(stateChecksums[STATE_NET_POLICIES], KEY_NET_POLICIES,
-                        netPoliciesData, data);
+            writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS,
+                    lockSettingsData, data);
 
         writeNewChecksums(stateChecksums, newState);
     }
@@ -522,7 +504,7 @@
                             restoredSupplicantData, restoredSupplicantData.length);
                     FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
                             FileUtils.S_IRUSR | FileUtils.S_IWUSR |
-                                    FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+                            FileUtils.S_IRGRP | FileUtils.S_IWGRP,
                             Process.myUid(), Process.WIFI_UID);
                 }
                 if (restoredWifiConfigFile != null) {
@@ -551,7 +533,7 @@
 
     @Override
     public void onRestore(BackupDataInput data, int appVersionCode,
-                          ParcelFileDescriptor newState) throws IOException {
+            ParcelFileDescriptor newState) throws IOException {
 
         HashSet<String> movedToGlobal = new HashSet<String>();
         Settings.System.getMovedToGlobalSettings(movedToGlobal);
@@ -579,15 +561,7 @@
                 mWifiRestore.incorporateWifiConfigFile(data);
             } else if (KEY_LOCK_SETTINGS.equals(key)) {
                 restoreLockSettings(data);
-            } else if (KEY_SOFTAP_CONFIG.equals(key)){
-                byte[] softapData = new byte[size];
-                data.readEntityData(softapData, 0, size);
-                restoreSoftApConfiguration(softapData);
-            } else if (KEY_NET_POLICIES.equals(key)) {
-                byte[] netPoliciesData = new byte[size];
-                data.readEntityData(netPoliciesData, 0, size);
-                restoreNetworkPolicies(netPoliciesData);
-            } else {
+             } else {
                 data.skipEntityData();
             }
         }
@@ -615,8 +589,6 @@
         byte[] locale = mSettingsHelper.getLocaleData();
         byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
         byte[] wifiConfigData = getFileData(mWifiConfigFile);
-        byte[] softApConfigData = getSoftAPConfiguration();
-        byte[] netPoliciesData = getNetworkPolicies();
 
         // Write the data to the staging file, then emit that as our tarfile
         // representation of the backed-up settings.
@@ -651,12 +623,6 @@
             if (DEBUG_BACKUP) Log.d(TAG, lockSettingsData.length + " bytes of lock settings data");
             out.writeInt(lockSettingsData.length);
             out.write(lockSettingsData);
-            if (DEBUG_BACKUP) Log.d(TAG, softApConfigData.length + " bytes of softap config data");
-            out.writeInt(softApConfigData.length);
-            out.write(softApConfigData);
-            if (DEBUG_BACKUP) Log.d(TAG, netPoliciesData.length + " bytes of network policies data");
-            out.writeInt(netPoliciesData.length);
-            out.write(netPoliciesData);
 
             out.flush();    // also flushes downstream
 
@@ -669,7 +635,7 @@
 
     @Override
     public void onRestoreFile(ParcelFileDescriptor data, long size,
-                              int type, String domain, String relpath, long mode, long mtime)
+            int type, String domain, String relpath, long mode, long mtime)
             throws IOException {
         if (DEBUG_BACKUP) Log.d(TAG, "onRestoreFile() invoked");
         // Our data is actually a blob of flattened settings data identical to that
@@ -726,7 +692,7 @@
             restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, buffer, nBytes);
             FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
                     FileUtils.S_IRUSR | FileUtils.S_IWUSR |
-                            FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+                    FileUtils.S_IRGRP | FileUtils.S_IWGRP,
                     Process.myUid(), Process.WIFI_UID);
             // retain the previous WIFI state.
             enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
@@ -749,26 +715,6 @@
                 }
             }
 
-            if (version >= FULL_BACKUP_ADDED_SOFTAP_CONF){
-                nBytes = in.readInt();
-                if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of softap config data");
-                if (nBytes > buffer.length) buffer = new byte[nBytes];
-                if (nBytes > 0) {
-                    in.readFully(buffer, 0, nBytes);
-                    restoreSoftApConfiguration(buffer);
-                }
-            }
-
-            if (version >= FULL_BACKUP_ADDED_NET_POLICIES){
-                nBytes = in.readInt();
-                if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of network policies data");
-                if (nBytes > buffer.length) buffer = new byte[nBytes];
-                if (nBytes > 0) {
-                    in.readFully(buffer, 0, nBytes);
-                    restoreNetworkPolicies(buffer);
-                }
-            }
-
             if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete.");
         } else {
             data.close();
@@ -784,6 +730,11 @@
 
         try {
             int stateVersion = dataInput.readInt();
+            if (stateVersion > STATE_VERSION) {
+                // Constrain the maximum state version this backup agent
+                // can handle in case a newer or corrupt backup set existed
+                stateVersion = STATE_VERSION;
+            }
             for (int i = 0; i < STATE_SIZES[stateVersion]; i++) {
                 stateChecksums[i] = dataInput.readLong();
             }
@@ -808,7 +759,7 @@
     }
 
     private long writeIfChanged(long oldChecksum, String key, byte[] data,
-                                BackupDataOutput output) {
+            BackupDataOutput output) {
         CRC32 checkSummer = new CRC32();
         checkSummer.update(data);
         long newChecksum = checkSummer.getValue();
@@ -883,7 +834,7 @@
     }
 
     private void restoreSettings(BackupDataInput data, Uri contentUri,
-                                 HashSet<String> movedToGlobal) {
+            HashSet<String> movedToGlobal) {
         byte[] settings = new byte[data.getDataSize()];
         try {
             data.readEntityData(settings, 0, settings.length);
@@ -895,7 +846,7 @@
     }
 
     private void restoreSettings(byte[] settings, int bytes, Uri contentUri,
-                                 HashSet<String> movedToGlobal) {
+            HashSet<String> movedToGlobal) {
         if (DEBUG) {
             Log.i(TAG, "restoreSettings: " + contentUri);
         }
@@ -1214,30 +1165,6 @@
         }
     }
 
-    private byte[] getSoftAPConfiguration(){
-        WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
-        return WiFiConfigurationSerializer.marshalWifiConfig(wifiManager.getWifiApConfiguration());
-    }
-
-    private void restoreSoftApConfiguration(byte[] data){
-        WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
-        wifiManager.setWifiApConfiguration(WiFiConfigurationSerializer.unmarshalWifiConfig(data));
-    }
-
-    private byte[] getNetworkPolicies(){
-        NetworkPolicyManager networkPolicyManager =
-                (NetworkPolicyManager)getSystemService(NETWORK_POLICY_SERVICE);
-        return NetworkPolicySerializer
-                .marshalNetworkPolicies(networkPolicyManager.getNetworkPolicies());
-    }
-
-    private void restoreNetworkPolicies(byte[] data){
-        NetworkPolicyManager networkPolicyManager =
-                (NetworkPolicyManager)getSystemService(NETWORK_POLICY_SERVICE);
-        networkPolicyManager
-                .setNetworkPolicies(NetworkPolicySerializer.unmarshalNetworkPolicies(data));
-    }
-
     /**
      * Write an int in BigEndian into the byte array.
      * @param out byte array
@@ -1259,7 +1186,8 @@
     }
 
     private int readInt(byte[] in, int pos) {
-        int result =    ((in[pos    ] & 0xFF) << 24) |
+        int result =
+                ((in[pos    ] & 0xFF) << 24) |
                 ((in[pos + 1] & 0xFF) << 16) |
                 ((in[pos + 2] & 0xFF) <<  8) |
                 ((in[pos + 3] & 0xFF) <<  0);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/WiFiConfigurationSerializer.java b/packages/SettingsProvider/src/com/android/providers/settings/WiFiConfigurationSerializer.java
deleted file mode 100644
index 2317dbc..0000000
--- a/packages/SettingsProvider/src/com/android/providers/settings/WiFiConfigurationSerializer.java
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.providers.settings;
-
-import android.net.IpConfiguration;
-import android.net.LinkAddress;
-import android.net.ProxyInfo;
-import android.net.StaticIpConfiguration;
-import android.net.wifi.WifiConfiguration;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.util.BitSet;
-
-
-/**
- * Backup/Restore Serializer Class for com.android.net.wifi.WifiConfiguration
- */
-public class WiFiConfigurationSerializer {
-    private static final boolean DEBUG = false;
-    private static final String TAG = "WiFiConfigSerializer";
-
-    private static final int NULL = 0;
-    private static final int NOT_NULL = 1;
-    /**
-     * Current Version of the Serializer.
-     */
-    private static int STATE_VERSION = 1;
-
-    /**
-     * write the Network selecton status to Byte Array
-     */
-    private static void writeNetworkSelectionStatus(WifiConfiguration config, DataOutputStream dest)
-            throws IOException {
-        WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus();
-
-        dest.writeInt(status.getNetworkSelectionStatus());
-        dest.writeInt(status.getNetworkSelectionDisableReason());
-        for (int index = WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE;
-                index < WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX;
-                index++) {
-            dest.writeInt(status.getDisableReasonCounter(index));
-        }
-        dest.writeLong(status.getDisableTime());
-        writeString(dest, status.getNetworkSelectionBSSID());
-    }
-
-    /**
-     * Marshals a WifiConfig object into a byte-array.
-     *
-     * @param wifiConfig - WifiConfiguration to be Marshalled
-     * @return byte array
-     */
-
-    public static byte[] marshalWifiConfig(WifiConfiguration wifiConfig) {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        if(wifiConfig != null) {
-            DataOutputStream out = new DataOutputStream(baos);
-            try {
-                out.writeInt(STATE_VERSION);
-                out.writeInt(wifiConfig.networkId);
-                out.writeInt(wifiConfig.status);
-                writeNetworkSelectionStatus(wifiConfig, out);
-                writeString(out, wifiConfig.SSID);
-                writeString(out, wifiConfig.BSSID);
-                out.writeInt(wifiConfig.apBand);
-                out.writeInt(wifiConfig.apChannel);
-                writeString(out, wifiConfig.FQDN);
-                writeString(out, wifiConfig.providerFriendlyName);
-                out.writeInt(wifiConfig.roamingConsortiumIds.length);
-                for (long id : wifiConfig.roamingConsortiumIds) {
-                    out.writeLong(id);
-                }
-                writeString(out, wifiConfig.preSharedKey);
-                for (String wepKey : wifiConfig.wepKeys) {
-                    writeString(out, wepKey);
-                }
-                out.writeInt(wifiConfig.wepTxKeyIndex);
-                out.writeInt(wifiConfig.priority);
-                out.writeInt(wifiConfig.hiddenSSID ? 1 : 0);
-                out.writeInt(wifiConfig.requirePMF ? 1 : 0);
-                writeString(out, wifiConfig.updateIdentifier);
-
-                writeBitSet(out, wifiConfig.allowedKeyManagement);
-                writeBitSet(out, wifiConfig.allowedProtocols);
-                writeBitSet(out, wifiConfig.allowedAuthAlgorithms);
-                writeBitSet(out, wifiConfig.allowedPairwiseCiphers);
-                writeBitSet(out, wifiConfig.allowedGroupCiphers);
-
-
-                //IpConfiguration
-                writeIpConfiguration(out, wifiConfig.getIpConfiguration());
-
-                writeString(out, wifiConfig.dhcpServer);
-                writeString(out, wifiConfig.defaultGwMacAddress);
-                out.writeInt(wifiConfig.selfAdded ? 1 : 0);
-                out.writeInt(wifiConfig.didSelfAdd ? 1 : 0);
-                out.writeInt(wifiConfig.validatedInternetAccess ? 1 : 0);
-                out.writeInt(wifiConfig.ephemeral ? 1 : 0);
-                out.writeInt(wifiConfig.creatorUid);
-                out.writeInt(wifiConfig.lastConnectUid);
-                out.writeInt(wifiConfig.lastUpdateUid);
-                writeString(out, wifiConfig.creatorName);
-                writeString(out, wifiConfig.lastUpdateName);
-                out.writeLong(wifiConfig.lastConnectionFailure);
-                out.writeLong(wifiConfig.lastRoamingFailure);
-                out.writeInt(wifiConfig.lastRoamingFailureReason);
-                out.writeInt(wifiConfig.numScorerOverride);
-                out.writeInt(wifiConfig.numScorerOverrideAndSwitchedNetwork);
-                out.writeInt(wifiConfig.numAssociation);
-                out.writeInt(wifiConfig.numUserTriggeredWifiDisableLowRSSI);
-                out.writeInt(wifiConfig.numUserTriggeredWifiDisableBadRSSI);
-                out.writeInt(wifiConfig.numUserTriggeredWifiDisableNotHighRSSI);
-                out.writeInt(wifiConfig.numTicksAtLowRSSI);
-                out.writeInt(wifiConfig.numTicksAtBadRSSI);
-                out.writeInt(wifiConfig.numTicksAtNotHighRSSI);
-                out.writeInt(wifiConfig.numUserTriggeredJoinAttempts);
-                out.writeInt(wifiConfig.userApproved);
-                out.writeInt(wifiConfig.numNoInternetAccessReports);
-                out.writeInt(wifiConfig.noInternetAccessExpected ? 1 : 0);
-            } catch (IOException ioe) {
-                Log.e(TAG, "Failed to Convert WifiConfiguration to byte array", ioe);
-                baos.reset();
-            }
-        }
-        return baos.toByteArray();
-    }
-
-    /**
-     *
-     */
-    private static void readNetworkSelectionStatusFromByteArray(DataInputStream in,
-            WifiConfiguration config, int version) throws IOException {
-        WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus();
-        status.setNetworkSelectionStatus(in.readInt());
-        status.setNetworkSelectionDisableReason(in.readInt());
-        for (int index = WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE;
-                index < WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX;
-                index++) {
-            status.setDisableReasonCounter(index, in.readInt());
-        }
-        status.setDisableTime(in.readLong());
-        status.setNetworkSelectionBSSID(readString(in, version));
-    }
-
-    /**
-     * Unmarshals a byte array into a WifiConfig Object
-     *
-     * @param data - marshalled WifiConfig Object
-     * @return WifiConfiguration Object
-     */
-
-    public static WifiConfiguration unmarshalWifiConfig(byte[] data) {
-        if (data == null ||  data.length == 0) {
-            return null;
-        }
-        DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
-        WifiConfiguration config = new WifiConfiguration();
-        try {
-            int version = in.readInt();
-
-            config.networkId = in.readInt();
-            config.status = in.readInt();
-            readNetworkSelectionStatusFromByteArray(in, config, version);
-            config.SSID = readString(in, version);
-            config.BSSID = readString(in, version);
-            config.apBand = in.readInt();
-            config.apChannel = in.readInt();
-            config.FQDN = readString(in, version);
-            config.providerFriendlyName = readString(in, version);
-            int numRoamingConsortiumIds = in.readInt();
-            config.roamingConsortiumIds = new long[numRoamingConsortiumIds];
-            for (int i = 0; i < numRoamingConsortiumIds; i++) {
-                config.roamingConsortiumIds[i] = in.readLong();
-            }
-            config.preSharedKey = readString(in, version);
-            for (int i = 0; i < config.wepKeys.length; i++) {
-                config.wepKeys[i] = readString(in, version);
-            }
-            config.wepTxKeyIndex = in.readInt();
-            config.priority = in.readInt();
-            config.hiddenSSID = in.readInt() != 0;
-            config.requirePMF = in.readInt() != 0;
-            config.updateIdentifier = readString(in, version);
-
-            config.allowedKeyManagement = readBitSet(in, version);
-            config.allowedProtocols = readBitSet(in, version);
-            config.allowedAuthAlgorithms = readBitSet(in, version);
-            config.allowedPairwiseCiphers = readBitSet(in, version);
-            config.allowedGroupCiphers = readBitSet(in, version);
-
-            //Not backed-up because EnterpriseConfig involves
-            //Certificates which are device specific.
-            //config.enterpriseConfig = new WifiEnterpriseConfig();
-
-            config.setIpConfiguration(readIpConfiguration(in, version));
-
-
-            config.dhcpServer = readString(in, version);
-            config.defaultGwMacAddress = readString(in, version);
-            config.selfAdded = in.readInt() != 0;
-            config.didSelfAdd = in.readInt() != 0;
-            config.validatedInternetAccess = in.readInt() != 0;
-            config.ephemeral = in.readInt() != 0;
-            config.creatorUid = in.readInt();
-            config.lastConnectUid = in.readInt();
-            config.lastUpdateUid = in.readInt();
-            config.creatorName = readString(in, version);
-            config.lastUpdateName = readString(in, version);
-            config.lastConnectionFailure = in.readLong();
-            config.lastRoamingFailure = in.readLong();
-            config.lastRoamingFailureReason = in.readInt();
-            config.roamingFailureBlackListTimeMilli = in.readLong();
-            config.numScorerOverride = in.readInt();
-            config.numScorerOverrideAndSwitchedNetwork = in.readInt();
-            config.numAssociation = in.readInt();
-            config.numUserTriggeredWifiDisableLowRSSI = in.readInt();
-            config.numUserTriggeredWifiDisableBadRSSI = in.readInt();
-            config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt();
-            config.numTicksAtLowRSSI = in.readInt();
-            config.numTicksAtBadRSSI = in.readInt();
-            config.numTicksAtNotHighRSSI = in.readInt();
-            config.numUserTriggeredJoinAttempts = in.readInt();
-            config.userApproved = in.readInt();
-            config.numNoInternetAccessReports = in.readInt();
-            config.noInternetAccessExpected = in.readInt() != 0;
-        } catch (IOException ioe) {
-            Log.e(TAG, "Failed to convert byte array to WifiConfiguration object", ioe);
-            return null;
-        }
-        return config;
-    }
-
-    private static ProxyInfo readProxyInfo(DataInputStream in, int version) throws IOException {
-        int isNull = in.readByte();
-        if (isNull == NULL) return null;
-        String host = readString(in, version);
-        int port = in.readInt();
-        String exclusionList = readString(in, version);
-        return new ProxyInfo(host, port, exclusionList);
-    }
-
-    private static void writeProxyInfo(DataOutputStream out, ProxyInfo proxyInfo) throws IOException {
-        if (proxyInfo != null) {
-            out.writeByte(NOT_NULL);
-            writeString(out, proxyInfo.getHost());
-            out.writeInt(proxyInfo.getPort());
-            writeString(out, proxyInfo.getExclusionListAsString());
-        } else {
-            out.writeByte(NULL);
-        }
-    }
-
-    private static InetAddress readInetAddress(DataInputStream in, int version) throws IOException {
-        int isNull = in.readByte();
-        if (isNull == NULL) return null;
-        InetAddress address = null;
-        int addressLength = in.readInt();
-        if (addressLength < 1) return address;
-        byte[] addressBytes = new byte[addressLength];
-        in.read(addressBytes, 0, addressLength);
-        try {
-            address = InetAddress.getByAddress(addressBytes);
-        } catch (UnknownHostException unknownHostException) {
-            return null;
-        }
-        return address;
-    }
-
-    private static void writeInetAddress(DataOutputStream out, InetAddress address) throws IOException {
-        if (address.getAddress() != null) {
-            out.writeByte(NOT_NULL);
-            out.writeInt(address.getAddress().length);
-            out.write(address.getAddress(), 0, address.getAddress().length);
-        } else {
-            out.writeByte(NULL);
-        }
-    }
-
-    private static LinkAddress readLinkAddress(DataInputStream in, int version) throws IOException {
-        int isNull = in.readByte();
-        if (isNull == NULL) return null;
-        InetAddress address = readInetAddress(in, version);
-        int prefixLength = in.readInt();
-        int flags = in.readInt();
-        int scope = in.readInt();
-        return new LinkAddress(address, prefixLength, flags, scope);
-    }
-
-    private static void writeLinkAddress(DataOutputStream out, LinkAddress address) throws IOException {
-        if (address != null) {
-            out.writeByte(NOT_NULL);
-            writeInetAddress(out, address.getAddress());
-            out.writeInt(address.getPrefixLength());
-            out.writeInt(address.getFlags());
-            out.writeInt(address.getScope());
-        } else {
-            out.writeByte(NULL);
-        }
-    }
-
-    private static StaticIpConfiguration readStaticIpConfiguration(DataInputStream in, int version) throws IOException {
-        int isNull = in.readByte();
-        if (isNull == NULL) return null;
-        StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
-        staticIpConfiguration.ipAddress = readLinkAddress(in, version);
-        staticIpConfiguration.gateway = readInetAddress(in, version);
-        int dnsServersLength = in.readInt();
-        for (int i = 0; i < dnsServersLength; i++) {
-            staticIpConfiguration.dnsServers.add(readInetAddress(in, version));
-        }
-        staticIpConfiguration.domains = readString(in, version);
-        return staticIpConfiguration;
-    }
-
-    private static void writeStaticIpConfiguration(DataOutputStream out, StaticIpConfiguration staticIpConfiguration) throws IOException {
-        if (staticIpConfiguration != null) {
-            out.writeByte(NOT_NULL);
-            writeLinkAddress(out, staticIpConfiguration.ipAddress);
-            writeInetAddress(out, staticIpConfiguration.gateway);
-            out.writeInt(staticIpConfiguration.dnsServers.size());
-            for (InetAddress inetAddress : staticIpConfiguration.dnsServers) {
-                writeInetAddress(out, inetAddress);
-            }
-            writeString(out, staticIpConfiguration.domains);
-        } else {
-            out.writeByte(NULL);
-        }
-    }
-
-    private static IpConfiguration readIpConfiguration(DataInputStream in, int version) throws IOException {
-        int isNull = in.readByte();
-        if (isNull == NULL) return null;
-        IpConfiguration ipConfiguration = new IpConfiguration();
-        String tmp = readString(in, version);
-        ipConfiguration.ipAssignment = tmp == null ? null : IpConfiguration.IpAssignment.valueOf(tmp);
-        tmp = readString(in, version);
-        ipConfiguration.proxySettings = tmp == null ? null : IpConfiguration.ProxySettings.valueOf(tmp);
-        ipConfiguration.staticIpConfiguration = readStaticIpConfiguration(in, version);
-        ipConfiguration.httpProxy = readProxyInfo(in, version);
-        return ipConfiguration;
-    }
-
-
-    private static void writeIpConfiguration(DataOutputStream out, IpConfiguration ipConfiguration) throws IOException {
-        if (ipConfiguration != null) {
-            out.writeByte(NOT_NULL);
-            writeString(out, ipConfiguration.ipAssignment != null ? ipConfiguration.ipAssignment.name() : null);
-            writeString(out, ipConfiguration.proxySettings != null ? ipConfiguration.proxySettings.name() : null);
-            writeStaticIpConfiguration(out, ipConfiguration.staticIpConfiguration);
-            writeProxyInfo(out, ipConfiguration.httpProxy);
-        } else {
-            out.writeByte(NULL);
-        }
-
-    }
-
-    private static String readString(DataInputStream in, int version) throws IOException {
-        byte isNull = in.readByte();
-        if (isNull == NOT_NULL) {
-            return in.readUTF();
-        }
-        return null;
-    }
-
-    private static void writeString(DataOutputStream out, String val) throws IOException {
-        if (val != null) {
-            out.writeByte(NOT_NULL);
-            out.writeUTF(val);
-        } else {
-            out.writeByte(NULL);
-        }
-    }
-
-    private static BitSet readBitSet(DataInputStream in, int version) throws IOException {
-        byte isNull = in.readByte();
-        if (isNull == NOT_NULL) {
-            int length = in.readInt();
-            byte[] bytes = new byte[length];
-            in.read(bytes, 0, length);
-            return BitSet.valueOf(bytes);
-        }
-        return new BitSet();
-    }
-
-    private static void writeBitSet(DataOutputStream out, BitSet val) throws IOException {
-        if (val != null) {
-            out.writeByte(NOT_NULL);
-            byte[] byteArray = val.toByteArray();
-            out.writeInt(byteArray.length);
-            out.write(byteArray);
-        } else {
-            out.writeByte(NULL);
-        }
-    }
-}
diff --git a/packages/SettingsProvider/test/Android.mk b/packages/SettingsProvider/test/Android.mk
index f278967..ef863e7 100644
--- a/packages/SettingsProvider/test/Android.mk
+++ b/packages/SettingsProvider/test/Android.mk
@@ -5,10 +5,7 @@
 # Note we statically link SettingsState to do some unit tests.  It's not accessible otherwise
 # because this test is not an instrumentation test. (because the target runs in the system process.)
 LOCAL_SRC_FILES := $(call all-subdir-java-files) \
-    ../src/com/android/providers/settings/SettingsState.java \
-    ../src/com/android/providers/settings/WiFiConfigurationSerializer.java \
-    ../src/com/android/providers/settings/NetworkPolicySerializer.java
-
+    ../src/com/android/providers/settings/SettingsState.java
 
 LOCAL_PACKAGE_NAME := SettingsProviderTest
 
@@ -16,4 +13,4 @@
 
 LOCAL_CERTIFICATE := platform
 
-include $(BUILD_PACKAGE)
+include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/NetworkPolicySerializerTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/NetworkPolicySerializerTest.java
deleted file mode 100644
index 1986596..0000000
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/NetworkPolicySerializerTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.android.providers.settings;
-
-import android.net.NetworkPolicy;
-import android.net.NetworkTemplate;
-import android.test.AndroidTestCase;
-
-import java.util.Random;
-
-/**
- * Tests for NetworkPolicySerializer
- */
-public class NetworkPolicySerializerTest extends AndroidTestCase {
-    static Random sRandom = new Random();
-
-    public void testMarshallAndUnmarshalNetworkPolicy() {
-        NetworkPolicy policy = getDummyNetworkPolicy();
-        byte[] data = NetworkPolicySerializer.marshalNetworkPolicy(policy);
-        assertNotNull("Got Null data from marshal", data);
-        assertFalse("Got back an empty byte[] from marshal", data.length == 0);
-
-        NetworkPolicy unmarshaled = NetworkPolicySerializer.unmarshalNetworkPolicy(data);
-        assertNotNull("Got Null data from unmarshaled", unmarshaled);
-        assertTrue("NetworkPolicy Marshall and Unmarshal Failed!", policy.equals(unmarshaled));
-    }
-
-    public void testMarshallNetworkPolicyEdgeCases() {
-        byte[] data = NetworkPolicySerializer.marshalNetworkPolicy(null);
-        assertNotNull("NetworkPolicy marshal returned null. Expected: byte[0]", data);
-        assertEquals("NetworkPolicy marshal returned incomplete byte array. Expected: byte[0]",
-                data.length, 0);
-    }
-
-    public void testUnmarshallNetworkPolicyEdgeCases() {
-        NetworkPolicy policy = NetworkPolicySerializer.unmarshalNetworkPolicy(null);
-        assertNull("Non null NetworkPolicy returned for null byte[] input", policy);
-
-        policy = NetworkPolicySerializer.unmarshalNetworkPolicy(new byte[0]);
-        assertNull("Non null NetworkPolicy returned for empty byte[] input", policy);
-
-        policy = NetworkPolicySerializer.unmarshalNetworkPolicy(new byte[]{10, 20, 30, 40, 50, 60});
-        assertNull("Non null NetworkPolicy returned for incomplete byte[] input", policy);
-    }
-
-    public void testMarshallAndUnmarshalNetworkPolicies() {
-        NetworkPolicy[] policies = getDummyNetworkPolicies(5);
-        byte[] data = NetworkPolicySerializer.marshalNetworkPolicies(policies);
-        assertNotNull("Got Null data from marshal", data);
-        assertFalse("Got back an empty byte[] from marshal", data.length == 0);
-
-        NetworkPolicy[] unmarshaled = NetworkPolicySerializer.unmarshalNetworkPolicies(data);
-        assertNotNull("Got Null data from unmarshaled", unmarshaled);
-        try {
-            for (int i = 0; i < policies.length; i++) {
-                assertTrue("NetworkPolicies Marshall and Unmarshal Failed!",
-                        policies[i].equals(unmarshaled[i]));
-            }
-        } catch (NullPointerException npe) {
-            assertTrue("Some policies were not marshaled/unmarshaled correctly", false);
-        }
-    }
-
-    public void testMarshallNetworkPoliciesEdgeCases() {
-        byte[] data = NetworkPolicySerializer.marshalNetworkPolicies(null);
-        assertNotNull("NetworkPolicies marshal returned null!", data);
-        assertEquals("NetworkPolicies marshal returned incomplete byte array", data.length, 0);
-
-        data = NetworkPolicySerializer.marshalNetworkPolicies(new NetworkPolicy[0]);
-        assertNotNull("NetworkPolicies marshal returned null for empty NetworkPolicy[]", data);
-        assertEquals("NetworkPolicies marshal returned incomplete byte array for empty NetworkPolicy[]"
-                , data.length, 0);
-    }
-
-    public void testUnmarshalNetworkPoliciesEdgeCases() {
-        NetworkPolicy[] policies = NetworkPolicySerializer.unmarshalNetworkPolicies(null);
-        assertNotNull("NetworkPolicies unmarshal returned null for null input. Expected: byte[0] ",
-                policies);
-        assertEquals("Non Empty NetworkPolicy[] returned for null input Expected: byte[0]",
-                policies.length, 0);
-
-        policies = NetworkPolicySerializer.unmarshalNetworkPolicies(new byte[0]);
-        assertNotNull("NetworkPolicies unmarshal returned null for empty byte[] input. Expected: byte[0]",
-                policies);
-        assertEquals("Non Empty NetworkPolicy[] returned for empty byte[] input. Expected: byte[0]",
-                policies.length, 0);
-
-        policies = NetworkPolicySerializer.unmarshalNetworkPolicies(new byte[]{10, 20, 30, 40, 50, 60});
-        assertNotNull("NetworkPolicies unmarshal returned null for incomplete byte[] input. " +
-                "Expected: byte[0] ", policies);
-        assertEquals("Non Empty NetworkPolicy[] returned for incomplete byte[] input Expected: byte[0]",
-                policies.length, 0);
-
-    }
-
-    private NetworkPolicy[] getDummyNetworkPolicies(int num) {
-        NetworkPolicy[] policies = new NetworkPolicy[num];
-        for (int i = 0; i < num; i++) {
-            policies[i] = getDummyNetworkPolicy();
-        }
-        return policies;
-    }
-
-    private NetworkPolicy getDummyNetworkPolicy() {
-        NetworkTemplate template = new NetworkTemplate(NetworkTemplate.MATCH_MOBILE_ALL, "subId",
-                "GoogleGuest");
-        int cycleDay = sRandom.nextInt();
-        String cycleTimezone = "timezone";
-        long warningBytes = sRandom.nextLong();
-        long limitBytes = sRandom.nextLong();
-        long lastWarningSnooze = sRandom.nextLong();
-        long lastLimitSnooze = sRandom.nextLong();
-        boolean metered = sRandom.nextInt() % 2 == 0;
-        boolean inferred = sRandom.nextInt() % 2 == 0;
-        return new NetworkPolicy(template, cycleDay, cycleTimezone, warningBytes, limitBytes,
-                lastWarningSnooze, lastLimitSnooze, metered, inferred);
-    }
-
-}
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index a93caca..78197b3 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -286,7 +286,7 @@
             // At this point it's handling onStartCommand(), with the intent passed as an Extra.
             if (!(msg.obj instanceof Intent)) {
                 // Sanity check.
-                Log.e(TAG, "Internal error: invalid msg.obj: " + msg.obj);
+                Log.wtf(TAG, "handleMessage(): invalid msg.obj type: " + msg.obj);
                 return;
             }
             final Parcelable parcel = ((Intent) msg.obj).getParcelableExtra(EXTRA_ORIGINAL_INTENT);
@@ -520,8 +520,14 @@
         }
         int activeProcesses = 0;
         for (int i = 0; i < total; i++) {
-            final int pid = mProcesses.keyAt(i);
             final BugreportInfo info = mProcesses.valueAt(i);
+            if (info == null) {
+                Log.wtf(TAG, "pollProgress(): null info at index " + i + "(pid = "
+                        + mProcesses.keyAt(i) + ")");
+                continue;
+            }
+
+            final int pid = info.pid;
             if (info.finished) {
                 if (DEBUG) Log.v(TAG, "Skipping finished process " + pid);
                 continue;
@@ -720,6 +726,12 @@
      * Handles the BUGREPORT_FINISHED intent sent by {@code dumpstate}.
      */
     private void onBugreportFinished(int pid, Intent intent) {
+        final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
+        if (bugreportFile == null) {
+            // Should never happen, dumpstate always set the file.
+            Log.wtf(TAG, "Missing " + EXTRA_BUGREPORT + " on intent " + intent);
+            return;
+        }
         mInfoDialog.onBugreportFinished(pid);
         BugreportInfo info = getInfo(pid);
         if (info == null) {
@@ -729,7 +741,8 @@
             mProcesses.put(pid, info);
         }
         info.renameScreenshots(mScreenshotsDir);
-        info.bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
+        info.bugreportFile = bugreportFile;
+
         final File screenshot = getFileExtra(intent, EXTRA_SCREENSHOT);
         if (screenshot != null) {
             info.addScreenshot(screenshot);
@@ -957,7 +970,7 @@
     private static void addDetailsToZipFile(Context context, BugreportInfo info) {
         if (info.bugreportFile == null) {
             // One possible reason is a bug in the Parcelization code.
-            Log.e(TAG, "INTERNAL ERROR: no bugreportFile on " + info);
+            Log.wtf(TAG, "addDetailsToZipFile(): no bugreportFile on " + info);
             return;
         }
         if (TextUtils.isEmpty(info.title) && TextUtils.isEmpty(info.description)) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 2713fb5..c74e411 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -349,6 +349,12 @@
             android:resizeable="true"
             android:supportsPictureInPicture="true"
             android:excludeFromRecents="true" />
+        <activity
+            android:name="com.android.systemui.tv.pip.PipOnboardingActivity"
+            android:exported="true"
+            android:theme="@style/PipTheme"
+            android:launchMode="singleTop"
+            android:excludeFromRecents="true" />
 
         <!-- platform logo easter egg activity -->
         <activity
diff --git a/packages/SystemUI/res/anim/recents_from_app_enter.xml b/packages/SystemUI/res/anim/recents_from_app_enter.xml
deleted file mode 100644
index 10ddce6..0000000
--- a/packages/SystemUI/res/anim/recents_from_app_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<!-- Recents Activity -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false"
-     android:zAdjustment="top">
-  <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
-         android:fillEnabled="true"
-         android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/fast_out_slow_in"
-         android:duration="0"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recents_from_app_exit.xml b/packages/SystemUI/res/anim/recents_from_app_exit.xml
deleted file mode 100644
index c98ecf4..0000000
--- a/packages/SystemUI/res/anim/recents_from_app_exit.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<!-- Incoming Activity -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false"
-     android:zAdjustment="normal">
-
-    <!-- Animate the view out only after recents is visible -->
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-           android:fillEnabled="true"
-           android:fillBefore="true" android:fillAfter="true"
-           android:interpolator="@android:interpolator/fast_out_slow_in"
-           android:duration="1"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
index b191e62..00b3dfd 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
@@ -23,6 +23,6 @@
   <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/linear"
+         android:interpolator="@android:interpolator/linear_out_slow_in"
          android:duration="150"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
index fa6caf2..33831b8 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
@@ -23,6 +23,6 @@
   <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/linear_out_slow_in"
-         android:duration="150"/>
+         android:interpolator="@interpolator/recents_from_launcher_exit_interpolator"
+         android:duration="133"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
index e0e2fc8..23cedf8 100644
--- a/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
@@ -23,6 +23,6 @@
   <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/linear_out_slow_in"
-         android:duration="@integer/recents_enter_from_home_transition_duration"/>
+         android:interpolator="@interpolator/recents_from_launcher_exit_interpolator"
+         android:duration="133"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
deleted file mode 100644
index 1135bc0..0000000
--- a/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false"
-     android:zAdjustment="normal">
-  <!--scale android:fromXScale="2.0" android:toXScale="1.0"
-         android:fromYScale="2.0" android:toYScale="1.0"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:fillEnabled="true"
-         android:fillBefore="true" android:fillAfter="true"
-         android:pivotX="50%p" android:pivotY="50%p"
-         android:duration="250" /-->
-</set>
diff --git a/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
deleted file mode 100644
index fa28cf4..0000000
--- a/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false"
-     android:zAdjustment="top">
-  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-         android:fillEnabled="true"
-         android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:duration="250"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recents_return_to_launcher_exit.xml b/packages/SystemUI/res/anim/recents_return_to_launcher_exit.xml
deleted file mode 100644
index e95e667..0000000
--- a/packages/SystemUI/res/anim/recents_return_to_launcher_exit.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false"
-     android:zAdjustment="normal">
-  <!--scale android:fromXScale="1.0" android:toXScale="2.0"
-         android:fromYScale="1.0" android:toYScale="2.0"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:pivotX="50%p" android:pivotY="50%p"
-         android:duration="250" /-->
-  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:duration="250"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
index b191e62..544ec88 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
@@ -23,6 +23,6 @@
   <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/linear"
-         android:duration="150"/>
+         android:interpolator="@interpolator/recents_to_launcher_enter_interpolator"
+         android:duration="133"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
index fa6caf2..226edb8 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
@@ -24,5 +24,5 @@
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
          android:interpolator="@android:interpolator/linear_out_slow_in"
-         android:duration="150"/>
+         android:duration="1"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
index ea82835..657b216 100644
--- a/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
@@ -23,6 +23,6 @@
   <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/linear"
-         android:duration="100"/>
+         android:interpolator="@interpolator/recents_to_launcher_enter_interpolator"
+         android:duration="133"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
index a8bdc8e..5182cab2 100644
--- a/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
@@ -24,5 +24,5 @@
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
          android:interpolator="@android:interpolator/linear"
-         android:duration="100"/>
+         android:duration="1"/>
 </set>
diff --git a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml
deleted file mode 100644
index 73ae9f2..0000000
--- a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:detachWallpaper="true"
-     android:shareInterpolator="false"
-     android:zAdjustment="normal">
-  <!--scale android:fromXScale="2.0" android:toXScale="1.0"
-         android:fromYScale="2.0" android:toYScale="1.0"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:fillEnabled="true"
-         android:fillBefore="true" android:fillAfter="true"
-         android:pivotX="50%p" android:pivotY="50%p"
-         android:duration="250" /-->
-  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-         android:fillEnabled="true"
-         android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:duration="250"/>
-</set>
diff --git a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml
deleted file mode 100644
index 7e257d9..0000000
--- a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:detachWallpaper="true"
-     android:shareInterpolator="false"
-     android:zAdjustment="top">
-  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-         android:fillEnabled="true"
-         android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:duration="250"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recents_return_to_launcher_enter.xml b/packages/SystemUI/res/interpolator/recents_from_launcher_exit_interpolator.xml
similarity index 62%
rename from packages/SystemUI/res/anim/recents_return_to_launcher_enter.xml
rename to packages/SystemUI/res/interpolator/recents_from_launcher_exit_interpolator.xml
index efa9019..4a7fff6 100644
--- a/packages/SystemUI/res/anim/recents_return_to_launcher_enter.xml
+++ b/packages/SystemUI/res/interpolator/recents_from_launcher_exit_interpolator.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
 /*
-** Copyright 2012, The Android Open Source Project
+** Copyright 2014, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -16,11 +16,8 @@
 ** limitations under the License.
 */
 -->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false"
-     android:zAdjustment="normal">
-  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:duration="250"/>
-</set>
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0"
+    android:controlY1="0"
+    android:controlX2="0.8"
+    android:controlY2="1" />
diff --git a/packages/SystemUI/res/anim/recents_return_to_launcher_enter.xml b/packages/SystemUI/res/interpolator/recents_to_launcher_enter_interpolator.xml
similarity index 62%
copy from packages/SystemUI/res/anim/recents_return_to_launcher_enter.xml
copy to packages/SystemUI/res/interpolator/recents_to_launcher_enter_interpolator.xml
index efa9019..c61dfd8 100644
--- a/packages/SystemUI/res/anim/recents_return_to_launcher_enter.xml
+++ b/packages/SystemUI/res/interpolator/recents_to_launcher_enter_interpolator.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
 /*
-** Copyright 2012, The Android Open Source Project
+** Copyright 2014, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -16,11 +16,8 @@
 ** limitations under the License.
 */
 -->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:shareInterpolator="false"
-     android:zAdjustment="normal">
-  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:duration="250"/>
-</set>
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.4"
+    android:controlY1="0"
+    android:controlX2="1"
+    android:controlY2="1" />
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_category_separator.xml
similarity index 66%
rename from packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml
rename to packages/SystemUI/res/layout/keyboard_shortcuts_category_separator.xml
index 802acfe..778ef8f 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_category_separator.xml
@@ -15,8 +15,11 @@
   ~ limitations under the License
   -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content">
-</LinearLayout>
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="1dp"
+    android:layout_marginStart="24dp"
+    android:layout_marginTop="8dp"
+    android:layout_marginEnd="0dp"
+    android:layout_marginBottom="20dp"
+    android:background="?android:attr/dividerHorizontal" />
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml
index fa07eb1..7ca3b95 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml
@@ -16,7 +16,7 @@
   -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="horizontal"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content">
-</LinearLayout>
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" />
+
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
index 77b1264..f73ee15 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
@@ -14,25 +14,35 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<LinearLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/keyboard_shortcuts_wrapper"
-        android:layout_width="488dp"
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="488dp"
+    android:layout_height="wrap_content">
+    <LinearLayout
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:focusable="true">
-    <ScrollView
+        android:orientation="vertical">
+        <ScrollView
             android:id="@+id/keyboard_shortcuts_scroll_view"
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            android:layout_weight="1">
-        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+            <LinearLayout
                 android:id="@+id/keyboard_shortcuts_container"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:orientation="vertical"/>
-    </ScrollView>
-    <View
+        </ScrollView>
+        <!-- Required for stretching to full available height when the items in the scroll view
+             occupy less space then the full height -->
+        <View
             android:layout_width="match_parent"
-            android:layout_height="1dp"
-            android:background="?android:attr/listDivider"/>
-</LinearLayout>
+            android:layout_height="0dp"
+            android:layout_weight="1"/>
+    </LinearLayout>
+    <View
+        android:layout_gravity="bottom"
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="?android:attr/dividerHorizontal"/>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/qs_add_tile_layout.xml b/packages/SystemUI/res/layout/qs_add_tile_layout.xml
deleted file mode 100644
index 962b00e..0000000
--- a/packages/SystemUI/res/layout/qs_add_tile_layout.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="wrap_content"
-    android:layout_width="wrap_content"
-    android:paddingTop="20dp"
-    android:paddingStart="7dp"
-    android:paddingEnd="7dp">
-    <LinearLayout
-        android:layout_height="wrap_content"
-        android:layout_width="80dp"
-        android:orientation="vertical">
-        <ImageView
-            android:id="@+id/tile_icon"
-            android:layout_gravity="center"
-            android:layout_width="@dimen/qs_tile_icon_size"
-            android:layout_height="@dimen/qs_tile_icon_size" />
-        <TextView
-            android:id="@+id/tile_label"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center|bottom"
-            android:paddingTop="10dp"
-            android:gravity="center"
-            android:textSize="@dimen/qs_tile_text_size" />
-    </LinearLayout>
-</FrameLayout>
diff --git a/packages/SystemUI/res/layout/qs_customize_layout.xml b/packages/SystemUI/res/layout/qs_customize_divider.xml
similarity index 63%
rename from packages/SystemUI/res/layout/qs_customize_layout.xml
rename to packages/SystemUI/res/layout/qs_customize_divider.xml
index 0b8e02f..71ad85b 100644
--- a/packages/SystemUI/res/layout/qs_customize_layout.xml
+++ b/packages/SystemUI/res/layout/qs_customize_divider.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-     Copyright (C) 2015 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,18 +14,16 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.systemui.qs.customize.NonPagedTileLayout
+
+<TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/tiles_container"
+    android:id="@android:id/title"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-    <view
-        class="com.android.systemui.qs.PagedTileLayout$TilePage"
-        android:id="@+id/tile_page"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
-</com.android.systemui.qs.customize.NonPagedTileLayout>
-
+    android:paddingTop="20dp"
+    android:paddingStart="16dp"
+    android:paddingEnd="8dp"
+    android:paddingBottom="13dp"
+    android:textAppearance="@android:style/TextAppearance.Material.Body2"
+    android:textColor="?android:attr/colorAccent"
+    android:text="@string/drag_to_add_tiles" />
diff --git a/packages/SystemUI/res/layout/qs_customize_panel.xml b/packages/SystemUI/res/layout/qs_customize_panel.xml
index e56431b..73a92d9 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel.xml
@@ -22,85 +22,53 @@
     android:background="@drawable/qs_customizer_background"
     android:gravity="center_horizontal">
 
-    <FrameLayout
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:background="@drawable/notification_header_bg">
+        android:paddingTop="28dp"
+        android:paddingEnd="8dp">
 
-        <LinearLayout
-            android:id="@+id/drag_buttons"
-            android:layout_width="match_parent"
-            android:layout_height="fill_parent"
-            android:orientation="horizontal">
-            <FrameLayout
-                android:layout_width="0dp"
-                android:layout_height="fill_parent"
-                android:layout_weight="1">
-                <com.android.systemui.qs.customize.DropButton
-                    android:id="@+id/info_button"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:gravity="center"
-                    android:drawableStart="@drawable/ic_info"
-                    android:drawablePadding="10dp"
-                    android:textAppearance="?android:attr/textAppearanceMedium"
-                    android:textColor="@android:color/white"
-                    android:text="@string/qs_customize_info" />
-            </FrameLayout>
-            <FrameLayout
-                android:layout_width="0dp"
-                android:layout_height="fill_parent"
-                android:layout_weight="1">
-                <com.android.systemui.qs.customize.DropButton
-                    android:id="@+id/remove_button"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:gravity="center"
-                    android:drawableStart="@drawable/ic_close_white"
-                    android:drawablePadding="10dp"
-                    android:textAppearance="?android:attr/textAppearanceMedium"
-                    android:textColor="@android:color/white"
-                    android:text="@string/qs_customize_remove" />
-            </FrameLayout>
-        </LinearLayout>
+        <ImageView
+            android:id="@+id/close"
+            android:layout_width="56dp"
+            android:layout_height="56dp"
+            android:padding="16dp"
+            android:src="@drawable/ic_close_white" />
 
-        <Toolbar
-            android:id="@*android:id/action_bar"
-            android:layout_width="match_parent"
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
+
+        <Button
+            android:id="@+id/save"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:navigationContentDescription="@*android:string/action_bar_up_description"
-            android:background="@drawable/notification_header_bg"
-            style="?android:attr/toolbarStyle" />
-    </FrameLayout>
+            android:paddingStart="12dp"
+            android:paddingEnd="12dp"
+            android:background="?android:attr/selectableItemBackground"
+            android:textAppearance="@android:style/TextAppearance.Material.Widget.Button.Inverse"
+            android:textColor="?android:attr/colorAccent"
+            android:text="@string/save" />
 
-    <com.android.systemui.tuner.AutoScrollView
+        <Button
+            android:id="@+id/reset"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingStart="12dp"
+            android:paddingEnd="12dp"
+            android:background="?android:attr/selectableItemBackground"
+            android:textAppearance="@android:style/TextAppearance.Material.Widget.Button.Inverse"
+            android:textColor="?android:attr/colorAccent"
+            android:text="@*android:string/reset" />
+
+    </LinearLayout>
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@android:id/list"
         android:layout_width="@dimen/notification_panel_width"
         android:layout_height="0dp"
-        android:layout_weight="1"
-        android:paddingTop="12dp"
-        android:paddingBottom="8dp"
-        android:elevation="2dp">
-
-        <com.android.systemui.qs.customize.CustomQSPanel
-            android:id="@+id/quick_settings_panel"
-            android:background="#0000"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-
-    </com.android.systemui.tuner.AutoScrollView>
-
-    <com.android.systemui.qs.customize.FloatingActionButton
-        android:id="@+id/fab"
-        android:clickable="true"
-        android:layout_width="@dimen/fab_size"
-        android:layout_height="@dimen/fab_size"
-        android:layout_gravity="bottom|end"
-        android:layout_marginEnd="@dimen/fab_margin"
-        android:layout_marginBottom="@dimen/fab_margin"
-        android:elevation="@dimen/fab_elevation"
-        android:background="@drawable/fab_background" />
+        android:layout_weight="1" />
 
     <View
         android:layout_width="match_parent"
diff --git a/packages/PrintSpooler/res/color/item_text_color.xml b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml
similarity index 65%
copy from packages/PrintSpooler/res/color/item_text_color.xml
copy to packages/SystemUI/res/layout/qs_customize_tile_frame.xml
index f580fbd..aaa84fd 100644
--- a/packages/PrintSpooler/res/color/item_text_color.xml
+++ b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!--
+     Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,7 +15,10 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-   <item android:state_enabled="true" android:color="#333333" />
-   <item android:color="#888888"/>
-</selector>
\ No newline at end of file
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="wrap_content"
+    android:layout_width="wrap_content"
+    android:paddingStart="8dp"
+    android:paddingEnd="8dp"
+    android:paddingBottom="16dp" />
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index 5a96dc3..153e35f 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -18,10 +18,20 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_alignParentBottom="true"
-    android:padding="@dimen/qs_panel_padding"
+    android:paddingEnd="@dimen/qs_panel_padding"
     android:visibility="invisible"
-    android:background="@drawable/btn_borderless_rect" >
+    android:background="@drawable/btn_borderless_rect"
+    android:gravity="center">
+
+    <ImageView
+        android:id="@*android:id/up"
+        android:layout_width="56dp"
+        android:layout_height="56dp"
+        android:layout_marginEnd="16dp"
+        android:padding="16dp"
+        android:clickable="true"
+        android:background="?android:attr/selectableItemBackground"
+        android:src="?android:attr/homeAsUpIndicator" />
 
     <TextView
         android:id="@android:id/title"
@@ -37,4 +47,4 @@
         android:clickable="false"
         android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
 
-</com.android.keyguard.AlphaOptimizedLinearLayout>
\ No newline at end of file
+</com.android.keyguard.AlphaOptimizedLinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
index ccdddf7..5bb4f5d 100644
--- a/packages/SystemUI/res/layout/qs_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -28,7 +28,7 @@
         android:id="@android:id/icon"
         android:layout_width="24dp"
         android:layout_height="24dp"
-        android:layout_marginEnd="12dp" />
+        android:layout_marginEnd="20dp" />
 
     <LinearLayout
         android:layout_width="0dp"
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index 0bef513..5fde4f6 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -15,6 +15,7 @@
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_height="48dp"
     android:paddingLeft="16dp"
     android:paddingRight="16dp"
     style="@style/BrightnessDialogContainer">
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 6784695..07ac6a5 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -106,7 +106,7 @@
     <LinearLayout
         android:id="@+id/date_time_group"
         android:layout_width="wrap_content"
-        android:layout_height="28dp"
+        android:layout_height="25dp"
         android:layout_alignParentStart="true"
         android:layout_alignParentTop="true"
         android:orientation="horizontal">
@@ -115,7 +115,7 @@
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_marginStart="16dp"
-            android:layout_marginTop="2dp"
+            android:layout_marginTop="4dp"
             android:id="@+id/clock" />
 
         <com.android.systemui.statusbar.policy.DateView
@@ -123,7 +123,7 @@
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_marginStart="6dp"
-            android:layout_marginTop="8dp"
+            android:layout_marginTop="4dp"
             android:drawableStart="@drawable/header_dot"
             android:drawablePadding="6dp"
             android:singleLine="true"
@@ -136,7 +136,7 @@
             android:id="@+id/alarm_status"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_marginTop="8dp"
+            android:layout_marginTop="4dp"
             android:drawablePadding="6dp"
             android:drawableStart="@drawable/ic_access_alarms_small"
             android:textColor="#64ffffff"
@@ -152,9 +152,9 @@
         android:background="#0000"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="30dp"
-        android:layout_marginStart="8dp"
-        android:layout_marginEnd="8dp"
+        android:layout_marginTop="25dp"
+        android:layout_marginStart="12dp"
+        android:layout_marginEnd="12dp"
         android:layout_alignParentEnd="true"
         android:clipChildren="false"
         android:clipToPadding="false" />
@@ -164,7 +164,7 @@
         layout="@layout/qs_detail_header"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
+        android:layout_marginTop="28dp"
         />
 
     <com.android.systemui.statusbar.AlphaOptimizedImageView
diff --git a/packages/SystemUI/res/layout/status_bar_no_notifications.xml b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
index dd501d4..6f87184 100644
--- a/packages/SystemUI/res/layout/status_bar_no_notifications.xml
+++ b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
@@ -25,9 +25,9 @@
             android:id="@+id/no_notifications"
             android:layout_width="match_parent"
             android:layout_height="64dp"
-            android:paddingTop="12dp"
+            android:paddingTop="28dp"
             android:gravity="top|center_horizontal"
-            android:textColor="#ffffff"
-            android:textSize="20sp"
+            android:textColor="#e6ffffff"
+            android:textSize="16sp"
             android:text="@string/empty_shade_text"/>
 </com.android.systemui.statusbar.EmptyShadeView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
index dc7577a..efb273f 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
@@ -19,15 +19,16 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:visibility="gone"
-        android:clipChildren="false"
-        android:clipToPadding="false">
+        android:paddingEnd="8dp"
+        android:visibility="gone">
     <com.android.systemui.statusbar.DismissViewButton
+            style="@android:style/Widget.Material.Button.Borderless"
             android:id="@+id/dismiss_text"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
             android:layout_gravity="end"
             android:focusable="true"
-            android:background="@drawable/ripple_drawable"
-            android:contentDescription="@string/accessibility_clear_all"/>
+            android:contentDescription="@string/accessibility_clear_all"
+            android:text="@string/clear_all_notifications_text"
+            android:textAllCaps="true"/>
 </com.android.systemui.statusbar.DismissView>
diff --git a/packages/SystemUI/res/layout/tv_pip_menu.xml b/packages/SystemUI/res/layout/tv_pip_menu.xml
index a638d17..3562c64 100644
--- a/packages/SystemUI/res/layout/tv_pip_menu.xml
+++ b/packages/SystemUI/res/layout/tv_pip_menu.xml
@@ -17,45 +17,37 @@
 */
 -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <FrameLayout
-        android:layout_alignParentEnd="true"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:paddingStart="10dp"
-        android:paddingEnd="10dp"
-        android:background="#88FFFFFF">
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_gravity="center_vertical"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" >
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:layout_gravity="end"
+    android:paddingStart="10dp"
+    android:paddingEnd="10dp"
+    android:background="#88FFFFFF"
+    android:gravity="center_vertical" >
 
-            <Button android:id="@+id/full"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:text="@string/pip_fullscreen"
-                android:textSize="10sp"
-                android:focusable="true" />
+    <Button android:id="@+id/full"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:text="@string/pip_fullscreen"
+        android:textSize="10sp"
+        android:focusable="true" />
 
-            <Button android:id="@+id/exit"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:text="@string/pip_exit"
-                android:textSize="10sp"
-                android:focusable="true" />
+    <Button android:id="@+id/exit"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:text="@string/pip_exit"
+        android:textSize="10sp"
+        android:focusable="true" />
 
-            <Button android:id="@+id/cancel"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:text="@string/pip_cancel"
-                android:textSize="10sp"
-                android:focusable="true" />
-        </LinearLayout>
-    </FrameLayout>
-</RelativeLayout>
+    <Button android:id="@+id/cancel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:text="@string/pip_cancel"
+        android:textSize="10sp"
+        android:focusable="true" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_onboarding.xml b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
new file mode 100644
index 0000000..ef39555
--- /dev/null
+++ b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
@@ -0,0 +1,51 @@
+<?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.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#C00288D1"
+    android:gravity="center"
+    android:orientation="vertical" >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="30sp"
+        android:textColor="@android:color/white"
+        android:text="@string/pip_onboarding_title" />
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_sysbar_home" />
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="30dp"
+        android:textSize="13sp"
+        android:textColor="@android:color/white"
+        android:text="@string/pip_onboarding_description" />
+    <Button
+        android:id="@+id/close"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="15sp"
+        android:textAllCaps="true"
+        android:text="@string/pip_onboarding_button" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml
index e8691b5..6d9c48d 100644
--- a/packages/SystemUI/res/layout/tv_pip_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_overlay.xml
@@ -17,17 +17,13 @@
 */
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/guide_overlay"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <TextView
-        android:id="@+id/guide_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="bottom"
-        android:padding="3dp"
-        android:textSize="13sp"
-        android:textColor="#111111"
-        android:background="#99EEEEEE"
-        android:text="@string/pip_hold_home" />
-</FrameLayout>
+    android:layout_height="wrap_content"
+    android:layout_gravity="bottom"
+    android:padding="3dp"
+    android:textSize="13sp"
+    android:textColor="#111111"
+    android:background="#99EEEEEE"
+    android:text="@string/pip_hold_home" />
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index f1000ff..4972828 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Geen SIM nie."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Sellulêre data is af"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-verbinding."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Vliegtuigmodus."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Geen SIM-kaart nie."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skermvaspen"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"soek"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Kon nie <xliff:g id="APP">%s</xliff:g> begin nie."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Meer"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> meer"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Geskiedenis"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Vee uit"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Verdeel horisontaal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verdeel vertikaal"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Verdeel gepasmaak"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normale kleure"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Aandkleure"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Gepasmaakte kleure"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Outo"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Onbekende kleure"</string>
     <string name="color_transform" msgid="6985460408079086090">"Kleurverandering"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Wys kitsinstellings-teël"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Oorfone is gekoppel"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Kopstuk is gekoppel"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Aktiveer of deaktiveer ikone om op die statusbalk gewys te word."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Databespaarder"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Databespaarder is aan"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Databespaarder is af"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Aan"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigasiebalk"</string>
+    <string name="start" msgid="6873794757232879664">"Begin"</string>
+    <string name="center" msgid="4327473927066010960">"Middel"</string>
+    <string name="end" msgid="125797972524818282">"Einde"</string>
+    <string name="space" msgid="804232271282109749">"Spasieerder"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Kieslys / Sleutelbordwisselaar"</string>
+    <string name="select_button" msgid="1597989540662710653">"Kies knoppie om by te voeg"</string>
+    <string name="add_button" msgid="4134946063432258161">"Voeg knoppie by"</string>
+    <string name="save" msgid="2311877285724540644">"Stoor"</string>
+    <string name="reset" msgid="2448168080964209908">"Stel terug"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Geen tuisknoppie is gevind nie"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"\'n Tuisknoppie word vereis sodat daar op hierdie toestel genavigeer kan word. Voeg asseblief \'n tuisknoppie by voordat jy stoor."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Verstel knoppiebreedte"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Knipbord"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Die knipbord laat toe dat items direk na die knipbord getrek word. Items kan ook direk vanaf die knipbord getrek word, indien dit daar is."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Gepasmaakte navigasieknoppie"</string>
+    <string name="keycode" msgid="7335281375728356499">"Sleutelkode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Sleutelbordknoppies maak dit moontlik dat sleutelbordsleutels by die navigasiebalk gevoeg kan word. Wanneer hulle gedruk word, doen hulle dieselfde as die gekose sleutelbordsleutel. Eers moet die sleutel vir die knoppie gekies word, gevolg deur \'n prent wat op die knoppie gewys sal word."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Kies Sleutelbordknoppie"</string>
+    <string name="preview" msgid="9077832302472282938">"Voorskou"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
deleted file mode 100644
index afb7fec..0000000
--- a/packages/SystemUI/res/values-af/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Maak PIP toe"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Volskerm"</string>
-    <string name="pip_play" msgid="674145557658227044">"Speel"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Laat wag"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Kanselleer"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Hou HOME om PIP te beheer"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index fa8dc9d..2fa8012 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"ምንም SIM የለም።"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ብሉቱዝ ማያያዝ።"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"የአውሮፕላን ሁነታ።"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"ምንም SIM ካርድ የለም።"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ማያ ገጽ መሰካት"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ን መጀመር አልተቻለም።"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"ተጨማሪ"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> ተጨማሪ"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ታሪክ"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ጥረግ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"አግድም ክፈል"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ቁልቁል ክፈል"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"በብጁ ክፈል"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"መደበኛ ቀለሞች"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"የለሊት ቀለሞች"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"ብጁ ቀለሞች"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"ራስ-ሰር"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"የማይታወቁ ቀለሞች"</string>
     <string name="color_transform" msgid="6985460408079086090">"የቀለም ማሻሻያ"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"የፈጣን ቅንብሮች ሰቅን አሳይ"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"የጆር ማዳመጫዎች ተገናኝተዋል"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"የጆሮ ማዳመጫ ተገናኝቷል"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"አዶዎች በሁኔታ አሞሌ ላይ እንዲታዩ ወይም እንዳይታዩ ያንቁ ወይም ያሰናክሉ።"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"ውሂብ ቆጣቢ"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ውሂብ ቆጣቢ በርቷል"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ውሂብ ቆጣቢ ጠፍቷል"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"በርቷል"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"የአሰሳ አሞሌ"</string>
+    <string name="start" msgid="6873794757232879664">"ጀምር"</string>
+    <string name="center" msgid="4327473927066010960">"መሃል"</string>
+    <string name="end" msgid="125797972524818282">"መጨረሻ"</string>
+    <string name="space" msgid="804232271282109749">"ክፍተት ሰጪ"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"ምናሌ / የቁልፍ ሰሌዳ መቀየሪያ"</string>
+    <string name="select_button" msgid="1597989540662710653">"የሚታከል አዝራር ይምረጡ"</string>
+    <string name="add_button" msgid="4134946063432258161">"አዝራር አክል"</string>
+    <string name="save" msgid="2311877285724540644">"አስቀምጥ"</string>
+    <string name="reset" msgid="2448168080964209908">"ዳግም አስጀምር"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"ምንም የመነሻ አዝራር አልተገኘም"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ይህን መሣሪያ ማሰስ ለመቻል የመነሻ አዝራር ያስፈልጋል። እባክዎ ከማስቀመጥዎ በፊት የመነሻ አዝራር ያክሉ።"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"የአዝራር ስፋት አስተካክል"</string>
+    <string name="clipboard" msgid="1313879395099896312">"የቅንጥብ ሰሌዳ"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"የቅንጥብ ሰሌዳው ንጥሎች በቀጥታ ወደ ቅንጥብ ሰሌዳው እንዲጎተቱ ያስችላል። እንዲሁም ሲኖር ንጥሎች በቀጥታ ከቅንጥብ ሰሌዳው ውጭ ሊጎተቱ ይችላሉ።"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"ብጁ የአሰሳ አዝራር"</string>
+    <string name="keycode" msgid="7335281375728356499">"የቁልፍ ኮድ"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"የቁልፍ ኮድ አዝራሮች የቁልፍ ሰሌዳ ቁልፎች ወደ የአሰሳ አሞሌው እንዲታከሉ ያስችላሉ። ሲጫኑ የተመረጠውን የቁልፍ ሰሌዳ ቁልፍ ያስመስላሉ። መጀመሪያ ቁልፉ ለአዝራሩ መመረጥ አለበት፣ ከዚያ በመቀጠል በአዝራሩ ላይ የሚታየው ምስል መመረጥ አለበት።"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"የቁልፍ ሰሌዳ አዝራር ይምረጡ"</string>
+    <string name="preview" msgid="9077832302472282938">"ቅድመ-እይታ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
deleted file mode 100644
index 0184601..0000000
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIPን ዝጋ"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"ሙሉ ማያ ገጽ"</string>
-    <string name="pip_play" msgid="674145557658227044">"አጫውት"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"ለአፍታ አቁም"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"ይቅር"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIPን ለመቆጣጠር መነሻን ተጭነው ይያዙ"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 10853bf..2b80354 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -150,6 +150,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"‏ليست هناك شريحة SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"تم تعطيل بيانات شبكة الجوّال"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ربط البلوتوث."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"وضع الطائرة."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"‏ليس هناك شريحة SIM."</string>
@@ -304,8 +305,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"تثبيت الشاشة"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"تعذر بدء <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"المزيد"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> أخرى"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"السجلّ"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"محو"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسيم أفقي"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسيم رأسي"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"تقسيم مخصص"</string>
@@ -471,6 +472,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"ألوان عادية"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"ألوان ليلية"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"ألوان مخصصة"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"تلقائي"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"ألوان غير معروفة"</string>
     <string name="color_transform" msgid="6985460408079086090">"إشعار الألوان"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"إظهار قسم الإعدادات السريعة"</string>
@@ -497,10 +499,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"تم توصيل سماعات رأس"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"تم توصيل سماعات رأس"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"يمكنك تمكين أو تعطيل الرموز بحيث لا تظهر في شريط الحالة."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"توفير البيانات"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"تم تشغيل توفير البيانات"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"تم تعطيل توفير البيانات"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"تشغيل"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"شريط التنقل"</string>
+    <string name="start" msgid="6873794757232879664">"البدء"</string>
+    <string name="center" msgid="4327473927066010960">"وسط"</string>
+    <string name="end" msgid="125797972524818282">"النهاية"</string>
+    <string name="space" msgid="804232271282109749">"أداة المباعدة"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"مبدِّل القوائم / لوحة المفاتيح"</string>
+    <string name="select_button" msgid="1597989540662710653">"تحديد الزر لإضافته"</string>
+    <string name="add_button" msgid="4134946063432258161">"إضافة زر"</string>
+    <string name="save" msgid="2311877285724540644">"حفظ"</string>
+    <string name="reset" msgid="2448168080964209908">"إعادة تعيين"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"لم يُعثر على زر صفحة رئيسية"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"زر الصفحة الرئيسية مطلوب لكي تتمكن من التنقل في هذا الجهاز، الرجاء إضافة زر صفحة رئيسية قبل الحفظ."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"ضبط عرض الزر"</string>
+    <string name="clipboard" msgid="1313879395099896312">"الحافظة"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"تتيح الحافظة إمكانية سحب العناصر مباشرة إلى الحافظة، وكذلك يمكن سحب العناصر مباشرة خارج الحافظة عند وجودها."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"زر التنقل المخصص"</string>
+    <string name="keycode" msgid="7335281375728356499">"رمز المفتاح"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"تتيح أزرار رموز المفاتيح إمكانية إضافة مفاتيح لوحة المفاتيح إلى شريط التنقل. وعند الضغط عليها، تحاكي الأزرار مفتاح لوحة المفاتيح المحدد. ويجب أولاً تحديد المفتاح للزر، وبعد ذلك تحديد صورة لكي يتم عرضها على الزر."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"تحديد زر لوحة المفاتيح"</string>
+    <string name="preview" msgid="9077832302472282938">"معاينة"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
deleted file mode 100644
index 28329d5..0000000
--- a/packages/SystemUI/res/values-ar/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"‏إغلاق PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"ملء الشاشة"</string>
-    <string name="pip_play" msgid="674145557658227044">"تشغيل"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"إيقاف مؤقت"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"إلغاء"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"‏اضغط مع الاستمرار على \"الرئيسية\" للتحكم في PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 00b78b2..a21253f 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM yoxdur"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobil Data Deaktivdir"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth tezering."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Uçuş rejimi"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM kart yoxdur."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekran sancağı"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"axtarış"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlana bilmir."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Daha çox"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> Daha çox"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Tarixçə"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Təmizləyin"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Üfüqi Böl"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Şaquli Böl"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Fərdi Böl"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normal rənglər"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Gecə rəngləri"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Xüsusi rənglər"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Avto"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Naməlum rəng"</string>
     <string name="color_transform" msgid="6985460408079086090">"Rəng modifikasiyası"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Cəld ayarlar örtüyünü göstərin"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Qulaqlıq qoşulub"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Qulaqlıq qoşulub"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"İkonaların status panelində görünməsini aktiv və ya deaktiv edin."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Data Qənaəti"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Qənaəti aktivdir"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Qənaəti deaktivdir"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Aktiv"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Naviqasiya paneli"</string>
+    <string name="start" msgid="6873794757232879664">"Başladın"</string>
+    <string name="center" msgid="4327473927066010960">"Mərkəz"</string>
+    <string name="end" msgid="125797972524818282">"Son"</string>
+    <string name="space" msgid="804232271282109749">"Boşluq"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menyu / Klaviatura Keçirici"</string>
+    <string name="select_button" msgid="1597989540662710653">"Əlavə etmək üçün düymə seçin"</string>
+    <string name="add_button" msgid="4134946063432258161">"Düymə əlavə edin"</string>
+    <string name="save" msgid="2311877285724540644">"Saxlayın"</string>
+    <string name="reset" msgid="2448168080964209908">"Sıfırlayın"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Heç bir əsas ekran düyməsi tapılmadı"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Bu cihazı idarə etmək üçün əsas düymə tələb olunur. Yaddaşda saxlamadan əvvəl əsas düyməni əlavə edin."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Düymənin enini nizamlayın"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Pano"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Elementlərin sürüşdürərək birbaşa panoya əlavə olunmasına icazə verir. Mövcud olduqda elementlər pano kənarından da sürüşdürərək birbaşa panoya əlavə oluna bilər."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Fərdi naviqasiya düyməsi"</string>
+    <string name="keycode" msgid="7335281375728356499">"Açar kodu"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Açar kodu düymələri klaviatura açarlarının Naviqasiya Panelinə əlavə olunmasına icazə verir. Basıldıqda seçilmiş klaviatura açarını yaradır. İlk olaraq düymə üçün düymə üzərində göstərilən şəkilə uyğun açar seçilməlidir."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Klaviatura Düyməsi Seçin"</string>
+    <string name="preview" msgid="9077832302472282938">"Önizləmə"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
deleted file mode 100644
index 8f3be27..0000000
--- a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP bağlayın"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Tam ekran"</string>
-    <string name="pip_play" msgid="674145557658227044">"Göstərin"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Fasilə verin"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Ləğv edin"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP idarə etmək üçün ƏSAS düyməni basıb saxlayın"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 4b3f157..cb1549b 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -147,6 +147,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nema SIM kartice."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Podaci za mobilne uređaje su isključeni"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth privezivanje."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim rada u avionu."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Nema SIM kartice."</string>
@@ -301,8 +302,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kačenje ekrana"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Pokretanje aplikacije <xliff:g id="APP">%s</xliff:g> nije uspelo."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Još"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Još <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Istorija"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Obriši"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podeli horizontalno"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podeli vertikalno"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođeno deljenje"</string>
@@ -468,6 +469,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normalne boje"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Noćne boje"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Prilagođene boje"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatski"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Nepoznate boje"</string>
     <string name="color_transform" msgid="6985460408079086090">"Izmena boja"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Prikaži pločicu Brza podešavanja"</string>
@@ -494,10 +496,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalice su povezane"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Naglavne slušalice su povezane"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Omogućite ili onemogućite prikazivanje ikona na statusnoj traci."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Ušteda podataka"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Ušteda podataka je uključena"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Ušteda podataka je isključena"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Uključeno"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Traka za navigaciju"</string>
+    <string name="start" msgid="6873794757232879664">"Pokreni"</string>
+    <string name="center" msgid="4327473927066010960">"Centar"</string>
+    <string name="end" msgid="125797972524818282">"Dno"</string>
+    <string name="space" msgid="804232271282109749">"Oznaka za razmak"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Meni/Tastatura prebacivač"</string>
+    <string name="select_button" msgid="1597989540662710653">"Izaberite dugme za dodavanje"</string>
+    <string name="add_button" msgid="4134946063432258161">"Dodaj dugme"</string>
+    <string name="save" msgid="2311877285724540644">"Sačuvaj"</string>
+    <string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Nismo pronašli dugme Početna"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Dugme Početna je neophodno za navigaciju na ovom uređaju. Dodajte dugme Početna pre nego što sačuvate izmene."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Prilagodi širinu dugmeta"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Privremena memorija"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Privremena memorija omogućava da se stavke prevlače direktno u privremenu memoriju. Postojeće stavke mogu da se prevlače i direktno iz privremene memorije."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Prilagođeno dugme za navigaciju"</string>
+    <string name="keycode" msgid="7335281375728356499">"Kôd tastera"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Dugmad za kodove tastera omogućava da se na traku za navigaciju dodaju tasteri na tastaturi. Kada pritisnete dugme, simulira se izabrani taster na tastaturi. Prvo morate da izaberete taster za dugme, pa sliku koju će se prikazivati na dugmetu."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Izaberite dugme za tastaturu"</string>
+    <string name="preview" msgid="9077832302472282938">"Pregled"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
deleted file mode 100644
index 7d35b20..0000000
--- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Zatvori PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Ceo ekran"</string>
-    <string name="pip_play" msgid="674145557658227044">"Pusti"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pauziraj"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Otkaži"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Zadržite taster za POČETNI EKRAN da biste kontrolisali PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a5fdd8e..606144a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Няма SIM карта."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Мобилните данни са изключени"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Тетъринг през Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Самолетен режим."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Няма SIM карта."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"фиксиране на екрана"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не можа да стартира."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Още"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Още <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"История"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Изчистване"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хоризонтално разделяне"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Вертикално разделяне"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Персонализирано разделяне"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Нормални цветове"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Нощни цветове"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Персонализирани цветове"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Автоматично"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Неизвестни цветове"</string>
     <string name="color_transform" msgid="6985460408079086090">"Промяна на цветовете"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Показване на плочката за бързи настройки"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Слушалките (без микрофон) са свързани"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Слушалките са свързани"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Активиране или деактивиране на показването на икони в лентата на състоянието."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Икономия на данни"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Функцията „Икономия на данни“ е включена"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Функцията „Икономия на данни“ е изключена"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Вкл."</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Лента за навигация"</string>
+    <string name="start" msgid="6873794757232879664">"Начало"</string>
+    <string name="center" msgid="4327473927066010960">"Център"</string>
+    <string name="end" msgid="125797972524818282">"Край"</string>
+    <string name="space" msgid="804232271282109749">"Разстояние между бутоните"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Превкл. на менюто/клавиатурата"</string>
+    <string name="select_button" msgid="1597989540662710653">"Избиране на бутон за добавяне"</string>
+    <string name="add_button" msgid="4134946063432258161">"Добавяне на бутон"</string>
+    <string name="save" msgid="2311877285724540644">"Запазване"</string>
+    <string name="reset" msgid="2448168080964209908">"Повторно задаване"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Няма намерен бутон „Начало“"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"За да се придвижвате в това устройство, е необходим бутон „Начало“. Моля, добавете такъв, преди да запазите."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Коригиране на ширината на бутона"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Буферна памет"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Този бутон ви дава възможност да премествате с плъзгане елементи директно в буферната памет, а също и извън нея."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Персонализиран бутон за навигация"</string>
+    <string name="keycode" msgid="7335281375728356499">"Клавишен код"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Бутоните с клавишни кодове ви дават възможност да добавяте клавиши от клавиатурата към лентата за навигация. При докосване на такъв бутон се симулира натискане на съответния клавиш. Първо, трябва да изберете клавиш за бутона, а след това – изображение, което да се показва върху него."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Избиране на клавиш от клавиатурата"</string>
+    <string name="preview" msgid="9077832302472282938">"Визуализация"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
deleted file mode 100644
index 82c2d08..0000000
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Затваряне на режима „Картина в картина“"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Цял екран"</string>
-    <string name="pip_play" msgid="674145557658227044">"Пускане"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Пауза"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Отказ"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Задръжте „HOME“, за да контролирате режима „Картина в картина“"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index d6f5868..3ece957 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"কোনো সিম নেই৷"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"সেলুলার ডেটা বন্ধ আছে"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth টিথারিং৷"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"বিমান মোড৷"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"কোনো SIM কার্ড নেই।"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"স্ক্রীন পিন করা"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"অনুসন্ধান"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> শুরু করা যায়নি৷"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"আরো"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"আরো <xliff:g id="NUMBER">%d</xliff:g>টি"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ইতিহাস"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"সাফ করুন"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"অনুভূমিক স্প্লিট"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"উল্লম্ব স্প্লিট"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"কাস্টম স্প্লিট করুন"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"স্বাভাবিক রঙ"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"রাতের রঙ"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"কাস্টম রঙ"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"স্বয়ংক্রিয়ভাবে"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"অজানা রঙ"</string>
     <string name="color_transform" msgid="6985460408079086090">"রঙ সংশোধন"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"দ্রুত সেটিংস টাইল দেখান"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"হেডফোনগুলি সংযুক্ত হয়েছে"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"হেডসেট সংযুক্ত হয়েছে"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"স্থিতি দন্ডে দেখানোর জন্য আইকনগুলিকে সক্ষম বা অক্ষম করুন৷"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"ডেটা সেভার"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ডেটা সেভার চালু আছে"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ডেটা সেভার বন্ধ আছে"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"চালু আছে"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"নেভিগেশন দন্ড"</string>
+    <string name="start" msgid="6873794757232879664">"শুরু করুন"</string>
+    <string name="center" msgid="4327473927066010960">"কেন্দ্র"</string>
+    <string name="end" msgid="125797972524818282">"শেষ"</string>
+    <string name="space" msgid="804232271282109749">"স্পেসার"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"মেনু / কীবোর্ড স্যুইচার"</string>
+    <string name="select_button" msgid="1597989540662710653">"যোগ করার জন্য বোতাম নির্বাচন করুন"</string>
+    <string name="add_button" msgid="4134946063432258161">"বোতাম যোগ করুন"</string>
+    <string name="save" msgid="2311877285724540644">"সংরক্ষণ করুন"</string>
+    <string name="reset" msgid="2448168080964209908">"পুনরায় সেট করুন"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"কোনো হোম বোতাম পাওয়া যায় নি"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"এই ডিভাইসটিকে নেভিগেট করার জন্য একটি হোম বোতামের প্রয়োজন। সংরক্ষণ করার আগে অনুগ্রহ করে একটি হোম বোতাম যোগ করুন।"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"বোতামের প্রস্থ সমন্বয় করুন"</string>
+    <string name="clipboard" msgid="1313879395099896312">"ক্লিপবোর্ড"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"ক্লিপবোর্ড আইটেমগুলিকে সরাসরি ক্লিপবোর্ডে টেনে আনার অনুমতি দেয়। ক্লিপবোর্ডের বাইরে হাজির থাকার সময়েও আইটেমগুলিকে সরাসরি টেনে আনা যায়।"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"কাস্টম নেভিগেশান বোতাম"</string>
+    <string name="keycode" msgid="7335281375728356499">"কীকোড"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"কীকোড বোতামগুলি নেভিগেশান দন্ডে কীবোর্ডের কীগুলি যোগ করার অনুমতি দেয়। চাপ দেওয়ার সময়ে সেগুলি নির্বাচিত কীবোর্ডের কী কে অনুকরণ করে। বোতামে দেখানো হয়েছে এমন একটি চিত্রকে অনুসরণ করে অবশ্যই প্রথমে বোতামের জন্য কী নির্বাচন করতে হবে।"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"কীবোর্ডের বোতাম নির্বাচন করুন"</string>
+    <string name="preview" msgid="9077832302472282938">"পূর্বরূপ দেখুন"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
deleted file mode 100644
index 15d0e82..0000000
--- a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP বন্ধ করুন"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"পূর্ণ স্ক্রীন"</string>
-    <string name="pip_play" msgid="674145557658227044">"চালান"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"বিরাম দিন"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"বাতিল করুন"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP নিয়ন্ত্রণ করতে HOME ধরে রাখুন"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
new file mode 100644
index 0000000..fe4cca2
--- /dev/null
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -0,0 +1,988 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for app_label (7164937344850004466) -->
+    <skip />
+    <!-- no translation found for status_bar_clear_all_button (7774721344716731603) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_remove_item_title (6026395868129852968) -->
+    <skip />
+    <!-- no translation found for status_bar_recent_inspect_item_title (7793624864528818569) -->
+    <skip />
+    <!-- no translation found for status_bar_no_recent_apps (7374907845131203189) -->
+    <skip />
+    <!-- no translation found for status_bar_accessibility_dismiss_recents (4576076075226540105) -->
+    <skip />
+    <!-- no translation found for status_bar_accessibility_recent_apps (9138535907802238759) -->
+    <!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
+    <skip />
+    <!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
+    <skip />
+    <!-- no translation found for status_bar_latest_events_title (6594767438577593172) -->
+    <skip />
+    <!-- no translation found for battery_low_title (6456385927409742437) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format (2900940511201380775) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_saver_started (6859235584035338833) -->
+    <skip />
+    <!-- no translation found for invalid_charger (4549105996740522523) -->
+    <skip />
+    <!-- no translation found for invalid_charger_title (3515740382572798460) -->
+    <skip />
+    <!-- no translation found for invalid_charger_text (5474997287953892710) -->
+    <skip />
+    <!-- no translation found for battery_low_why (4553600287639198111) -->
+    <skip />
+    <!-- no translation found for battery_saver_confirmation_title (5299585433050361634) -->
+    <skip />
+    <!-- no translation found for battery_saver_confirmation_ok (7507968430447930257) -->
+    <skip />
+    <!-- no translation found for battery_saver_start_action (5576697451677486320) -->
+    <skip />
+    <!-- no translation found for status_bar_settings_settings_button (3023889916699270224) -->
+    <skip />
+    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
+    <skip />
+    <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
+    <skip />
+    <!-- no translation found for status_bar_settings_mute_label (554682549917429396) -->
+    <skip />
+    <!-- no translation found for status_bar_settings_auto_brightness_label (511453614962324674) -->
+    <skip />
+    <!-- no translation found for status_bar_settings_notifications (397146176280905137) -->
+    <skip />
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
+    <!-- no translation found for status_bar_input_method_settings_configure_input_methods (3504292471512317827) -->
+    <skip />
+    <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) -->
+    <skip />
+    <!-- no translation found for usb_device_permission_prompt (834698001271562057) -->
+    <skip />
+    <!-- no translation found for usb_accessory_permission_prompt (5171775411178865750) -->
+    <skip />
+    <!-- no translation found for usb_device_confirm_prompt (5161205258635253206) -->
+    <skip />
+    <!-- no translation found for usb_accessory_confirm_prompt (3808984931830229888) -->
+    <skip />
+    <!-- no translation found for usb_accessory_uri_prompt (513450621413733343) -->
+    <skip />
+    <!-- no translation found for title_usb_accessory (4966265263465181372) -->
+    <skip />
+    <!-- no translation found for label_view (6304565553218192990) -->
+    <skip />
+    <!-- no translation found for always_use_device (1450287437017315906) -->
+    <skip />
+    <!-- no translation found for always_use_accessory (1210954576979621596) -->
+    <skip />
+    <!-- no translation found for usb_debugging_title (4513918393387141949) -->
+    <skip />
+    <!-- no translation found for usb_debugging_message (2220143855912376496) -->
+    <skip />
+    <!-- no translation found for usb_debugging_always (303335496705863070) -->
+    <skip />
+    <!-- no translation found for usb_debugging_secondary_user_title (6353808721761220421) -->
+    <skip />
+    <!-- no translation found for usb_debugging_secondary_user_message (8572228137833020196) -->
+    <skip />
+    <!-- no translation found for compat_mode_on (6623839244840638213) -->
+    <skip />
+    <!-- no translation found for compat_mode_off (4434467572461327898) -->
+    <skip />
+    <!-- no translation found for screenshot_saving_ticker (7403652894056693515) -->
+    <skip />
+    <!-- no translation found for screenshot_saving_title (8242282144535555697) -->
+    <skip />
+    <!-- no translation found for screenshot_saving_text (2419718443411738818) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (6461865960961414961) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (1152839647677558815) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (705781116746922771) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_text (1260203058661337274) -->
+    <skip />
+    <!-- no translation found for usb_preference_title (6551050377388882787) -->
+    <skip />
+    <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+    <skip />
+    <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+    <skip />
+    <!-- no translation found for installer_cd_button_title (2312667578562201583) -->
+    <skip />
+    <!-- no translation found for accessibility_back (567011538994429120) -->
+    <skip />
+    <!-- no translation found for accessibility_home (8217216074895377641) -->
+    <skip />
+    <!-- no translation found for accessibility_menu (316839303324695949) -->
+    <skip />
+    <!-- no translation found for accessibility_recent (5208608566793607626) -->
+    <skip />
+    <!-- no translation found for accessibility_search_light (1103867596330271848) -->
+    <skip />
+    <!-- no translation found for accessibility_camera_button (8064671582820358152) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_button (6738112589538563574) -->
+    <skip />
+    <!-- no translation found for accessibility_voice_assist_button (487611083884852965) -->
+    <skip />
+    <!-- no translation found for accessibility_unlock_button (128158454631118828) -->
+    <skip />
+    <!-- no translation found for accessibility_unlock_button_fingerprint (8214125623493923751) -->
+    <skip />
+    <!-- no translation found for accessibility_unlock_without_fingerprint (7541705575183694446) -->
+    <skip />
+    <!-- no translation found for unlock_label (8779712358041029439) -->
+    <skip />
+    <!-- no translation found for phone_label (2320074140205331708) -->
+    <skip />
+    <!-- no translation found for voice_assist_label (3956854378310019854) -->
+    <skip />
+    <!-- no translation found for camera_label (7261107956054836961) -->
+    <skip />
+    <!-- no translation found for recents_caption_resize (3517056471774958200) -->
+    <skip />
+    <!-- no translation found for cancel (6442560571259935130) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+    <skip />
+    <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+    <skip />
+    <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+    <skip />
+    <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+    <skip />
+    <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+    <skip />
+    <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+    <skip />
+    <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+    <skip />
+    <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+    <skip />
+    <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+    <skip />
+    <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+    <skip />
+    <!-- no translation found for accessibility_wifi_name (7202151365171148501) -->
+    <skip />
+    <!-- no translation found for accessibility_bluetooth_name (8441517146585531676) -->
+    <skip />
+    <!-- no translation found for accessibility_no_wimax (4329180129727630368) -->
+    <skip />
+    <!-- no translation found for accessibility_wimax_one_bar (4170994299011863648) -->
+    <skip />
+    <!-- no translation found for accessibility_wimax_two_bars (9176236858336502288) -->
+    <skip />
+    <!-- no translation found for accessibility_wimax_three_bars (6116551636752103927) -->
+    <skip />
+    <!-- no translation found for accessibility_wimax_signal_full (2768089986795579558) -->
+    <skip />
+    <!-- no translation found for accessibility_ethernet_disconnected (5896059303377589469) -->
+    <skip />
+    <!-- no translation found for accessibility_ethernet_connected (2692130313069182636) -->
+    <skip />
+    <!-- no translation found for accessibility_no_signal (7064645320782585167) -->
+    <skip />
+    <!-- no translation found for accessibility_not_connected (6395326276213402883) -->
+    <skip />
+    <!-- no translation found for accessibility_zero_bars (3806060224467027887) -->
+    <skip />
+    <!-- no translation found for accessibility_one_bar (1685730113192081895) -->
+    <skip />
+    <!-- no translation found for accessibility_two_bars (6437363648385206679) -->
+    <skip />
+    <!-- no translation found for accessibility_three_bars (2648241415119396648) -->
+    <skip />
+    <!-- no translation found for accessibility_signal_full (9122922886519676839) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_on (2385254693624345265) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_off (6475508157786853157) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_connected (8366256693719499665) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_1x (994133468120244018) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_hspa (2032328855462645198) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_lte (5413468808637540658) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_roaming (5977362333466556094) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+    <skip />
+    <!-- no translation found for accessibility_data_connection_wifi (2324496756590645221) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+    <skip />
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobilni podaci isključeni"</string>
+    <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+    <skip />
+    <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+    <skip />
+    <!-- no translation found for accessibility_no_sims (3957997018324995781) -->
+    <skip />
+    <!-- no translation found for accessibility_carrier_network_change_mode (4017301580441304305) -->
+    <skip />
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
+    <!-- no translation found for accessibility_settings_button (799583911231893380) -->
+    <skip />
+    <!-- no translation found for accessibility_notifications_button (4498000369779421892) -->
+    <skip />
+    <!-- no translation found for accessibility_remove_notification (3603099514902182350) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+    <skip />
+    <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+    <skip />
+    <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+    <skip />
+    <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+    <skip />
+    <!-- no translation found for accessibility_casting (6887382141726543668) -->
+    <skip />
+    <!-- no translation found for accessibility_work_mode (2478631941714607225) -->
+    <skip />
+    <!-- no translation found for accessibility_recents_item_will_be_dismissed (395770242498031481) -->
+    <skip />
+    <!-- no translation found for accessibility_recents_item_dismissed (6803574935084867070) -->
+    <skip />
+    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
+    <skip />
+    <!-- no translation found for accessibility_recents_item_launched (7616039892382525203) -->
+    <skip />
+    <!-- no translation found for accessibility_recents_task_header (1437183540924535457) -->
+    <skip />
+    <!-- no translation found for accessibility_notification_dismissed (854211387186306927) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_notification_shade (4690274844447504208) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_quick_settings (6186378411582437046) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_lock_screen (5625143713611759164) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_settings (3417884241751434521) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_recent_apps (4876900986661819788) -->
+    <skip />
+    <!-- no translation found for accessibility_desc_close (7479755364962766729) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_user (1104846699869476855) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_wifi (5518210213118181692) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_wifi_changed_off (8716484460897819400) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_wifi_changed_on (6440117170789528622) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_mobile (4876806564086241341) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_battery (1480931583381408972) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_airplane_off (7786329360056634412) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_airplane_on (6406141469157599296) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_airplane_changed_off (66846307818850664) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_airplane_changed_on (8983005603505087728) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_dnd_priority_on (1448402297221249355) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_dnd_none_on (6882582132662613537) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_dnd_off (2371832603753738581) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_dnd_changed_off (898107593453022935) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_dnd_changed_on (4483780856613561039) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_bluetooth_off (2133631372372064339) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_bluetooth_on (7681999166216621838) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_bluetooth_connecting (6953242966685343855) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_bluetooth_connected (4306637793614573659) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_off (2730003763480934529) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_bluetooth_changed_on (8722351798763206577) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_location_off (5119080556976115520) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_location_on (5809937096590102036) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_location_changed_off (8526845571503387376) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_location_changed_on (339403053079338468) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_alarm (3959908972897295660) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_close (3115847794692516306) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_more_time (3659274935356197708) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_less_time (2404728746293515623) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_flashlight_off (4936432000069786988) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_flashlight_on (2003479320007841077) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_flashlight_changed_off (3303701786768224304) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_flashlight_changed_on (6531793301533894686) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_off (4406577213290173911) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_color_inversion_changed_on (6897462320184911126) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_hotspot_changed_off (5004708003447561394) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_hotspot_changed_on (2890951609226476206) -->
+    <skip />
+    <!-- no translation found for accessibility_casting_turned_off (1430668982271976172) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_work_mode_off (7045417396436552890) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_work_mode_on (7650588553988014341) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_work_mode_changed_off (5605534876107300711) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_work_mode_changed_on (249840330756998612) -->
+    <skip />
+    <!-- no translation found for accessibility_brightness (8003681285547803095) -->
+    <skip />
+    <!-- no translation found for data_usage_disabled_dialog_3g_title (5281770593459841889) -->
+    <skip />
+    <!-- no translation found for data_usage_disabled_dialog_4g_title (1601769736881078016) -->
+    <skip />
+    <!-- no translation found for data_usage_disabled_dialog_mobile_title (4651001290947318931) -->
+    <skip />
+    <!-- no translation found for data_usage_disabled_dialog_title (3932437232199671967) -->
+    <skip />
+    <!-- no translation found for data_usage_disabled_dialog (8453242888903772524) -->
+    <skip />
+    <!-- no translation found for data_usage_disabled_dialog_enable (1412395410306390593) -->
+    <skip />
+    <!-- no translation found for status_bar_settings_signal_meter_disconnected (1940231521274147771) -->
+    <skip />
+    <!-- no translation found for status_bar_settings_signal_meter_wifi_nossid (6557486452774597820) -->
+    <skip />
+    <!-- no translation found for gps_notification_searching_text (8574247005642736060) -->
+    <skip />
+    <!-- no translation found for gps_notification_found_text (4619274244146446464) -->
+    <skip />
+    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+    <skip />
+    <!-- no translation found for accessibility_clear_all (5235938559247164925) -->
+    <skip />
+    <!-- no translation found for status_bar_notification_inspect_item_title (5668348142410115323) -->
+    <skip />
+    <!-- no translation found for status_bar_notification_app_settings_title (5525260160341558869) -->
+    <skip />
+    <!-- no translation found for accessibility_rotation_lock_off (4062780228931590069) -->
+    <skip />
+    <!-- no translation found for accessibility_rotation_lock_on_landscape (6731197337665366273) -->
+    <skip />
+    <!-- no translation found for accessibility_rotation_lock_on_portrait (5809367521644012115) -->
+    <skip />
+    <!-- no translation found for accessibility_rotation_lock_off_changed (8134601071026305153) -->
+    <skip />
+    <!-- no translation found for accessibility_rotation_lock_on_landscape_changed (3135965553707519743) -->
+    <skip />
+    <!-- no translation found for accessibility_rotation_lock_on_portrait_changed (8922481981834012126) -->
+    <skip />
+    <!-- no translation found for dessert_case (1295161776223959221) -->
+    <skip />
+    <!-- no translation found for start_dreams (7219575858348719790) -->
+    <skip />
+    <!-- no translation found for ethernet_label (7967563676324087464) -->
+    <skip />
+    <!-- no translation found for quick_settings_dnd_label (8735855737575028208) -->
+    <skip />
+    <!-- no translation found for quick_settings_dnd_priority_label (483232950670692036) -->
+    <skip />
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
+    <!-- no translation found for quick_settings_dnd_none_label (5025477807123029478) -->
+    <skip />
+    <!-- no translation found for quick_settings_bluetooth_label (6304190285170721401) -->
+    <skip />
+    <!-- no translation found for quick_settings_bluetooth_multiple_devices_label (3912245565613684735) -->
+    <skip />
+    <!-- no translation found for quick_settings_bluetooth_off_label (8159652146149219937) -->
+    <skip />
+    <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+    <skip />
+    <!-- no translation found for quick_settings_brightness_label (6968372297018755815) -->
+    <skip />
+    <!-- no translation found for quick_settings_rotation_unlocked_label (7305323031808150099) -->
+    <skip />
+    <!-- no translation found for quick_settings_rotation_locked_label (6359205706154282377) -->
+    <skip />
+    <!-- no translation found for quick_settings_rotation_locked_portrait_label (5102691921442135053) -->
+    <skip />
+    <!-- no translation found for quick_settings_rotation_locked_landscape_label (8553157770061178719) -->
+    <skip />
+    <!-- no translation found for quick_settings_ime_label (7073463064369468429) -->
+    <skip />
+    <!-- no translation found for quick_settings_location_label (5011327048748762257) -->
+    <skip />
+    <!-- no translation found for quick_settings_location_off_label (7464544086507331459) -->
+    <skip />
+    <!-- no translation found for quick_settings_media_device_label (1302906836372603762) -->
+    <skip />
+    <!-- no translation found for quick_settings_rssi_label (7725671335550695589) -->
+    <skip />
+    <!-- no translation found for quick_settings_rssi_emergency_only (2713774041672886750) -->
+    <skip />
+    <!-- no translation found for quick_settings_settings_label (5326556592578065401) -->
+    <skip />
+    <!-- no translation found for quick_settings_time_label (4635969182239736408) -->
+    <skip />
+    <!-- no translation found for quick_settings_user_label (5238995632130897840) -->
+    <skip />
+    <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+    <skip />
+    <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_label (9135344704899546041) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_not_connected (7171904845345573431) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_no_network (2221993077220856376) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_off_label (7558778100843885864) -->
+    <skip />
+    <!-- no translation found for quick_settings_wifi_detail_empty_text (269990350383909226) -->
+    <skip />
+    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
+    <skip />
+    <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+    <skip />
+    <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+    <skip />
+    <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+    <skip />
+    <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+    <skip />
+    <!-- no translation found for quick_settings_brightness_dialog_title (8599674057673605368) -->
+    <skip />
+    <!-- no translation found for quick_settings_brightness_dialog_auto_brightness_label (5064982743784071218) -->
+    <skip />
+    <!-- no translation found for quick_settings_inversion_label (8790919884718619648) -->
+    <skip />
+    <!-- no translation found for quick_settings_color_space_label (853443689745584770) -->
+    <skip />
+    <!-- no translation found for quick_settings_more_settings (326112621462813682) -->
+    <skip />
+    <!-- no translation found for quick_settings_done (3402999958839153376) -->
+    <skip />
+    <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+    <skip />
+    <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+    <skip />
+    <!-- no translation found for quick_settings_tethering_label (7153452060448575549) -->
+    <skip />
+    <!-- no translation found for quick_settings_hotspot_label (6046917934974004879) -->
+    <skip />
+    <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+    <skip />
+    <!-- no translation found for quick_settings_flashlight_label (2133093497691661546) -->
+    <skip />
+    <!-- no translation found for quick_settings_cellular_detail_title (8575062783675171695) -->
+    <skip />
+    <!-- no translation found for quick_settings_cellular_detail_data_usage (1964260360259312002) -->
+    <skip />
+    <!-- no translation found for quick_settings_cellular_detail_remaining_data (722715415543541249) -->
+    <skip />
+    <!-- no translation found for quick_settings_cellular_detail_over_limit (967669665390990427) -->
+    <skip />
+    <!-- no translation found for quick_settings_cellular_detail_data_used (1476810587475761478) -->
+    <skip />
+    <!-- no translation found for quick_settings_cellular_detail_data_limit (56011158504994128) -->
+    <skip />
+    <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+    <skip />
+    <!-- no translation found for quick_settings_work_mode_label (6244915274350490429) -->
+    <skip />
+    <!-- no translation found for recents_empty_message (8682129509540827999) -->
+    <skip />
+    <!-- no translation found for recents_app_info_button_label (2890317189376000030) -->
+    <skip />
+    <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
+    <skip />
+    <!-- no translation found for recents_search_bar_label (8074997400187836677) -->
+    <skip />
+    <!-- no translation found for recents_launch_error_message (2969287838120550506) -->
+    <skip />
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historija"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Obriši"</string>
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_horizontal (8848514474543427332) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_vertical (9075292233696180813) -->
+    <skip />
+    <!-- no translation found for recents_multistack_add_stack_dialog_split_custom (4177837597513701943) -->
+    <skip />
+    <!-- no translation found for expanded_header_battery_charged (5945855970267657951) -->
+    <skip />
+    <!-- no translation found for expanded_header_battery_charging (205623198487189724) -->
+    <skip />
+    <!-- no translation found for expanded_header_battery_charging_with_time (457559884275395376) -->
+    <skip />
+    <!-- no translation found for expanded_header_battery_not_charging (4798147152367049732) -->
+    <skip />
+    <!-- no translation found for ssl_ca_cert_warning (9005954106902053641) -->
+    <skip />
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for zen_priority_introduction (3070506961866919502) -->
+    <skip />
+    <!-- no translation found for zen_priority_customize_button (7948043278226955063) -->
+    <skip />
+    <!-- no translation found for zen_silence_introduction_voice (2284540992298200729) -->
+    <skip />
+    <!-- no translation found for zen_silence_introduction (3137882381093271568) -->
+    <skip />
+    <!-- no translation found for keyguard_more_overflow_text (9195222469041601365) -->
+    <skip />
+    <!-- no translation found for speed_bump_explanation (1288875699658819755) -->
+    <skip />
+    <!-- no translation found for notification_tap_again (8524949573675922138) -->
+    <skip />
+    <!-- no translation found for keyguard_unlock (8043466894212841998) -->
+    <skip />
+    <!-- no translation found for phone_hint (4872890986869209950) -->
+    <skip />
+    <!-- no translation found for voice_hint (8939888732119726665) -->
+    <skip />
+    <!-- no translation found for camera_hint (7939688436797157483) -->
+    <skip />
+    <!-- no translation found for interruption_level_none_with_warning (5114872171614161084) -->
+    <skip />
+    <!-- no translation found for interruption_level_none (6000083681244492992) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
+    <!-- no translation found for interruption_level_none_twoline (3957581548190765889) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
+    <!-- no translation found for interruption_level_all (1330581184930945764) -->
+    <skip />
+    <!-- no translation found for interruption_level_all_twoline (3719402899156124780) -->
+    <skip />
+    <!-- no translation found for keyguard_indication_charging_time (1757251776872835768) -->
+    <skip />
+    <!-- no translation found for keyguard_indication_charging_time_fast (9018981952053914986) -->
+    <skip />
+    <!-- no translation found for keyguard_indication_charging_time_slowly (955252797961724952) -->
+    <skip />
+    <!-- no translation found for accessibility_multi_user_switch_switcher (7305948938141024937) -->
+    <skip />
+    <!-- no translation found for accessibility_multi_user_switch_switcher_with_current (8434880595284601601) -->
+    <skip />
+    <!-- no translation found for accessibility_multi_user_switch_inactive (1424081831468083402) -->
+    <skip />
+    <!-- no translation found for accessibility_multi_user_switch_quick_contact (3020367729287990475) -->
+    <skip />
+    <!-- no translation found for user_add_user (5110251524486079492) -->
+    <skip />
+    <!-- no translation found for user_new_user_name (426540612051178753) -->
+    <skip />
+    <!-- no translation found for guest_nickname (8059989128963789678) -->
+    <skip />
+    <!-- no translation found for guest_new_guest (600537543078847803) -->
+    <skip />
+    <!-- no translation found for guest_exit_guest (7187359342030096885) -->
+    <skip />
+    <!-- no translation found for guest_exit_guest_dialog_title (8480693520521766688) -->
+    <skip />
+    <!-- no translation found for guest_exit_guest_dialog_message (4155503224769676625) -->
+    <skip />
+    <!-- no translation found for guest_exit_guest_dialog_remove (7402231963862520531) -->
+    <skip />
+    <!-- no translation found for guest_wipe_session_title (6419439912885956132) -->
+    <skip />
+    <!-- no translation found for guest_wipe_session_message (8476238178270112811) -->
+    <skip />
+    <!-- no translation found for guest_wipe_session_wipe (5065558566939858884) -->
+    <skip />
+    <!-- no translation found for guest_wipe_session_dontwipe (1401113462524894716) -->
+    <skip />
+    <!-- no translation found for guest_notification_title (1585278533840603063) -->
+    <skip />
+    <!-- no translation found for guest_notification_text (335747957734796689) -->
+    <skip />
+    <!-- no translation found for guest_notification_remove_action (8820670703892101990) -->
+    <skip />
+    <!-- no translation found for user_logout_notification_title (1453960926437240727) -->
+    <skip />
+    <!-- no translation found for user_logout_notification_text (3350262809611876284) -->
+    <skip />
+    <!-- no translation found for user_logout_notification_action (1195428991423425062) -->
+    <skip />
+    <!-- no translation found for user_add_user_title (4553596395824132638) -->
+    <!-- no translation found for user_add_user_title (2108112641783146007) -->
+    <skip />
+    <!-- no translation found for user_add_user_message_short (2161624834066214559) -->
+    <!-- no translation found for user_add_user_message_short (1511354412249044381) -->
+    <skip />
+    <!-- no translation found for user_remove_user_title (4681256956076895559) -->
+    <skip />
+    <!-- no translation found for user_remove_user_message (1453218013959498039) -->
+    <skip />
+    <!-- no translation found for user_remove_user_remove (7479275741742178297) -->
+    <skip />
+    <!-- no translation found for battery_saver_notification_title (237918726750955859) -->
+    <skip />
+    <!-- no translation found for battery_saver_notification_text (820318788126672692) -->
+    <skip />
+    <!-- no translation found for battery_saver_notification_action_text (109158658238110382) -->
+    <skip />
+    <!-- no translation found for media_projection_dialog_text (3071431025448218928) -->
+    <skip />
+    <!-- no translation found for media_projection_remember_text (3103510882172746752) -->
+    <skip />
+    <!-- no translation found for clear_all_notifications_text (814192889771462828) -->
+    <skip />
+    <!-- no translation found for media_projection_action_text (8470872969457985954) -->
+    <skip />
+    <!-- no translation found for empty_shade_text (708135716272867002) -->
+    <skip />
+    <!-- no translation found for device_owned_footer (3802752663326030053) -->
+    <skip />
+    <!-- no translation found for profile_owned_footer (8021888108553696069) -->
+    <skip />
+    <!-- no translation found for vpn_footer (2388611096129106812) -->
+    <skip />
+    <!-- no translation found for monitoring_title_device_owned (7121079311903859610) -->
+    <skip />
+    <!-- no translation found for monitoring_title_profile_owned (6790109874733501487) -->
+    <skip />
+    <!-- no translation found for monitoring_title (169206259253048106) -->
+    <skip />
+    <!-- no translation found for disable_vpn (4435534311510272506) -->
+    <skip />
+    <!-- no translation found for disconnect_vpn (1324915059568548655) -->
+    <skip />
+    <!-- no translation found for monitoring_description_device_owned (5780988291898461883) -->
+    <skip />
+    <!-- no translation found for monitoring_description_vpn (4445150119515393526) -->
+    <skip />
+    <!-- no translation found for monitoring_description_vpn_device_owned (3090670777499161246) -->
+    <skip />
+    <!-- no translation found for monitoring_description_vpn_profile_owned (2054949132145039290) -->
+    <skip />
+    <!-- no translation found for legacy_vpn_name (6604123105765737830) -->
+    <skip />
+    <!-- no translation found for monitoring_description_app (6259179342284742878) -->
+    <skip />
+    <!-- no translation found for monitoring_description_app_personal (484599052118316268) -->
+    <skip />
+    <!-- no translation found for monitoring_description_app_work (1754325860918060897) -->
+    <skip />
+    <!-- no translation found for monitoring_description_app_personal_work (4946600443852045903) -->
+    <skip />
+    <!-- no translation found for monitoring_description_vpn_app_device_owned (4970443827043261703) -->
+    <skip />
+    <!-- no translation found for keyguard_indication_trust_disabled (7412534203633528135) -->
+    <skip />
+    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
+    <skip />
+    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
+    <skip />
+    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
+    <skip />
+    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
+    <skip />
+    <!-- no translation found for zen_mode_and_condition (4462471036429759903) -->
+    <skip />
+    <!-- no translation found for volume_zen_end_now (3179845345429841822) -->
+    <skip />
+    <!-- no translation found for accessibility_volume_expand (5946812790999244205) -->
+    <skip />
+    <!-- no translation found for accessibility_volume_collapse (3609549593031810875) -->
+    <skip />
+    <!-- no translation found for screen_pinning_title (3273740381976175811) -->
+    <skip />
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
+    <!-- no translation found for screen_pinning_positive (3783985798366751226) -->
+    <skip />
+    <!-- no translation found for screen_pinning_negative (3741602308343880268) -->
+    <skip />
+    <!-- no translation found for quick_settings_reset_confirmation_title (748792586749897883) -->
+    <skip />
+    <!-- no translation found for quick_settings_reset_confirmation_message (2235970126803317374) -->
+    <skip />
+    <!-- no translation found for quick_settings_reset_confirmation_button (2660339101868367515) -->
+    <skip />
+    <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
+    <skip />
+    <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
+    <skip />
+    <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
+    <skip />
+    <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
+    <skip />
+    <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
+    <skip />
+    <!-- no translation found for group_summary_concadenation (6846402378100148789) -->
+    <skip />
+    <!-- no translation found for managed_profile_foreground_toast (5421487114739245972) -->
+    <skip />
+    <!-- no translation found for system_ui_tuner (708224127392452018) -->
+    <skip />
+    <!-- no translation found for show_battery_percentage (5444136600512968798) -->
+    <skip />
+    <!-- no translation found for show_battery_percentage_summary (3215025775576786037) -->
+    <skip />
+    <!-- no translation found for quick_settings (10042998191725428) -->
+    <skip />
+    <!-- no translation found for status_bar (4877645476959324760) -->
+    <skip />
+    <!-- no translation found for overview (4018602013895926956) -->
+    <skip />
+    <!-- no translation found for demo_mode (2389163018533514619) -->
+    <skip />
+    <!-- no translation found for enable_demo_mode (4844205668718636518) -->
+    <skip />
+    <!-- no translation found for show_demo_mode (2018336697782464029) -->
+    <skip />
+    <!-- no translation found for status_bar_ethernet (5044290963549500128) -->
+    <skip />
+    <!-- no translation found for status_bar_alarm (8536256753575881818) -->
+    <skip />
+    <!-- no translation found for status_bar_work (6022553324802866373) -->
+    <skip />
+    <!-- no translation found for status_bar_airplane (7057575501472249002) -->
+    <skip />
+    <!-- no translation found for add_tile (2995389510240786221) -->
+    <skip />
+    <!-- no translation found for broadcast_tile (3894036511763289383) -->
+    <skip />
+    <!-- no translation found for zen_alarm_warning_indef (3482966345578319605) -->
+    <skip />
+    <!-- no translation found for zen_alarm_warning (444533119582244293) -->
+    <skip />
+    <!-- no translation found for alarm_template (3980063409350522735) -->
+    <skip />
+    <!-- no translation found for alarm_template_far (4242179982586714810) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_detail (2579369091672902101) -->
+    <skip />
+    <!-- no translation found for accessibility_status_bar_hotspot (4099381329956402865) -->
+    <skip />
+    <!-- no translation found for accessibility_managed_profile (6613641363112584120) -->
+    <skip />
+    <!-- no translation found for tuner_warning_title (7094689930793031682) -->
+    <skip />
+    <!-- no translation found for tuner_warning (8730648121973575701) -->
+    <skip />
+    <!-- no translation found for tuner_persistent_warning (8597333795565621795) -->
+    <skip />
+    <!-- no translation found for got_it (2239653834387972602) -->
+    <skip />
+    <!-- no translation found for tuner_toast (603429811084428439) -->
+    <skip />
+    <!-- no translation found for remove_from_settings (8389591916603406378) -->
+    <skip />
+    <!-- no translation found for remove_from_settings_prompt (6069085993355887748) -->
+    <skip />
+    <!-- no translation found for activity_not_found (348423244327799974) -->
+    <skip />
+    <!-- no translation found for clock_seconds (7689554147579179507) -->
+    <skip />
+    <!-- no translation found for clock_seconds_desc (6282693067130470675) -->
+    <skip />
+    <!-- no translation found for qs_rearrange (8060918697551068765) -->
+    <skip />
+    <!-- no translation found for show_brightness (6613930842805942519) -->
+    <skip />
+    <!-- no translation found for experimental (6198182315536726162) -->
+    <skip />
+    <!-- no translation found for enable_bluetooth_title (5027037706500635269) -->
+    <skip />
+    <!-- no translation found for enable_bluetooth_message (9106595990708985385) -->
+    <skip />
+    <!-- no translation found for enable_bluetooth_confirmation_ok (6258074250948309715) -->
+    <skip />
+    <!-- no translation found for apply_to_topic (3641403489318659666) -->
+    <skip />
+    <!-- no translation found for apply_to_app (363016783939815960) -->
+    <skip />
+    <!-- no translation found for blocked_importance (5198578988978234161) -->
+    <skip />
+    <!-- no translation found for low_importance (4109929986107147930) -->
+    <skip />
+    <!-- no translation found for default_importance (8192107689995742653) -->
+    <skip />
+    <!-- no translation found for high_importance (1527066195614050263) -->
+    <skip />
+    <!-- no translation found for max_importance (5089005872719563894) -->
+    <skip />
+    <!-- no translation found for notification_importance_blocked (2397192642657872872) -->
+    <skip />
+    <!-- no translation found for notification_importance_low (4383563267370859725) -->
+    <skip />
+    <!-- no translation found for notification_importance_default (4926529615920610817) -->
+    <skip />
+    <!-- no translation found for notification_importance_high (3222680136612408223) -->
+    <skip />
+    <!-- no translation found for notification_importance_max (5236987171904756134) -->
+    <skip />
+    <!-- no translation found for notification_more_settings (816306283396553571) -->
+    <skip />
+    <!-- no translation found for notification_done (5279426047273930175) -->
+    <skip />
+    <!-- no translation found for color_matrix_none (2121957926040543148) -->
+    <skip />
+    <!-- no translation found for color_matrix_night (5943817622105307072) -->
+    <skip />
+    <!-- no translation found for color_matrix_custom (3655576492322298713) -->
+    <skip />
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatski"</string>
+    <!-- no translation found for color_matrix_unknown (2709202104256265107) -->
+    <skip />
+    <!-- no translation found for color_transform (6985460408079086090) -->
+    <skip />
+    <!-- no translation found for color_matrix_show_qs (1763244354399276679) -->
+    <skip />
+    <!-- no translation found for color_enable_custom (6729001308217347501) -->
+    <skip />
+    <!-- no translation found for color_apply (9212602012641034283) -->
+    <skip />
+    <!-- no translation found for color_revert_title (4746666545480534663) -->
+    <skip />
+    <!-- no translation found for color_revert_message (9116001069397996691) -->
+    <skip />
+    <!-- no translation found for battery_panel_title (3476715163685592453) -->
+    <skip />
+    <!-- no translation found for battery_detail_charging_summary (1279095653533044008) -->
+    <skip />
+    <!-- no translation found for battery_detail_switch_title (6285872470260795421) -->
+    <skip />
+    <!-- no translation found for battery_detail_switch_summary (9049111149407626804) -->
+    <skip />
+    <!-- no translation found for keyboard_shortcut_group_system (6472647649616541064) -->
+    <skip />
+    <!-- no translation found for keyboard_shortcut_group_system_home (3054369431319891965) -->
+    <skip />
+    <!-- no translation found for keyboard_shortcut_group_system_recents (3154851905021926744) -->
+    <skip />
+    <!-- no translation found for keyboard_shortcut_group_system_back (2207004531216446378) -->
+    <skip />
+    <!-- no translation found for tuner_full_zen_title (5905081395132280054) -->
+    <skip />
+    <!-- no translation found for tuner_full_zen_summary (6883568374520596402) -->
+    <skip />
+    <!-- no translation found for volume_and_do_not_disturb (3114580364524650941) -->
+    <skip />
+    <!-- no translation found for volume_down_silent (66962568467719591) -->
+    <skip />
+    <!-- no translation found for volume_up_silent (7141255269783588286) -->
+    <skip />
+    <!-- no translation found for battery (7498329822413202973) -->
+    <skip />
+    <!-- no translation found for clock (7416090374234785905) -->
+    <skip />
+    <!-- no translation found for headset (4534219457597457353) -->
+    <skip />
+    <!-- no translation found for accessibility_status_bar_headphones (9156307120060559989) -->
+    <skip />
+    <!-- no translation found for accessibility_status_bar_headset (8666419213072449202) -->
+    <skip />
+    <!-- no translation found for tuner_status_bar_explanation (9032196769944137864) -->
+    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Ušteda podataka"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Ušteda podataka je uključena"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Ušteda podataka je isključena"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Uključeno"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigaciona traka"</string>
+    <string name="start" msgid="6873794757232879664">"Početak"</string>
+    <string name="center" msgid="4327473927066010960">"Sredina"</string>
+    <string name="end" msgid="125797972524818282">"Kraj"</string>
+    <string name="space" msgid="804232271282109749">"Razmaknica"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Izbornik / Prebacivač tipkovn."</string>
+    <string name="select_button" msgid="1597989540662710653">"Odaberite gumb koji želite dodati"</string>
+    <string name="add_button" msgid="4134946063432258161">"Dodaj gumb"</string>
+    <string name="save" msgid="2311877285724540644">"Sačuvaj"</string>
+    <!-- no translation found for reset (2448168080964209908) -->
+    <skip />
+    <string name="no_home_title" msgid="1563808595146071549">"Gumb za početak nije pronađen."</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Gumb za početak je neophodan za navigaciju ovim uređajem. Dodajte gumb za početak prije pohranjivanja."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Podesite širinu gumba"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Međumemorija"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Međumorija omogućava direktno prebacivanje sadržaja u nju. Sadržaj se isto tako može povući direktno iz međumemorije ako ga ima."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Prilagođeni gumb za navigaciju"</string>
+    <string name="keycode" msgid="7335281375728356499">"Kod tipke"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Gumbovi za kodiranje tipki omogućavaju da se tipke sa tipkovnice dodaju u navigacionu traku. Kada se pritisnu, oni oponašaju izabranu tipku tastature. Kao prvo, tipka mora biti izabrana za dugme, a nakon toga se bira slika koja će biti prikazana na njemu."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Odaberite tipku na tastaturi"</string>
+    <string name="preview" msgid="9077832302472282938">"Pregledaj"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 714b750..7edf3a0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Vora"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"No hi ha cap targeta SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Les dades mòbils estan desactivades"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Ancoratge de Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode d\'avió."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"No hi ha cap targeta SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixació de pantalla"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No s\'ha pogut iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Més"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> més"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Esborra"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisió horitzontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisió vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisió personalitzada"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Colors normals"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Colors nocturns"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Colors personalitzats"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automàtica"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Colors desconeguts"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modificació del color"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostra el mosaic de Configuració ràpida"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculars connectats"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculars connectats"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activa o desactiva les icones a la barra d\'estat."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Economitzador de dades"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"L\'extensió Economitzador de dades està activada"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"L\'extensió Economitzador de dades està desactivada"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Activat"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barra de navegació"</string>
+    <string name="start" msgid="6873794757232879664">"Inici"</string>
+    <string name="center" msgid="4327473927066010960">"Centre"</string>
+    <string name="end" msgid="125797972524818282">"Final"</string>
+    <string name="space" msgid="804232271282109749">"Separador"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Commutador del teclat/menú"</string>
+    <string name="select_button" msgid="1597989540662710653">"Tria un botó per afegir-lo"</string>
+    <string name="add_button" msgid="4134946063432258161">"Afegeix un botó"</string>
+    <string name="save" msgid="2311877285724540644">"Desa"</string>
+    <string name="reset" msgid="2448168080964209908">"Reinicia"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"No s\'ha trobat cap botó d\'inici"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Per poder navegar per aquest dispositiu, cal un botó d\'inici. Afegeix-ne un abans de desar."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Ajusta l\'amplada del botó"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Porta-retalls"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Pots arrossegar elements al porta-retalls directament. Si conté elements, també els pots treure directament arrossegant-los."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Botó de navegació personalitzat"</string>
+    <string name="keycode" msgid="7335281375728356499">"Codi de tecla"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Amb els botons de codi de tecla es poden afegir tecles del teclat a la barra de navegació. En prémer aquests botons es duen a terme les mateixes accions que quan es prem la tecla corresponent. Primer cal seleccionar la tecla del botó i, a continuació, triar la imatge que es mostrarà."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Selecciona un botó de teclat"</string>
+    <string name="preview" msgid="9077832302472282938">"Previsualització"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
deleted file mode 100644
index 8daa867..0000000
--- a/packages/SystemUI/res/values-ca/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Tanca PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
-    <string name="pip_play" msgid="674145557658227044">"Reprodueix"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Posa en pausa"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancel·la"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Mantén premut el botó INICI per controlar PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index dcd42e0..e1d0d0e 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -148,6 +148,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Žádná SIM karta."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobilní data jsou vypnutá"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Sdílené připojení přes Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim Letadlo."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Není vložena SIM karta"</string>
@@ -302,8 +303,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"připnutí obrazovky"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikaci <xliff:g id="APP">%s</xliff:g> nelze spustit."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Další"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"ještě <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historie"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Vymazat"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vodorovné rozdělení"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikální rozdělení"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Vlastní rozdělení"</string>
@@ -469,6 +470,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normální barvy"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Noční barvy"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Vlastní barvy"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automaticky"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Neznámé barvy"</string>
     <string name="color_transform" msgid="6985460408079086090">"Změna barev"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Zobrazit dlaždici Rychlé nastavení"</string>
@@ -495,10 +497,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Sluchátka připojena"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Náhlavní souprava připojena"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Umožňuje aktivovat nebo deaktivovat zobrazení ikon na stavovém řádku."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Spořič dat"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Spořič dat je zapnutý"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Spořič dat je vypnutý"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Zapnuto"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigační panel"</string>
+    <string name="start" msgid="6873794757232879664">"Začátek"</string>
+    <string name="center" msgid="4327473927066010960">"Střed"</string>
+    <string name="end" msgid="125797972524818282">"Konec"</string>
+    <string name="space" msgid="804232271282109749">"Mezerník"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Přepínač nabídky/klávesnice"</string>
+    <string name="select_button" msgid="1597989540662710653">"Vyberte tlačítko"</string>
+    <string name="add_button" msgid="4134946063432258161">"Přidat tlačítko"</string>
+    <string name="save" msgid="2311877285724540644">"Uložit"</string>
+    <string name="reset" msgid="2448168080964209908">"Resetovat"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Nebylo nalezeno tlačítko plochy"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"K navigaci v zařízení je potřeba tlačítko plochy. Před uložením toto tlačítko přidejte."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Upravit šířku tlačítka"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Schránka"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Tlačítko Schránka umožňuje přetahovat položky přímo do schránky. Položky vložené do schránky lze také přetáhnout ven."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Vlastní navigační tlačítko"</string>
+    <string name="keycode" msgid="7335281375728356499">"Klávesa"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Tlačítka Klávesa umožňují přidat na navigační panel klávesy z klávesnice. Když na ně klepnete, budou emulovat vybranou klávesu. K tlačítku je nejprve nutné přiřadit klávesu a poté přidat obrázek tlačítka."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Vyberte klávesu na klávesnici"</string>
+    <string name="preview" msgid="9077832302472282938">"Náhled"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
deleted file mode 100644
index 8675c78..0000000
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Ukončit PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Celá obrazovka"</string>
-    <string name="pip_play" msgid="674145557658227044">"Přehrát"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pozastavit"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Zrušit"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Chcete-li funkci PIP ovládat, podržte tlačítko PLOCHA"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 835ce69..ce7db05 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Intet SIM-kort."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobildata er slået fra."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-netdeling."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Flytilstand."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Der er ikke noget SIM-kort."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"bliv i app"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> kunne ikke startes."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mere"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> mere"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historik"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Ryd"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Opdel vandret"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Opdel lodret"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Opdel brugerdefineret"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Almindelige farver"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Nattefarver"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Tilpassede farver"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatisk"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Ukendte farver"</string>
     <string name="color_transform" msgid="6985460408079086090">"Farveændring"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Vis feltet Hurtige indstillinger"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Hovedtelefoner er tilsluttet"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset er forbundet"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Slå visning af ikoner i statusbjælken til eller fra."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Datasparefunktion"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Datasparefunktionen er slået til"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Datasparefunktionen er slået fra"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Til"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigationslinje"</string>
+    <string name="start" msgid="6873794757232879664">"Start"</string>
+    <string name="center" msgid="4327473927066010960">"I midten"</string>
+    <string name="end" msgid="125797972524818282">"For enden"</string>
+    <string name="space" msgid="804232271282109749">"Mellemrumstast"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menu/tastaturskifter"</string>
+    <string name="select_button" msgid="1597989540662710653">"Vælg den knap, du vil tilføje"</string>
+    <string name="add_button" msgid="4134946063432258161">"Tilføj knap"</string>
+    <string name="save" msgid="2311877285724540644">"Gem"</string>
+    <string name="reset" msgid="2448168080964209908">"Nulstil"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Ingen startknap blev fundet"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Du skal have en startknap for at kunne navigere rundt på denne enhed. Tilføj en startknap, før du gemmer."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Juster knappens bredde"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Udklipsholder"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Med Udklipsholder kan elementerne trækkes direkte til udklipsholderen. Elementerne kan også trækkes direkte ud af udklipsholderen, når den er åben."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Tilpasset navigationsknap"</string>
+    <string name="keycode" msgid="7335281375728356499">"Tastekode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Tastekodeknapper gør det muligt at føje tastaturtaster til navigationslinjen. Når der trykkes på dem, efterligner de den valgte tastaturtast. Først vælges tasten til knappen, og derefter vælges det billede, der skal vises på knappen."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Vælg tastaturknap"</string>
+    <string name="preview" msgid="9077832302472282938">"Eksempelvisning"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
deleted file mode 100644
index a40e34c..0000000
--- a/packages/SystemUI/res/values-da/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Luk PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Fuld skærm"</string>
-    <string name="pip_play" msgid="674145557658227044">"Afspil"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Annuller"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Hold HOME-knappen nede for at styre PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 4888c23..1565521 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WLAN"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Keine SIM-Karte"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobile Datennutzung deaktiviert"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-Tethering"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Flugmodus"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Keine SIM-Karte"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Bildschirmfixierung"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> konnte nicht gestartet werden."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mehr"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> weitere"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Verlauf"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Löschen"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Geteilte Schaltfläche – horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Geteilte Schaltfläche – vertikal"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Geteilte Schaltfläche – benutzerdefiniert"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Standardfarben"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Nachtfarben"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Benutzerdefinierte Farben"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatisch"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Unbekannte Farben"</string>
     <string name="color_transform" msgid="6985460408079086090">"Farben ändern"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Kachel \"Schnelleinstellungen\" anzeigen"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Mit Kopfhörer verbunden"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Mit Headset verbunden"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Symbole in der Statusleiste ein- bzw. ausblenden"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Datenkomprimierung"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Datenkomprimierung aktiviert"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Datenkomprimierung deaktiviert"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"An"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigationsleiste"</string>
+    <string name="start" msgid="6873794757232879664">"Beim Start"</string>
+    <string name="center" msgid="4327473927066010960">"Mitte"</string>
+    <string name="end" msgid="125797972524818282">"Ende"</string>
+    <string name="space" msgid="804232271282109749">"Leerzeichen"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menü-/Tastaturwechsler"</string>
+    <string name="select_button" msgid="1597989540662710653">"Schaltfläche auswählen"</string>
+    <string name="add_button" msgid="4134946063432258161">"Schaltfläche hinzufügen"</string>
+    <string name="save" msgid="2311877285724540644">"Speichern"</string>
+    <string name="reset" msgid="2448168080964209908">"Zurücksetzen"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Startbildschirm-Schaltfläche fehlt"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Zur Bedienung dieses Geräts wird eine Schaltfläche für den Startbildschirm benötigt. Bitte füge vor dem Speichern eine entsprechende Schaltfläche hinzu."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Schaltflächenbreite anpassen"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Zwischenablage"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Elemente können direkt in die Zwischenablage gezogen werden. Ebenso können sie direkt aus der Zwischenablage gezogen werden, sofern diese geöffnet ist."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Benutzerdefinierte Navigationsschaltfläche"</string>
+    <string name="keycode" msgid="7335281375728356499">"Keycode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Mit den Keycode-Schaltflächen können der Navigationsleiste Tasten hinzugefügt werden. Wird eine Keycode-Schaltfläche ausgewählt, führt sie die Aktion der entsprechenden Taste aus. Wählen Sie zuerst die Taste für die Schaltfläche aus und anschließend ein Bild, das auf der Schaltfläche erscheinen soll."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Taste auswählen"</string>
+    <string name="preview" msgid="9077832302472282938">"Vorschau"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
deleted file mode 100644
index 66e3e01..0000000
--- a/packages/SystemUI/res/values-de/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PiP schließen"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Vollbild"</string>
-    <string name="pip_play" msgid="674145557658227044">"Wiedergeben"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pausieren"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Abbrechen"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Halte STARTSEITE gedrückt, um das PiP zu steuern."</string>
-</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 882e5fa..5c31b86 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Δεν υπάρχει SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Τα δεδομένα κινητής τηλεφωνίας είναι απενεργοποιημένα"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Πρόσδεση Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Λειτουργία πτήσης."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Δεν υπάρχει κάρτα SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"καρφίτσωμα οθόνης"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Δεν ήταν δυνατή η εκκίνηση της εφαρμογής <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Περισσότερα"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> ακόμα"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Ιστορικό"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Εκκαθάριση"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Οριζόντιος διαχωρισμός"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Κάθετος διαχωρισμός"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Προσαρμοσμένος διαχωρισμός"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Κανονικά χρώματα"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Νυχτερινά χρώματα"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Προσαρμοσμένα χρώματα"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Αυτόματο"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Άγνωστα χρώματα"</string>
     <string name="color_transform" msgid="6985460408079086090">"Τροποποίηση χρωμάτων"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Εμφάνιση πλακιδίου Γρήγορων ρυθμίσεων"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Τα ακουστικά συνδέθηκαν"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Τα ακουστικά συνδέθηκαν"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ενεργοποίηση ή απενεργοποίηση εμφάνιση εικονιδίων στη γραμμή κατάστασης."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Εξοικονόμηση δεδομένων"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Η Εξοικονόμηση δεδομένων είναι ενεργοποιημένη"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Η Εξοικονόμηση δεδομένων είναι απενεργοποιημένη"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Ενεργή"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Γραμμή πλοήγησης"</string>
+    <string name="start" msgid="6873794757232879664">"Έναρξη"</string>
+    <string name="center" msgid="4327473927066010960">"Κέντρο"</string>
+    <string name="end" msgid="125797972524818282">"Λήξη"</string>
+    <string name="space" msgid="804232271282109749">"Διαχωριστικό"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Εναλλαγή μενού/πληκτρολογίου"</string>
+    <string name="select_button" msgid="1597989540662710653">"Επιλογή κουμπιού για προσθήκη"</string>
+    <string name="add_button" msgid="4134946063432258161">"Προσθήκη κουμπιού"</string>
+    <string name="save" msgid="2311877285724540644">"Αποθήκευση"</string>
+    <string name="reset" msgid="2448168080964209908">"Επαναφορά"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Δεν βρέθηκε κουμπί αρχ. οθόνης"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Απαιτείται κουμπί αρχικής οθόνης για να είναι δυνατή η πλοήγηση σε αυτήν τη συσκευή. Προσθέστε ένα κουμπί αρχικής οθόνης πριν από την αποθήκευση."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Προσαρμογή πλάτους κουμπιού"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Πρόχειρο"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Το Πρόχειρο επιτρέπει να σύρετε στοιχεία απευθείας στο πρόχειρο. Μπορείτε, επίσης, να σύρετε στοιχεία από το πρόχειρο, όταν υπάρχουν στοιχεία σε αυτό."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Προσαρμοσμένο κουμπί πλοήγησης"</string>
+    <string name="keycode" msgid="7335281375728356499">"Κωδικός-πλήκτρο"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Τα κουμπιά κωδικού-πλήκτρου επιτρέπουν την προσθήκη πλήκτρου πληκτρολογίου στη γραμμή πλοήγησης. Όταν τα πατάτε, τα κουμπιά προσομοιώνουν το επιλεγμένη πλήκτρο πληκτρολογίου. Πρώτα πρέπει να επιλεγεί το πλήκτρο για το κουμπί. Στη συνέχεια, εμφανίζεται μια εικόνα στο κουμπί."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Επιλογή κουμπιού πληκτρολογίου"</string>
+    <string name="preview" msgid="9077832302472282938">"Προεπισκόπηση"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
deleted file mode 100644
index 7239386..0000000
--- a/packages/SystemUI/res/values-el/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Κλείσιμο PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Πλήρης οθόνη"</string>
-    <string name="pip_play" msgid="674145557658227044">"Αναπαραγωγή"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Παύση"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Ακύρωση"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Κρατήστε το πλήκτρο HOME πατημένο για να ελέγξετε το PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 6ded945..c2e1d58 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"No SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobile Data Off"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Aeroplane mode"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"No SIM card."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"screen pinning"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"More"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> More"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Clear"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normal colours"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Night colours"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Customised colours"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Unknown colours"</string>
     <string name="color_transform" msgid="6985460408079086090">"Colour modification"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Show Quick Settings tile"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Enable or disable icons from being shown in the status bar."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver is on"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver is off"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"On"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigation bar"</string>
+    <string name="start" msgid="6873794757232879664">"Start"</string>
+    <string name="center" msgid="4327473927066010960">"Centre"</string>
+    <string name="end" msgid="125797972524818282">"End"</string>
+    <string name="space" msgid="804232271282109749">"Spacer"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menu / Keyboard Switcher"</string>
+    <string name="select_button" msgid="1597989540662710653">"Select button to add"</string>
+    <string name="add_button" msgid="4134946063432258161">"Add button"</string>
+    <string name="save" msgid="2311877285724540644">"Savings"</string>
+    <string name="reset" msgid="2448168080964209908">"Reset"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"No home button found"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"A home button is required to be able to navigate this device. Please add a home button before saving."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Adjust button width"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Clipboard"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"The Clipboard allows items to be dragged directly to the clipboard. Items can also be dragged directly out of the clipboard when present."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Customised navigation button"</string>
+    <string name="keycode" msgid="7335281375728356499">"Keycode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Keycode buttons allow keyboard keys to be added to the Navigation Bar. When pressed they emulate the selected keyboard key. First the key must be selected for the button, followed by an image to be shown on the button."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Select Keyboard Button"</string>
+    <string name="preview" msgid="9077832302472282938">"Preview"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
deleted file mode 100644
index 76576dd..0000000
--- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Close PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
-    <string name="pip_play" msgid="674145557658227044">"Play"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancel"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Hold HOME to control PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 6ded945..c2e1d58 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"No SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobile Data Off"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Aeroplane mode"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"No SIM card."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"screen pinning"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"More"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> More"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Clear"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normal colours"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Night colours"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Customised colours"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Unknown colours"</string>
     <string name="color_transform" msgid="6985460408079086090">"Colour modification"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Show Quick Settings tile"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Enable or disable icons from being shown in the status bar."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver is on"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver is off"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"On"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigation bar"</string>
+    <string name="start" msgid="6873794757232879664">"Start"</string>
+    <string name="center" msgid="4327473927066010960">"Centre"</string>
+    <string name="end" msgid="125797972524818282">"End"</string>
+    <string name="space" msgid="804232271282109749">"Spacer"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menu / Keyboard Switcher"</string>
+    <string name="select_button" msgid="1597989540662710653">"Select button to add"</string>
+    <string name="add_button" msgid="4134946063432258161">"Add button"</string>
+    <string name="save" msgid="2311877285724540644">"Savings"</string>
+    <string name="reset" msgid="2448168080964209908">"Reset"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"No home button found"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"A home button is required to be able to navigate this device. Please add a home button before saving."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Adjust button width"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Clipboard"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"The Clipboard allows items to be dragged directly to the clipboard. Items can also be dragged directly out of the clipboard when present."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Customised navigation button"</string>
+    <string name="keycode" msgid="7335281375728356499">"Keycode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Keycode buttons allow keyboard keys to be added to the Navigation Bar. When pressed they emulate the selected keyboard key. First the key must be selected for the button, followed by an image to be shown on the button."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Select Keyboard Button"</string>
+    <string name="preview" msgid="9077832302472282938">"Preview"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
deleted file mode 100644
index 76576dd..0000000
--- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Close PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
-    <string name="pip_play" msgid="674145557658227044">"Play"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancel"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Hold HOME to control PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 6ded945..c2e1d58 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"No SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobile Data Off"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Aeroplane mode"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"No SIM card."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"screen pinning"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Could not start <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"More"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> More"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Clear"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normal colours"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Night colours"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Customised colours"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Unknown colours"</string>
     <string name="color_transform" msgid="6985460408079086090">"Colour modification"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Show Quick Settings tile"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Enable or disable icons from being shown in the status bar."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver is on"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver is off"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"On"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigation bar"</string>
+    <string name="start" msgid="6873794757232879664">"Start"</string>
+    <string name="center" msgid="4327473927066010960">"Centre"</string>
+    <string name="end" msgid="125797972524818282">"End"</string>
+    <string name="space" msgid="804232271282109749">"Spacer"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menu / Keyboard Switcher"</string>
+    <string name="select_button" msgid="1597989540662710653">"Select button to add"</string>
+    <string name="add_button" msgid="4134946063432258161">"Add button"</string>
+    <string name="save" msgid="2311877285724540644">"Savings"</string>
+    <string name="reset" msgid="2448168080964209908">"Reset"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"No home button found"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"A home button is required to be able to navigate this device. Please add a home button before saving."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Adjust button width"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Clipboard"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"The Clipboard allows items to be dragged directly to the clipboard. Items can also be dragged directly out of the clipboard when present."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Customised navigation button"</string>
+    <string name="keycode" msgid="7335281375728356499">"Keycode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Keycode buttons allow keyboard keys to be added to the Navigation Bar. When pressed they emulate the selected keyboard key. First the key must be selected for the button, followed by an image to be shown on the button."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Select Keyboard Button"</string>
+    <string name="preview" msgid="9077832302472282938">"Preview"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
deleted file mode 100644
index 76576dd..0000000
--- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Close PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
-    <string name="pip_play" msgid="674145557658227044">"Play"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancel"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Hold HOME to control PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 0cdb4c6..6318a29 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sin tarjeta SIM"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Los datos móviles están desactivados"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Conexión mediante Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avión"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Sin tarjeta SIM"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Fijar pantalla"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No se pudo iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Más"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> más"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Borrar"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Colores normales"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Colores nocturnos"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Colores personalizados"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automático"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Colores desconocidos"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modificación del color"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar el mosaico de Configuración rápida"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculares conectados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculares conectados"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Habilitar o inhabilitar la visualización de los íconos en la barra de estado"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Reducir datos"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Reducir datos está activada"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Reducir datos está desactivada"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Activado"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
+    <string name="start" msgid="6873794757232879664">"Iniciar"</string>
+    <string name="center" msgid="4327473927066010960">"Centro"</string>
+    <string name="end" msgid="125797972524818282">"Finalizar"</string>
+    <string name="space" msgid="804232271282109749">"Separador"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menú/Cambio de teclado"</string>
+    <string name="select_button" msgid="1597989540662710653">"Elige un botón para agregar"</string>
+    <string name="add_button" msgid="4134946063432258161">"Agregar botón"</string>
+    <string name="save" msgid="2311877285724540644">"Guardar"</string>
+    <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"No se encontró botón de inicio"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Se requiere un botón de inicio para navegar en este dispositivo. Agrega un botón de inicio antes de guardar el contenido."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Ajustar ancho del botón"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Portapapeles"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"El botón de Portapapeles permite arrastrar elementos directamente hacia el portapapeles, y fuera de él cuando estén presentes."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Botón de navegación personalizado"</string>
+    <string name="keycode" msgid="7335281375728356499">"Clave de código"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Los botones de las claves de código permiten agregar las teclas del teclado a la Barra de navegación. Al presionarlas, emulan la tecla seleccionada. Primero, debes elegir la tecla para el botón y, luego, asignarle una imagen."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Selecciona un botón del teclado"</string>
+    <string name="preview" msgid="9077832302472282938">"Vista previa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
deleted file mode 100644
index 9b0a055..0000000
--- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Cerrar PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
-    <string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancelar"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Mantén presionado el botón INICIO para controlar PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index cd5c95a..75370bd 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Tipo Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sin tarjeta SIM"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Datos móviles desactivados"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Compartir por Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avión"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"No hay tarjeta SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fijación de pantalla"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No se ha podido iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Más"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> más"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Borrar"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Colores normales"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Colores nocturnos"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Colores personalizados"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automático"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Colores desconocidos"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modificación de colores"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar mosaico de Ajustes rápidos"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculares conectados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculares conectados"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Permite mostrar u ocultar iconos en la barra de estado"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Economizador de datos"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Economizador de datos activado"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Economizador de datos desactivado"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Sí"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
+    <string name="start" msgid="6873794757232879664">"Inicio"</string>
+    <string name="center" msgid="4327473927066010960">"Centro"</string>
+    <string name="end" msgid="125797972524818282">"Fin"</string>
+    <string name="space" msgid="804232271282109749">"Espacio"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menú/Cambio de teclado"</string>
+    <string name="select_button" msgid="1597989540662710653">"Selecciona botón para añadirlo"</string>
+    <string name="add_button" msgid="4134946063432258161">"Añadir botón"</string>
+    <string name="save" msgid="2311877285724540644">"Guardar"</string>
+    <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Botón de inicio no encontrado"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Se necesita un botón de inicio para poder navegar por el dispositivo. Añádelo antes de guardar."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Ajustar el ancho del botón"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Portapapeles"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Con este botón puedes arrastrar los elementos directamente al portapapeles y, si está presente, fuera de él."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Botón de navegación personalizada"</string>
+    <string name="keycode" msgid="7335281375728356499">"Código de teclado"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Con los botones del código de teclado puedes añadir teclas a la barra de navegación que, al pulsarlas, emulan la tecla seleccionada. Primero debes seleccionar la tecla para el botón y, a continuación, la imagen que se va a mostrar en él."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Selecciona un botón de teclado"</string>
+    <string name="preview" msgid="9077832302472282938">"Vista previa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
deleted file mode 100644
index b9649f9..0000000
--- a/packages/SystemUI/res/values-es/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Cerrar PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
-    <string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancelar"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Mantén pulsado el botón INICIO para controlar PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 52fc39e..2f22c64 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Serv"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WiFi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM-kaarti pole."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobiilne andmeside on välja lülitatud"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetoothi jagamine."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Lennurežiim."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM-kaarti pole."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekraanikuva kinnitamine"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Rakendust <xliff:g id="APP">%s</xliff:g> ei saanud käivitada."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Rohkem"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Veel <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Ajalugu"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Kustuta"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horisontaalne poolitamine"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikaalne poolitamine"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Kohandatud poolitamine"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Tavalised värvid"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Öised värvid"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Kohandatud värvid"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automaatne"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Värvid on teadmata"</string>
     <string name="color_transform" msgid="6985460408079086090">"Värvi muutmine"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Kuva paan Kiirseaded"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Kõrvaklapid on ühendatud"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Peakomplekt on ühendatud"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Lubatakse või keelatakse ikoonide kuvamine olekuribal."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Andmemahu säästja"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Andmemahu säästja on sisse lülitatud"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Andmemahu säästja on välja lülitatud"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Sees"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigeerimisriba"</string>
+    <string name="start" msgid="6873794757232879664">"Algus"</string>
+    <string name="center" msgid="4327473927066010960">"Keskkoht"</string>
+    <string name="end" msgid="125797972524818282">"Lõpp"</string>
+    <string name="space" msgid="804232271282109749">"Tühik"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menüü / klaviatuuri vahetaja"</string>
+    <string name="select_button" msgid="1597989540662710653">"Lisatava nupu valimine"</string>
+    <string name="add_button" msgid="4134946063432258161">"Lisa nupp"</string>
+    <string name="save" msgid="2311877285724540644">"Salvesta"</string>
+    <string name="reset" msgid="2448168080964209908">"Lähtesta"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Avaekraani nuppu ei leitud"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Seadmes navigeerimiseks on vajalik avaekraani nupp. Lisage enne salvestamist avaekraani nupp."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Nupu laiuse reguleerimine"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Lõikelaud"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Lõikelaud võimaldab üksused lohistada otse lõikelauale. Kui üksused on lõikelaual, saab need sealt ka ära lohistada."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Kohandatud navigeerimisnupp"</string>
+    <string name="keycode" msgid="7335281375728356499">"Võtmekood"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Võtmekoodi nupud võimaldavad klaviatuuriklahvid lisada navigeerimisribale. Nupu vajutamisel jäljendavad need valitud klaviatuuriklahvi. Esmalt tuleb nupu jaoks valida klahv ja seejärel kujutis, mis nupul kuvada."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Klaviatuuri nupu valimine"</string>
+    <string name="preview" msgid="9077832302472282938">"Eelvaade"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings_tv.xml b/packages/SystemUI/res/values-et-rEE/strings_tv.xml
deleted file mode 100644
index 8af5984..0000000
--- a/packages/SystemUI/res/values-et-rEE/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Sule PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Täisekraan"</string>
-    <string name="pip_play" msgid="674145557658227044">"Esita"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Peata"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Tühista"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP juhtimiseks hoidke all nuppu AVAEKRAAN"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 06a43f6..aa2c5be 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi konexioa"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Ez dago SIM txartelik."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Desaktibatuta dago datu-konexioa"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Konexioa partekatzea (Bluetooth)"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Hegaldi-modua"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Ez dago SIM txartelik."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pantaila-ainguratzea"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"bilatu"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Ezin izan da hasi <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Gehiago"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Beste <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Garbitu"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Banaketa horizontala"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Banaketa bertikala"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Banaketa pertsonalizatua"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Kolore normalak"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Gaueko koloreak"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Kolore pertsonalizatuak"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatikoa"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Kolore ezezagunak"</string>
     <string name="color_transform" msgid="6985460408079086090">"Kolore-aldaketa"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Erakutsi ezarpen bizkorren lauza"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Aurikularrak konektatu dira"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Mikrofonodun entzungailua konektatu da"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Gaitu edo desgaitu ikonoak egoera-barran erakusteko aukera."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Datu-aurrezlea"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Aktibatuta dago datu-aurrezlea"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Desaktibatuta dago datu-aurrezlea"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Aktibatuta"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Nabigazio-barra"</string>
+    <string name="start" msgid="6873794757232879664">"Hasi"</string>
+    <string name="center" msgid="4327473927066010960">"Erdiratu"</string>
+    <string name="end" msgid="125797972524818282">"Amaitu"</string>
+    <string name="space" msgid="804232271282109749">"Bereizgailua"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menu- edo teklatu-aldatzailea"</string>
+    <string name="select_button" msgid="1597989540662710653">"Hautatu gehitu beharreko botoia"</string>
+    <string name="add_button" msgid="4134946063432258161">"Gehitu botoia"</string>
+    <string name="save" msgid="2311877285724540644">"Gorde"</string>
+    <string name="reset" msgid="2448168080964209908">"Berrezarri"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Ez da aurkitu hasiera-botoirik"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Hasiera-botoia behar da gailuan ibiltzeko. Gorde aurretik, gehi ezazu bat."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Doitu botoiaren zabalera"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Arbela"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Arbelari esker, elementuak arbelera zuzenean arrasta daitezke. Elementuak arbelean daudenean, handik zuzenean atera daitezke."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Nabigazio-botoi pertsonalizatua"</string>
+    <string name="keycode" msgid="7335281375728356499">"Tekla-kodea"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Tekla-kodeko botoiekin, teklatuko teklak gehi daitezke nabigazio-barran. Sakatzen direnean, hautatutako teklaren funtzioa gauzatzen dute. Lehendabizi, botoiaren tekla hautatu behar da eta, gero, botoian agertuko den irudia."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Hautatu teklatuko botoia"</string>
+    <string name="preview" msgid="9077832302472282938">"Aurrebista"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings_tv.xml b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
deleted file mode 100644
index be2053e..0000000
--- a/packages/SystemUI/res/values-eu-rES/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Itxi pantaila txikia"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantaila osoa"</string>
-    <string name="pip_play" msgid="674145557658227044">"Erreproduzitu"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pausatu"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Utzi"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Eduki sakatuta hasierako botoia pantaila txikia kontrolatzeko"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 0af19ba..67f3fab 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"بدون سیم کارت."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"داده تلفن همراه خاموش است"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"اتصال اینترنت با بلوتوث تلفن همراه."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"حالت هواپیما."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"سیم‌کارتی موجود نیست."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"پین کردن صفحه"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> شروع نشد."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"بیشتر"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> مورد دیگر"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"سابقه"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"پاک کردن"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"تقسیم افقی"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"تقسیم عمودی"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"سفارشی کردن تقسیم"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"رنگ‌های عادی"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"رنگ‌های شب"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"رنگ‌های سفارشی"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"خودکار"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"رنگ‌های نامشخص"</string>
     <string name="color_transform" msgid="6985460408079086090">"اصلاح رنگ"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"نمایش کاشی تنظیمات سریع"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"هدفون وصل شد"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"هدست وصل شد"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"فعال یا غیرفعال کردن نمایش نمادها در نوار وضعیت."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"صرفه‌جویی در مصرف داده"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"صرفه‌جویی در مصرف داده روشن است"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"صرفه‌جویی در مصرف داده خاموش است"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"روشن"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"نوار پیمایش"</string>
+    <string name="start" msgid="6873794757232879664">"شروع"</string>
+    <string name="center" msgid="4327473927066010960">"وسط"</string>
+    <string name="end" msgid="125797972524818282">"پایان"</string>
+    <string name="space" msgid="804232271282109749">"جداکننده"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"جابه‌جاکننده منو / صفحه‌کلید"</string>
+    <string name="select_button" msgid="1597989540662710653">"دکمه را برای افزودن انتخاب کنید"</string>
+    <string name="add_button" msgid="4134946063432258161">"دکمه افزودن"</string>
+    <string name="save" msgid="2311877285724540644">"ذخیره کردن"</string>
+    <string name="reset" msgid="2448168080964209908">"بازنشانی"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"دکمه صفحه اصلی‌ای پیدا نشد"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"برای پیمایش در این دستگاه به دکمه صفحه اصلی نیاز است. لطفاً قبل از ذخیره کردن، یک دکمه صفحه اصلی اضافه کنید."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"تنظیم پهنای دکمه"</string>
+    <string name="clipboard" msgid="1313879395099896312">"کلیپ‌بورد"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"«کلیپ‌بورد» امکان می‌دهد موارد به‌طور مستقیم به کلیپ‌بورد کشیده شوند. اگر مواردی در کلیپ‌بورد وجود داشته باشند می‌توانند به‌طور مستقیم به خارج از آن نیز کشیده شوند."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"دکمه پیمایش سفارشی"</string>
+    <string name="keycode" msgid="7335281375728356499">"کد کلید"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"دکمه «کد دکمه» به کلیدهای صفحه‌کلید امکان می‌دهند به «نوار پیمایش» اضافه شوند. وقتی فشار داده می‌شوند رفتار کلید صفحه‌کلید انتخاب‌شده را تقلید می‌کنند. ابتدا باید کلید را برای دکمه انتخاب کرد و به دنبال آن باید تصویری برای نشان داده شدن روی دکمه انتخاب شود."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"کلید صفحه‌کلید را انتخاب کنید"</string>
+    <string name="preview" msgid="9077832302472282938">"پیش‌نمایش"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
deleted file mode 100644
index b7c4e61..0000000
--- a/packages/SystemUI/res/values-fa/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"‏بستن PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"تمام صفحه"</string>
-    <string name="pip_play" msgid="674145557658227044">"پخش"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"مکث"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"لغو"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"‏نگه‌داشتن HOME برای کنترل PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 327e1df..6e3d740 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Ei SIM-korttia."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobiilidata pois päältä"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Internetin jakaminen Bluetoothin kautta."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Lentokonetila."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Ei SIM-korttia."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"näytön kiinnitys"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Sovelluksen <xliff:g id="APP">%s</xliff:g> käynnistäminen epäonnistui."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Lisää"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"+<xliff:g id="NUMBER">%d</xliff:g> lisää"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Tyhjennä"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vaakasuuntainen jako"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pystysuuntainen jako"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Muokattu jako"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Tavalliset värit"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Yövärit"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Muokatut värit"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automaattinen"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Tuntemattomat värit"</string>
     <string name="color_transform" msgid="6985460408079086090">"Muokatut värit"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Näytä pika-asetusruutu"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Kuulokkeet liitetty"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Kuulokemikrofoni liitetty"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ota tilapalkin kuvakkeet käyttöön tai poista ne käytöstä."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver on käytössä."</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver on pois käytöstä."</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Käytössä"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigointipalkki"</string>
+    <string name="start" msgid="6873794757232879664">"Alussa"</string>
+    <string name="center" msgid="4327473927066010960">"Keskellä"</string>
+    <string name="end" msgid="125797972524818282">"Lopussa"</string>
+    <string name="space" msgid="804232271282109749">"Tyhjä väli"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Valikko/Näppäimistövalitsin"</string>
+    <string name="select_button" msgid="1597989540662710653">"Valitse lisättävä painike"</string>
+    <string name="add_button" msgid="4134946063432258161">"Lisää painike"</string>
+    <string name="save" msgid="2311877285724540644">"Tallenna"</string>
+    <string name="reset" msgid="2448168080964209908">"Palauta"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Ei aloitusnäyttöpainiketta"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Laitteessa navigointi edellyttää aloitusnäyttöpainiketta. Lisää aloitusnäyttöpainike ennen tallentamista."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Muokkaa painikkeen leveyttä"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Leikepöytä"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Leikepöytä sallii kohteiden vetämisen suoraan leikepöydälle. Kohteet voi vetää myös suoraan pois leikepöydältä, kun se on käytössä."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Muokattu navigointipainike"</string>
+    <string name="keycode" msgid="7335281375728356499">"Näppäinkoodi"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Näppäinkoodi-painikkeet sallivat näppäimistön näppäimien lisäämisen navigointipalkkiin. Kun painiketta painetaan, se jäljittelee valittua näppäintä. Valitse ensin painikkeen kohteena oleva näppäin, sitten painikkeessa näkyvä kuva."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Valitse näppäimistön näppäin"</string>
+    <string name="preview" msgid="9077832302472282938">"Esikatselu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
deleted file mode 100644
index d39c37f..0000000
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Sulje PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Koko näyttö"</string>
-    <string name="pip_play" msgid="674145557658227044">"Toista"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Keskeytä"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Peruuta"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Hallinnoi PIP-tilaa painamalla Aloitusnäyttö-painiketta pitkään."</string>
-</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 7ebb5ab..d85662d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Aucune carte SIM"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Données cellulaires déésactivées"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Partage de connexion Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode Avion"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Aucune carte SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Plus"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> autres"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historique"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Effacer"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Couleurs normales"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Couleurs nocturnes"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Couleurs personnalisées"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatique"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Couleurs inconnues"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modifier la couleur"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Afficher la tuile de configuration rapide"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Écouteurs connectés"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Écouteurs connectés"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activer ou désactiver l\'affichage des icônes dans la barre d\'état"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Économiseur de données"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"La fonction Économiseur de données est activée"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"La fonction Économiseur de données est désactivée"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Activé"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barre de navigation"</string>
+    <string name="start" msgid="6873794757232879664">"Démarrer"</string>
+    <string name="center" msgid="4327473927066010960">"Centrer"</string>
+    <string name="end" msgid="125797972524818282">"Fin"</string>
+    <string name="space" msgid="804232271282109749">"Espace"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Sélecteur menu/clavier"</string>
+    <string name="select_button" msgid="1597989540662710653">"Sélectionnez le bouton à ajouter"</string>
+    <string name="add_button" msgid="4134946063432258161">"Ajouter un bouton"</string>
+    <string name="save" msgid="2311877285724540644">"Enregistrer"</string>
+    <string name="reset" msgid="2448168080964209908">"Réinitialiser"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Aucune touche d\'accueil"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Une touche d\'accueil est nécessaire pour naviguer sur cet appareil. Veuillez ajouter une touche d\'accueil avant d\'enregistrer."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Ajuster la largeur du bouton"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Presse-papiers"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Vous pouvez faire glisser des éléments directement dans le presse-papiers, et inversement."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Bouton de navigation personnalisé"</string>
+    <string name="keycode" msgid="7335281375728356499">"Code de touche"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Les boutons de codes de touche permettent d\'ajouter des touches du clavier à la barre de navigation. Lorsque vous appuyez sur l\'un de ces boutons, il reproduit la fonction du clavier correspondante. Vous devez d\'abord sélectionner la touche pour le bouton, puis l\'image à afficher sur celui-ci."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Sélectionnez la touche du clavier"</string>
+    <string name="preview" msgid="9077832302472282938">"Aperçu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_car.xml b/packages/SystemUI/res/values-fr-rCA/strings_car.xml
index 209773b..10e1fd5 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_car.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_car.xml
@@ -19,6 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Conduire en toute sécurité"</string>
+    <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Conduisez prudemment"</string>
     <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Tenez compte des conditions de la route et respectez toujours les lois en vigueur. Les itinéraires peuvent être incorrects, incomplets, dangereux, inappropriés ou interdits, et ils peuvent traverser des zones administratives. Les renseignements sur les entreprises peuvent également être incorrects ou incomplets. Les données ne sont pas fournies en temps réel, et la précision de la localisation n\'est pas garantie. Ne manipulez pas votre appareil mobile et n\'utilisez pas d\'applications non conçues pour Android Auto lorsque vous conduisez."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
deleted file mode 100644
index c06e492..0000000
--- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Fermer le mode PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Plein écran"</string>
-    <string name="pip_play" msgid="674145557658227044">"Lecture"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Interrompre"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Annuler"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Maintenez enfoncée la touche ACCUEIL gérer le mode PIP."</string>
-</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d16f680..62fe2c7 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Aucune carte SIM"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Données mobiles désactivées"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Partage de connexion Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode Avion"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Aucune carte SIM"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Plus"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> autres"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historique"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Effacer"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Couleurs normales"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Couleurs nocturnes"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Couleurs personnalisées"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatique"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Couleurs inconnues"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modification des couleurs"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Afficher la tuile de configuration rapide"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Casque connecté"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Casque connecté"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activer ou désactiver l\'affichage des icônes dans la barre d\'état"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Économiseur de données"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"L\'économiseur de données est activé."</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"L\'économiseur de données est désactivé."</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Activé"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barre de navigation"</string>
+    <string name="start" msgid="6873794757232879664">"Début"</string>
+    <string name="center" msgid="4327473927066010960">"Centre"</string>
+    <string name="end" msgid="125797972524818282">"Fin"</string>
+    <string name="space" msgid="804232271282109749">"Espace"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Sélecteur menu/clavier"</string>
+    <string name="select_button" msgid="1597989540662710653">"Sélectionner le bouton à ajouter"</string>
+    <string name="add_button" msgid="4134946063432258161">"Ajouter un bouton"</string>
+    <string name="save" msgid="2311877285724540644">"Enregistrer"</string>
+    <string name="reset" msgid="2448168080964209908">"Réinitialiser"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Aucun bouton d\'accueil trouvé"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Un bouton d\'accueil est nécessaire pour naviguer sur cet appareil. Veuillez ajouter un bouton d\'accueil avant d\'enregistrer."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Ajuster la largeur du bouton"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Presse-papiers"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Vous pouvez faire glisser des éléments directement dans le Presse-papiers et inversement."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Bouton de navigation personnalisé"</string>
+    <string name="keycode" msgid="7335281375728356499">"Code de touche"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Les boutons de codes de touche permettent d\'ajouter des touches du clavier à la barre de navigation. Lorsque vous appuyez sur l\'un de ces boutons, il reproduit la fonction de la touche du clavier correspondante. Vous devez d\'abord sélectionner la touche pour le bouton, puis l\'image à afficher sur celui-ci."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Sélectionner la touche du clavier"</string>
+    <string name="preview" msgid="9077832302472282938">"Aperçu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
deleted file mode 100644
index bf7306e..0000000
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Fermer le mode PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Plein écran"</string>
-    <string name="pip_play" msgid="674145557658227044">"Lire"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Suspendre"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Annuler"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Appuyez de manière prolongée sur \"ACCUEIL\" pour contrôler le mode PIP."</string>
-</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index fad6b43..831228e 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sen SIM"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Os datos móbiles están desactivados"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Ancoraxe de Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avión"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Non hai tarxeta SIM"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixación de pantalla"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Non foi posible iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Máis"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> máis"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historial"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Borrar"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dividir en horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dividir en vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dividir de xeito personalizado"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Cores normais"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Cores nocturnas"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Cores personalizadas"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automático"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Cores descoñecidas"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modificación de cor"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar mosaico de configuración rápida"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Conectáronse os auriculares"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Conectáronse os auriculares"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activa ou desactiva a visualización das iconas na barra de estado."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Economizador de datos"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"O economizador de datos está activado"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"O economizador de datos está desactivado"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Activar"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barra de navegación"</string>
+    <string name="start" msgid="6873794757232879664">"Inicio"</string>
+    <string name="center" msgid="4327473927066010960">"Centro"</string>
+    <string name="end" msgid="125797972524818282">"Fin"</string>
+    <string name="space" msgid="804232271282109749">"Barra espazadora"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Conmutador menú/teclado"</string>
+    <string name="select_button" msgid="1597989540662710653">"Selecciona o botón a engadir"</string>
+    <string name="add_button" msgid="4134946063432258161">"Engadir botón"</string>
+    <string name="save" msgid="2311877285724540644">"Gardar"</string>
+    <string name="reset" msgid="2448168080964209908">"Restablecer"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Botón de inicio non encontrado"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Necesítase un botón de inicio para navegar neste dispositivo. Engade un botón de inicio antes da acción de gardar."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Axustar o ancho do botón"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Portapapeis"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Pódense arrastrar elementos directamente ao portapapeis. Tamén se poden arrastrar directamente fóra del."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Botón de navegación personalizada"</string>
+    <string name="keycode" msgid="7335281375728356499">"Código de teclas"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Os botóns de código de teclas permiten engadir teclas do teclado á barra de navegación. Ao premelos, emulan a tecla seleccionada. Primeiro, debes seleccionar unha tecla para o botón e escoller a imaxe que se mostrará nel."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Selecciona o botón do teclado"</string>
+    <string name="preview" msgid="9077832302472282938">"Vista previa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings_tv.xml b/packages/SystemUI/res/values-gl-rES/strings_tv.xml
deleted file mode 100644
index 857911d..0000000
--- a/packages/SystemUI/res/values-gl-rES/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Pechar PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
-    <string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancelar"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Manter premido INICIO para controlar PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 576c332..20d48a4 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM નથી."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"સેલ્યુલર ડેટા બંધ છે"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth ટિથરિંગ."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"એરપ્લેન મોડ."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"કોઇ SIM કાર્ડ નથી."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"સ્ક્રીન પિનિંગ"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"શોધ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> પ્રારંભ કરી શકાયું નથી."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"વધુ"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> વધુ"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ઇતિહાસ"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"સાફ કરો"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"આડું વિભક્ત કરો"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ઊભું વિભક્ત કરો"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"કસ્ટમ વિભક્ત કરો"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"સામાન્ય રંગો"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"રાત્રિ રંગો"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"કસ્ટમ રંગો"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"સ્વતઃ"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"અજાણ્યા રંગો"</string>
     <string name="color_transform" msgid="6985460408079086090">"રંગ સંશોધન"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"ઝડપી સેટિંગ્સ ટાઇલ બતાવો"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"હેડફોન કનેક્ટ કર્યાં"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"હેડસેટ કનેક્ટ કર્યો"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"સ્થિતિ બારમાં બતાવવામાં આવતા આઇકન્સને સક્ષમ અથવા અક્ષમ કરો."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"ડેટા સેવર"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ડેટા સેવર ચાલુ છે"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ડેટા સેવર બંધ છે"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"ચાલુ"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"નેવિગેશન બાર"</string>
+    <string name="start" msgid="6873794757232879664">"પ્રારંભ કરો"</string>
+    <string name="center" msgid="4327473927066010960">"મધ્ય"</string>
+    <string name="end" msgid="125797972524818282">"સમાપ્ત"</string>
+    <string name="space" msgid="804232271282109749">"સ્પેસર"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"મેનૂ / કીબોર્ડ સ્વિચર"</string>
+    <string name="select_button" msgid="1597989540662710653">"ઉમેરવા માટે બટન પસંદ કરો"</string>
+    <string name="add_button" msgid="4134946063432258161">"બટન ઉમેરો"</string>
+    <string name="save" msgid="2311877285724540644">"સાચવો"</string>
+    <string name="reset" msgid="2448168080964209908">"ફરીથી સેટ કરો"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"કોઈ હોમ બટન મળ્યું નથી"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"આ ઉપકરણને નેવિગેટ કરવા માટે હોમ બટન આવશ્યક. કૃપા કરીને સાચવતાં પહેલાં એક હોમ બટન ઉમેરો."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"બટનની પહોળાઈ સમાયોજિત કરો"</string>
+    <string name="clipboard" msgid="1313879395099896312">"ક્લિપબોર્ડ"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"ક્લિપબોર્ડ આઇટમ્સને સીધા જ ક્લિપબોર્ડ પર ખેંચવાની મંજૂરી આપે છે. જ્યારે હાજર હોય ત્યારે આઇટમ્સ ક્લિપબોર્ડ પરથી સીધી જ બહાર પણ ખેંચી શકાય છે."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"કસ્ટમ નેવિગેશન બટન"</string>
+    <string name="keycode" msgid="7335281375728356499">"કીકોડ"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"કીકોડ બટન કીબોર્ડની કીઝને નેવિગેશન બારમાં ઉમેરવાની મંજૂરી આપે છે. જ્યારે દબાવવામાં આવે ત્યારે તે પસંદ કરેલ કીબોર્ડની કીનું અનુસરણ કરે છે. બટન માટે પહેલા કીબોર્ડની કીઝને પસંદ કરવી આવશ્યક છે, તે પછી બટન પર બતાવવામાં આવેલ છબી પસંદ કરવી આવશ્યક છે."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"કીબોર્ડ બટન પસંદ કરો"</string>
+    <string name="preview" msgid="9077832302472282938">"પૂર્વાવલોકન કરો"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
deleted file mode 100644
index fbb9a4f..0000000
--- a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP બંધ કરો"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"પૂર્ણ સ્ક્રીન"</string>
-    <string name="pip_play" msgid="674145557658227044">"ચલાવો"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"થોભાવો"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"રદ કરો"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP નિયંત્રિત કરવા માટે હોમ પકડી રાખો"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 5d97aa6..25356c8 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"किनारा"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"वाई-फ़ाई"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"कोई सिम नहीं."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"सेल्‍युलर डेटा बंद है"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ब्लूटूथ टेदरिंग."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"हवाई जहाज मोड."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"कोई सिम कार्ड नहीं है."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करना"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ नहीं किया जा सका."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"अधिक"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> अधिक"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"इतिहास"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"साफ़ करें"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज रूप से विभाजित करें"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"लम्बवत रूप से विभाजित करें"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"कस्‍टम रूप से विभाजित करें"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"सामान्य रंग"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"रात्रि के रंग"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"कस्टम रंग"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"स्वतः"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"अज्ञात रंग"</string>
     <string name="color_transform" msgid="6985460408079086090">"रंग परिवर्तन"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"त्‍वरित-सेटिंग टाइल दिखाएं"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफ़ोन कनेक्‍ट किए गए"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हैडसेट कनेक्‍ट किया गया"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"आइकन को स्‍थिति बार में दिखाए जाने से सक्षम या अक्षम करें."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"डेटा बचतकर्ता"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा बचतकर्ता चालू है"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा बचतकर्ता बंद है"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"चालू"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"नेविगेशन बार"</string>
+    <string name="start" msgid="6873794757232879664">"प्रारंभ करें"</string>
+    <string name="center" msgid="4327473927066010960">"मध्‍य"</string>
+    <string name="end" msgid="125797972524818282">"समाप्त"</string>
+    <string name="space" msgid="804232271282109749">"स्‍पेसर"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"मेनू / कीबोर्ड स्‍विचर"</string>
+    <string name="select_button" msgid="1597989540662710653">"जोड़ने के लिए बटन चुनें"</string>
+    <string name="add_button" msgid="4134946063432258161">"बटन जोड़ें"</string>
+    <string name="save" msgid="2311877285724540644">"सहेजें"</string>
+    <string name="reset" msgid="2448168080964209908">"रीसेट करें"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"कोई होम बटन नहीं मिला"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"इस डिवाइस को नेविगट करने के लिए होम बटन आवश्‍यक है. कृपया सहेजने के पहले होम बटन जोड़ें."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"बटन की चौड़ाई समायोजित करें"</string>
+    <string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"क्‍लिपबोर्ड आइटम सीधे क्‍लिपबोर्ड में खींचने देता है. मौजूद होने पर आइटम क्‍लिपबोर्ड से सीधे बाहर भी खींचे जा सकते हैं."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"कस्‍टम मार्गदर्शक बटन"</string>
+    <string name="keycode" msgid="7335281375728356499">"कुंजी कोड"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"कुंजी कोड बटन कीबोर्ड कुंजियों को मार्गदर्शक बार में जोड़ने देती हैं. दबाए जाने पर वे चयनित कीबोर्ड कुंजी का अनुकरण करते हैं. सबसे पहले, बटन के लिए कुंजी का चयन करना चाहिए, उसके बाद बटन पर दिखाए जाने वाले चित्र का चयन करना चाहिए."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"कीबोर्ड बटन चुनें"</string>
+    <string name="preview" msgid="9077832302472282938">"पूर्वावलोकन"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
deleted file mode 100644
index 780725d..0000000
--- a/packages/SystemUI/res/values-hi/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP बंद करें"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्‍क्रीन"</string>
-    <string name="pip_play" msgid="674145557658227044">"चलाएं"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"रोकें"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"अभी नहीं"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP को नियंत्रित करने के लिए होम पर रुकें"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index d96c308..746ae26 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -147,6 +147,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nema SIM kartice."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobilni podaci isključeni"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Posredno povezivanje Bluetootha."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Način rada u zrakoplovu"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Nema SIM kartice."</string>
@@ -301,8 +302,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"prikvačivanje zaslona"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Više"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Još <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Povijest"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Izbriši"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podijeli vodoravno"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podijeli okomito"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podijeli prilagođeno"</string>
@@ -468,6 +469,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Uobičajene boje"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Noćne boje"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Prilagođene boje"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatski"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Nepoznate boje"</string>
     <string name="color_transform" msgid="6985460408079086090">"Izmjena boja"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Prikaži pločicu s brzim postavkama"</string>
@@ -494,10 +496,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalice su povezane"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Slušalice su povezane"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Omogućuje ili onemogućuje prikazivanje ikona na traci statusa."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Ušteda podataka"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Ušteda podataka je uključena"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Ušteda podataka je isključena"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Uključeno"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigacijska traka"</string>
+    <string name="start" msgid="6873794757232879664">"Početak"</string>
+    <string name="center" msgid="4327473927066010960">"Sredina"</string>
+    <string name="end" msgid="125797972524818282">"Kraj"</string>
+    <string name="space" msgid="804232271282109749">"Razmak"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Izmjena izbornika/tipkovnice"</string>
+    <string name="select_button" msgid="1597989540662710653">"Odaberite gumb za dodavanje"</string>
+    <string name="add_button" msgid="4134946063432258161">"Dodaj gumb"</string>
+    <string name="save" msgid="2311877285724540644">"Spremi"</string>
+    <string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Nema gumba početnog zaslona"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Da biste se mogli kretati ovim uređajem, potreban je gumb početnog zaslona. Dodajte gumb početnog zaslona prije spremanja."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Prilagodite širinu gumba"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Međuspremnik"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Međuspremnik omogućuje povlačenje stavki izravno u međuspremnik. Stavke se mogu i izravno povlačiti iz međuspremnika ako se nalaze u njemu."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Prilagođeni navigacijski gumb"</string>
+    <string name="keycode" msgid="7335281375728356499">"Kôd tipke"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Gumbi koda tipke omogućuju dodavanje tipki tipkovnice na navigacijsku traku. Kada ih se pritisne, oni emuliraju odabranu tipku tipkovnice. Prvo se mora odabrati tipka za gumb, a nakon toga na gumbu će se pojaviti slika."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Odaberite gumb tipkovnice"</string>
+    <string name="preview" msgid="9077832302472282938">"Pregled"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
deleted file mode 100644
index e87d880..0000000
--- a/packages/SystemUI/res/values-hr/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Zatvori PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Cijeli zaslon"</string>
-    <string name="pip_play" msgid="674145557658227044">"Reproduciraj"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pauziraj"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Odustani"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Držite POČETNI ZASLON da biste kontrolirali PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 0f4c31b..d1e117f 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nincs SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobiladat-kapcsolat kikapcsolva"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth megosztása."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Repülőgép üzemmód."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Nincs SIM kártya."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"képernyő rögzítése"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nem lehet elindítani a következőt: <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Továbbiak"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> további"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Előzmények"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Törlés"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Osztott vízszintes"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Osztott függőleges"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Osztott egyéni"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Hagyományos színek"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Esti színek"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Egyéni színek"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatikus"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Ismeretlen színek"</string>
     <string name="color_transform" msgid="6985460408079086090">"Színmódosítás"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Gyorsbeállítások mozaikjának megjelenítése"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fejhallgató csatlakoztatva"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset csatlakoztatva"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ikonok megjelenítése és elrejtése az állapotsoron."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Adatforgalom-csökkentő"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Az adatforgalom-csökkentő be van kapcsolva"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Az Adatforgalom-csökkentő ki van kapcsolva"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Be"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigációs sáv"</string>
+    <string name="start" msgid="6873794757232879664">"Kezdés"</string>
+    <string name="center" msgid="4327473927066010960">"Igazítás középre"</string>
+    <string name="end" msgid="125797972524818282">"Vége"</string>
+    <string name="space" msgid="804232271282109749">"Távtartó"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menü/Billentyűzetváltó"</string>
+    <string name="select_button" msgid="1597989540662710653">"Hozzáadni kívánt gomb kiválasztása"</string>
+    <string name="add_button" msgid="4134946063432258161">"Gomb hozzáadása"</string>
+    <string name="save" msgid="2311877285724540644">"Mentés"</string>
+    <string name="reset" msgid="2448168080964209908">"Alaphelyzet"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Nem található főoldal gomb"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Az eszközön történő navigáláshoz főoldal gomb szükséges. Kérjük, a mentés előtt adjon hozzá egy főoldal gombot."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Gombszélesség beállítása"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Vágólap"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"A Vágólap lehetővé teszi az elemek áthúzását közvetlenül a vágólapra. Ha vannak elemek a vágólapon, közvetlenül lehúzhatók onnan."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Személyre szabott navigációs gomb"</string>
+    <string name="keycode" msgid="7335281375728356499">"Billentyűkód"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"A billentyűkód gombok lehetővé teszik gombok hozzáadását a navigációs sávhoz. A gombok megnyomásuk esetén a kiválasztott billentyűt imitálják. Először ki kell választani a gombhoz tartozó billentyűt, majd a gombon megjeleníteni kívánt képet."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Billentyűgomb kiválasztása"</string>
+    <string name="preview" msgid="9077832302472282938">"Előnézet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
deleted file mode 100644
index 73ba98d..0000000
--- a/packages/SystemUI/res/values-hu/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Kép a képben (PIP) bezárása"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Teljes képernyő"</string>
-    <string name="pip_play" msgid="674145557658227044">"Lejátszás"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Szüneteltetés"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Mégse"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Tartsa nyomva a KEZDŐKÉPERNYŐ gombot a PIP funkció vezérléséhez"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index d135933..18943e9 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM չկա:"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Բջջային ցանցով տվյալների փոխանցումն անջատված է"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-ը կապվում է:"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Ինքնաթիռային ռեժիմ"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM քարտ չկա:"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"էկրանի ամրակցում"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Հնարավոր չէ գործարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Ավելին"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"ևս <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Պատմություն"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Մաքրել"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Հորիզոնական տրոհում"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ուղղահայաց տրոհում"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Հատուկ տրոհում"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Սովորական գույներ"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Գիշերային գույներ"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Հատուկ գույներ"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Ավտոմատ"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Անհայտ գույներ"</string>
     <string name="color_transform" msgid="6985460408079086090">"Գույնի փոփոխում"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Ցույց տալ Արագ կարգավորումների սալիկը"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Ականջակալը կապակցված է"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Ականջակալը կապակցված է"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Միացնել կամ անջատել պատկերակների ցուցադրումը կարգավիճակի գոտում:"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Տվյալների խնայում"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Տվյալների խնայումը միացված է"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Տվյալների խնայումն անջատված է"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Միացնել"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Նավարկման գոտի"</string>
+    <string name="start" msgid="6873794757232879664">"Սկսել"</string>
+    <string name="center" msgid="4327473927066010960">"Կենտրոն"</string>
+    <string name="end" msgid="125797972524818282">"Վերջ"</string>
+    <string name="space" msgid="804232271282109749">"Բաժանիչ"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Ընտրացանկ/Ստեղնաշարի փոխարկիչ"</string>
+    <string name="select_button" msgid="1597989540662710653">"Ավելացնելու համար ընտրեք կոճակ"</string>
+    <string name="add_button" msgid="4134946063432258161">"Ավելացնել կոճակ"</string>
+    <string name="save" msgid="2311877285724540644">"Պահել"</string>
+    <string name="reset" msgid="2448168080964209908">"Վերակայել"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Գլխավոր էջի կոճակ չի գտնվել"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Այս սարքը նավարկելու համար պահանջվում է գլխավոր էջ վերադառնալու կոճակ: Պահելուց առաջ ավելացրեք գլխավոր էջ վերադառնալու կոճակ:"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Կարգավորել կոճակի լայնությունը"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Սեղմատախտակ"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Սեղմատախտակ կոճակը թույլ է տալիս տարրերը քաշել անմիջապես դեպի սեղմատախտակ: Առկայության դեպքում տարրերը հնարավոր է նաև սեղմատախտակից դուրս քաշել:"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Հատուկ նավարկման կոճակ"</string>
+    <string name="keycode" msgid="7335281375728356499">"Ստեղնային կոդ"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Ստեղնային կոդի կոճակները թույլ են տալիս Նավարկման գոտում ավելացնել ստեղնաշարի ստեղները: Սեղմելու դեպքում դրանք էմուլացնում են ստեղնաշարի ընտրված ստեղնը: Կոճակի համար նախ անհրաժեշտ է ընտրել ստեղնը, այնուհետև՝ կոճակի վրա ցուցադրվող պատկերը:"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Ընտրեք ստեղնաշարի կոճակը"</string>
+    <string name="preview" msgid="9077832302472282938">"Նախադիտում"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
deleted file mode 100644
index 8113f09..0000000
--- a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Փակել PIP-ն"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Լիէկրան"</string>
-    <string name="pip_play" msgid="674145557658227044">"Նվագարկել"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Դադարեցնել"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Չեղարկել"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP-ն կառավարելու համար սեղմած պահեք HOME կոճակը"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 6335c5d..887dc89 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Tidak ada SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Data Seluler Nonaktif"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Penambatan bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode pesawat."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Tidak ada kartu SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pin ke layar"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulai <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Lainnya"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> Lagi"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Riwayat"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Hapus"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Pisahkan Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pisahkan Vertikal"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pisahkan Khusus"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Warna normal"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Warna malam"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Warna khusus"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Otomatis"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Warna tidak diketahui"</string>
     <string name="color_transform" msgid="6985460408079086090">"Perubahan warna"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Tampilkan ubin Setelan Cepat"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphone terhubung"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset terhubung"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Aktifkan atau nonaktifkan ikon yang ditampilkan di bilah status."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Penghemat Data"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Penghemat Data aktif"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Penghemat Data nonaktif"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Aktif"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Bilah navigasi"</string>
+    <string name="start" msgid="6873794757232879664">"Awal"</string>
+    <string name="center" msgid="4327473927066010960">"Tengah"</string>
+    <string name="end" msgid="125797972524818282">"Akhir"</string>
+    <string name="space" msgid="804232271282109749">"Pengatur spasi"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Pengalih Menu / Keyboard"</string>
+    <string name="select_button" msgid="1597989540662710653">"Pilih tombol untuk ditambahkan"</string>
+    <string name="add_button" msgid="4134946063432258161">"Tambahkan tombol"</string>
+    <string name="save" msgid="2311877285724540644">"Simpan"</string>
+    <string name="reset" msgid="2448168080964209908">"Setel ulang"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Tidak ada tombol layar utama"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Tombol layar utama diperlukan agar dapat menavigasi perangkat ini. Tambahkan tombol layar uama sebelum menyimpan."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Sesuaikan lebar tombol"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Papan klip"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Papan klip memungkinkan item diseret langsung ke papan klip. Item juga dapat diseret langsung dari papan klik jika ada."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Tombol navigasi khusus"</string>
+    <string name="keycode" msgid="7335281375728356499">"Kode tombol"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Tombol untuk kode tombol memungkinkan keyboard ditambahkan ke Bilah Navigasi. Jika ditekan, tombol ini mengemulasi tombol keyboard yang dipilih. Terlebih dahulu tombol harus dipilih, diikuti dengan gambar yang akan ditampilkan."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Pilih Tombol Keyboard"</string>
+    <string name="preview" msgid="9077832302472282938">"Pratinjau"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
deleted file mode 100644
index b889231..0000000
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Tutup PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Layar penuh"</string>
-    <string name="pip_play" msgid="674145557658227044">"Putar"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Jeda"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Batal"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Tahan LAYAR UTAMA untuk mengontrol PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 76f5389..0786003 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Ekkert SIM-kort."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Slökkt á farsímagögnum"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tjóðrun með Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Flugstilling"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Ekkert SIM-kort."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skjáfesting"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"leita"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Ekki var hægt að ræsa <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Meira"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> í viðbót"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Ferill"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Hreinsa"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Lárétt skipting"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Lóðrétt skipting"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Sérsniðin skipting"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Venjulegir litir"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Næturlitir"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Sérsniðnir litir"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Sjálfvirkt"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Óþekktir litir"</string>
     <string name="color_transform" msgid="6985460408079086090">"Litabreytingar"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Sýna flísar í flýtistillingum"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Heyrnartól tengd"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Höfuðtól tengt"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Birtu eða feldu myndtákn í stöðustikunni."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Gagnasparnaður"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Kveikt er á gagnasparnaði"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Slökkt er á gagnasparnaði"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Kveikt"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Yfirlitsstika"</string>
+    <string name="start" msgid="6873794757232879664">"Byrja"</string>
+    <string name="center" msgid="4327473927066010960">"Miðja"</string>
+    <string name="end" msgid="125797972524818282">"Ljúka"</string>
+    <string name="space" msgid="804232271282109749">"Bil"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Valmynd / lyklaborðsval"</string>
+    <string name="select_button" msgid="1597989540662710653">"Veldu hnapp til að bæta við"</string>
+    <string name="add_button" msgid="4134946063432258161">"Bæta við hnappi"</string>
+    <string name="save" msgid="2311877285724540644">"Vista"</string>
+    <string name="reset" msgid="2448168080964209908">"Endurstilla"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Enginn heimahnappur fannst"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Þörf er á heimahnappi til að hægt sé að fletta á þessu tæki. Bættu við heimahnappi áður en þú vistar."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Breyta breidd hnapps"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Klippiborð"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Hægt er að draga atriði beint yfir á klippiborðið. Eins má draga þau atriði sem eru þar fyrir beint út af klippiborðinu."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Sérsniðinn flettingahnappur"</string>
+    <string name="keycode" msgid="7335281375728356499">"Lykilkóði"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Með lykilkóðahnöppum má bæta lyklaborðshnöppum við yfirlitsstikuna. Þegar ýtt er á slíka hnappa líkja þeir eftir fyrirfram völdum lyklaborðshnöppum. Fyrst þarf að velja tiltekinn hnapp fyrir hvern þeirra og síðan þá mynd sem á að birtast á hnappnum."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Veldu lyklaborðshnapp"</string>
+    <string name="preview" msgid="9077832302472282938">"Forskoðun"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings_tv.xml b/packages/SystemUI/res/values-is-rIS/strings_tv.xml
deleted file mode 100644
index d91605e..0000000
--- a/packages/SystemUI/res/values-is-rIS/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Loka PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Allur skjárinn"</string>
-    <string name="pip_play" msgid="674145557658227044">"Spila"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Hlé"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Hætta við"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Haltu HOME-lyklinum niðri til að stjórna PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index cfcd42c..f6373ff 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nessuna SIM presente."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Rete dati disattivata"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tethering Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modalità aereo."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Nessuna SIM presente."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"blocco su schermo"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossibile avviare <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Altro"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Altre attività: <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Cronologia"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Cancella"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisione in orizzontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisione in verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisione personalizzata"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Colori normali"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Colori per la notte"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Colori personalizzati"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatico"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Colori sconosciuti"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modifica del colore"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostra il riquadro Impostazioni rapide"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Cuffie collegate"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auricolare collegato"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Consente di attivare o disattivare la visualizzazione delle icone nella barra di stato."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Risparmio dati"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Risparmio dati attivo"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Risparmio dati disattivato"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Attiva"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barra di navigazione"</string>
+    <string name="start" msgid="6873794757232879664">"All\'inizio"</string>
+    <string name="center" msgid="4327473927066010960">"Al centro"</string>
+    <string name="end" msgid="125797972524818282">"Alla fine"</string>
+    <string name="space" msgid="804232271282109749">"Spaziatore"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Selettore menu/tastiera"</string>
+    <string name="select_button" msgid="1597989540662710653">"Selez. pulsante da aggiungere"</string>
+    <string name="add_button" msgid="4134946063432258161">"Aggiungi pulsante"</string>
+    <string name="save" msgid="2311877285724540644">"Salva"</string>
+    <string name="reset" msgid="2448168080964209908">"Reimposta"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Nessun pulsante Home trovato"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Per potersi spostare tra le funzioni del dispositivo, è necessario un pulsante Home. Aggiungine uno prima di salvare."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Modifica la larghezza del pulsante"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Appunti"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"La funzione Appunti consente di trascinare gli elementi direttamente negli appunti e fuori dagli appunti."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Pulsante di navigazione personalizzato"</string>
+    <string name="keycode" msgid="7335281375728356499">"Keycode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"I pulsanti keycode consentono di aggiungere tasti della tastiera alla barra di navigazione. Quando vengono premuti, emulano il tasto selezionato. Innanzitutto è necessario selezionare il tasto da associare al pulsante, poi un\'immagine da mostrare sul pulsante."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Seleziona il tasto della tastiera"</string>
+    <string name="preview" msgid="9077832302472282938">"Anteprima"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
deleted file mode 100644
index 0279e45..0000000
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Chiudi visualizzazione PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Schermo intero"</string>
-    <string name="pip_play" msgid="674145557658227044">"Riproduci"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pausa"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Annulla"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Tieni premuto HOME per controllare la visualizzazione PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 6fd3456..fe15d7f 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -148,6 +148,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"קצה"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"‏אין כרטיס SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"הנתונים הסלולריים כבויים"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"‏שיתוף אינטרנט דרך Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"מצב טיסה"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"‏אין כרטיס SIM."</string>
@@ -302,8 +303,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"הצמדת מסך"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"לא ניתן היה להפעיל את <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"עוד"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> נוספות"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"היסטוריה"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"נקה"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"פיצול אופקי"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"פיצול אנכי"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"פיצול מותאם אישית"</string>
@@ -469,6 +470,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"צבעים רגילים"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"צבעי לילה"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"צבעים מותאמים אישית"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"אוטומטי"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"צבעים לא ידועים"</string>
     <string name="color_transform" msgid="6985460408079086090">"שינוי צבע"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"הצגת אריח של הגדרות מהירות"</string>
@@ -495,10 +497,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"אוזניות מחוברות"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"אוזניות מחוברות"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"הפעלה או השבתה של סמלים המוצגים בשורת הסטטוס."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"‏חוסך הנתונים (Data Saver)"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"‏חוסך הנתונים (Data Saver) פועל"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"‏חוסך הנתונים (Data Saver) כבוי"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"פועל"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"סרגל ניווט"</string>
+    <string name="start" msgid="6873794757232879664">"התחלה"</string>
+    <string name="center" msgid="4327473927066010960">"מרכז"</string>
+    <string name="end" msgid="125797972524818282">"סיום"</string>
+    <string name="space" msgid="804232271282109749">"רווח"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"מחליף תפריט / מקלדת"</string>
+    <string name="select_button" msgid="1597989540662710653">"בחירת לחצן להוספה"</string>
+    <string name="add_button" msgid="4134946063432258161">"הוסף לחצן"</string>
+    <string name="save" msgid="2311877285724540644">"שמור"</string>
+    <string name="reset" msgid="2448168080964209908">"איפוס"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"לחצן הבית לא נמצא"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"לחצן הבית נדרש כדי לנווט במכשיר הזה. הוסף לחצן בית לפני השמירה."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"שינוי של רוחב לחצן"</string>
+    <string name="clipboard" msgid="1313879395099896312">"לוח"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"בעזרת האפשרות \'לוח\', ניתן לגרור פריטים ישירות ללוח. ניתן גם לגרור פריטים ישירות מהלוח, כשהוא זמין."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"לחצן לניווט מותאם אישית"</string>
+    <string name="keycode" msgid="7335281375728356499">"קוד מפתח"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"לחצנים של קוד מפתח מאפשרים להוסיף מקשי מקלדת לסרגל הניווט. בעת הלחיצה הם מדמים את מקש המקלדת שנבחר. תחילה יש לבחור את המקש ללחצן, ולאחר מכן יש לבחור תמונה שתוצג בלחצן."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"בחירת לחצן מקלדת"</string>
+    <string name="preview" msgid="9077832302472282938">"תצוגה מקדימה"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings_car.xml b/packages/SystemUI/res/values-iw/strings_car.xml
index 8d62258..4b7ba97 100644
--- a/packages/SystemUI/res/values-iw/strings_car.xml
+++ b/packages/SystemUI/res/values-iw/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"נסיעה בטוחה"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"‏עליך להיות מודע לתנאי הנהיגה באופן מלא, ולציית תמיד לדינים החלים. ייתכן שהמסלול אינו מדויק, לא שלם, מסוכן, לא מתאים, אסור למעבר או כרוך בחציית אזורים מנהליים. ייתכן שגם מידע עסקי לא יהיה מדויק או שלם. הנתונים אינם מדווחים בזמן אמת ולא ניתן להבטיח דיוק במיקום. אל תתעסק במכשיר הנייד שלך ואל תשתמש באפליקציות שאינן מיועדות ל-Android Auto בזמן הנהיגה."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"‏שמור על עירנות לתנאי הנסיעה וציית תמיד לכללים והחוקים. ייתכן שהמסלול לא מדויק, לא שלם, מסוכן, לא מתאים, אסור למעבר או כרוך בחציית אזורים מנהליים. ייתכן גם שחלק מהמידע העסקי לא מדויק או לא שלם. הנתונים אינם מדווחים בזמן אמת ולא ניתן להבטיח דיוק במיקום. אל תתעסק במכשיר הנייד ואל תשתמש באפליקציות שאינן מיועדות ל-Android Auto בזמן הנהיגה."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
deleted file mode 100644
index a1bebb9..0000000
--- a/packages/SystemUI/res/values-iw/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"‏סגור PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"מסך מלא"</string>
-    <string name="pip_play" msgid="674145557658227044">"הפעל"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"השהה"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"ביטול"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"‏המשך ללחוץ על HOME כדי לשלוט ב-PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 189fcd9..537dbf0 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIMがありません。"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"モバイルデータ OFF"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetoothテザリング。"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"機内モード。"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIMカードが挿入されていません。"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"画面固定"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>を開始できません。"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"もっと見る"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"他 <xliff:g id="NUMBER">%d</xliff:g> 件"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"履歴"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"消去"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"横に分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"縦に分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"分割(カスタム)"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"標準の色"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"夜間の色"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"カスタムの色"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"自動"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"不明な色"</string>
     <string name="color_transform" msgid="6985460408079086090">"色の変更"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"[クイック設定] タイルの表示"</string>
@@ -499,4 +501,25 @@
     <skip />
     <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
     <skip />
+    <string name="switch_bar_on" msgid="1142437840752794229">"ON"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"ナビゲーション バー"</string>
+    <string name="start" msgid="6873794757232879664">"最初"</string>
+    <string name="center" msgid="4327473927066010960">"中央"</string>
+    <string name="end" msgid="125797972524818282">"最後"</string>
+    <string name="space" msgid="804232271282109749">"スペース"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"メニューとキーボードの切り替え"</string>
+    <string name="select_button" msgid="1597989540662710653">"追加するボタンの選択"</string>
+    <string name="add_button" msgid="4134946063432258161">"ボタンを追加"</string>
+    <string name="save" msgid="2311877285724540644">"保存"</string>
+    <string name="reset" msgid="2448168080964209908">"リセット"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"ホームボタンが見つかりません"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"この端末を操作できるようにするにはホームボタンが必要です。保存する前にホームボタンを追加してください。"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"ボタンの幅の調整"</string>
+    <string name="clipboard" msgid="1313879395099896312">"クリップボード"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"クリップボード機能ではクリップボードにアイテムを直接ドラッグできます。クリップボードにアイテムがある場合、直接そのアイテムをドラッグして取り出すこともできます。"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"カスタム ナビゲーション ボタン"</string>
+    <string name="keycode" msgid="7335281375728356499">"キーコード"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"キーコード ボタンを利用すると、ナビゲーション バーにキーボードのキー機能を追加できるようになります。ボタンを押すと選択済みのキーボードのキーがエミュレートされます。まずボタン用にキーを選択し、次にボタン上の画像を選択する必要があります。"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"キーボードのボタンの選択"</string>
+    <string name="preview" msgid="9077832302472282938">"プレビュー"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
deleted file mode 100644
index 08a5a1c..0000000
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP を閉じる"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"全画面表示"</string>
-    <string name="pip_play" msgid="674145557658227044">"再生"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"一時停止"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"キャンセル"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"[ホーム] を押し続けると PIP を制御できます"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 07390f5..79fa408 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM არ არის."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"მობილური ინტერნეტი გამორთულია"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-ის ჩართვა"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"თვითმფრინავის რეჟიმი"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM ბარათი არ არის."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ეკრანზე ჩამაგრება"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-ის გამოძახება ვერ მოხერხდა."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"მეტი"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"კიდევ <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ისტორია"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"გასუფთავება"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ჰორიზონტალური გაყოფა"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ვერტიკალური გაყოფა"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ინდივიდუალური გაყობა"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"ჩვეულებრივი ფერები"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"ღამის ფერები"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"მორგებული ფერები"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"ავტომატური"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"უცნობი ფერები"</string>
     <string name="color_transform" msgid="6985460408079086090">"ფერების შეცვლა"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"სწრაფი პარამეტრების მოზაიკის ჩვენება"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ყურსასმენები დაკავშირებულია"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ყურსაცვამი დაკავშირებულია"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"სტატუსის ზოლში ხატულების ჩვენების ჩართვა ან გათიშვა."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"მონაცემთა დამზოგველი"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"მონაცემთა დამზოგველი ჩართულია"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"მონაცემთა დამზოგველი გამორთულია"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"ჩართული"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"ნავიგაციის ზოლი"</string>
+    <string name="start" msgid="6873794757232879664">"თავში"</string>
+    <string name="center" msgid="4327473927066010960">"ცენტრში"</string>
+    <string name="end" msgid="125797972524818282">"ბოლოში"</string>
+    <string name="space" msgid="804232271282109749">"ინტერვალი"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"მენიუს/კლავიატურის გადამრთველი"</string>
+    <string name="select_button" msgid="1597989540662710653">"აირჩიეთ დასამატებელი ღილაკი"</string>
+    <string name="add_button" msgid="4134946063432258161">"ღილაკის დამატება"</string>
+    <string name="save" msgid="2311877285724540644">"შენახვა"</string>
+    <string name="reset" msgid="2448168080964209908">"საწყისზე დაბრუნება"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"მთავარი ღილაკი ვერ მოიძებნა"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ამ მოწყობილობაში ნავიგაციისთვის საჭიროა მთავარი ღილაკი. გთხოვთ, შენახვამდე დაამატოთ მთავარი ღილაკი."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"ღილაკის სიგანის კორექტირება"</string>
+    <string name="clipboard" msgid="1313879395099896312">"გაცვლის ბუფერი"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"გაცვლის ბუფერის მეშვეობით შესაძლებელია ერთეულების ჩავლებით პირდაპირ მასში გადატანა და ჩავლებითვე გამოტანა, როცა ის ხელმისაწვდომია."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"ნავიგაციის მორგებული ღილაკი"</string>
+    <string name="keycode" msgid="7335281375728356499">"კლავიშის კოდი"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"კლავიშის კოდის ტიპის ღილაკების მეშვეობით ნავიგაციის ზოლში კლავიატურის კლავიშების დამატება არის შესაძლებელი. მათზე დაჭერისას არჩეული კლავიატურის კლავიშის ემულაცია ხდება. პირველ რიგში, ღილაკისთვის უნდა აირჩეს კლავიში, ხოლო შემდეგ სურათი, რომელიც ღილაკზე უნდა იყოს ნაჩვენები."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"აირჩიეთ კლავიატურის ღილაკი"</string>
+    <string name="preview" msgid="9077832302472282938">"გადახედვა"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
deleted file mode 100644
index 83db37b..0000000
--- a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP-ის დახურვა"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"სრულ ეკრანზე"</string>
-    <string name="pip_play" msgid="674145557658227044">"დაკვრა"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"პაუზა"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"გაუქმება"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP-ის სამართავად, ხანგრძლივად დააჭირეთ მთავარ ღილაკს"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 02e773c..c5a89ff 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE (ұялы байланыстар жүйесіне арналған жетілдірілген деректер шамалары)"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM жоқ."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Ұялы дерек өшірулі"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth тетеринг."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Ұшақ режимі."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM картасы жоқ."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экранды бекіту"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"іздеу"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> іске қосу мүмкін болмады."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Қосымша"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> Қосымша"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Тарих"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Тазалау"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Бөлінген көлденең"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Бөлінген тік"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Бөлінген теңшелетін"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Қалыпты түстер"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Түнгі түстер"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Арнаулы түстер"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Авто"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Белгісіз түстер"</string>
     <string name="color_transform" msgid="6985460408079086090">"Түсті өзгерту"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Жылдам параметрлер торын көрсету"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Құлақаспап қосылды"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Құлақаспап жинағы қосылды"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Белгішелердің күй жолағында көрсетілуін қосу немесе өшіру"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Дерек сақтағыш"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Дерек сақтағыш қосулы"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Дерек сақтағышы өшірулі"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Қосулы"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Шарлау тақтасы"</string>
+    <string name="start" msgid="6873794757232879664">"Бастау"</string>
+    <string name="center" msgid="4327473927066010960">"Орталық"</string>
+    <string name="end" msgid="125797972524818282">"Аяқтау"</string>
+    <string name="space" msgid="804232271282109749">"Аралық"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Мәзір/пернетақта ауыстырғышы"</string>
+    <string name="select_button" msgid="1597989540662710653">"Қосу үшін түймені таңдаңыз"</string>
+    <string name="add_button" msgid="4134946063432258161">"Қосу түймесі"</string>
+    <string name="save" msgid="2311877285724540644">"Сақтау"</string>
+    <string name="reset" msgid="2448168080964209908">"Қайта реттеу"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Негізгі бет түймесі табылмады"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Негізгі бет түймесі осы құрылғыны шарлау үшін қажет. Сақтау алдында негізгі бет түймесін қосыңыз."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Түйме енін реттеу"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Буфер"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"\"Буфер\" элементтерді тікелей буферге сүйреуге мүмкіндік береді. Сондай-ақ, бар болса, элементтерді тікелей буферден сүйреп шығаруға болады."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Арнаулы шарлау түймесі"</string>
+    <string name="keycode" msgid="7335281375728356499">"Кілт коды"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Кілт коды түймелері пернетақта пернелерін шарлау тақтасына қосуға мүмкіндік береді. Басқан кезде олар таңдалған пернетақта пернесін эмуляциялайды. Алдымен түйме үшін пернені, содан кейін түймеде көрсетілетін кескінді таңдау керек."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Пернетақта түймесін таңдау"</string>
+    <string name="preview" msgid="9077832302472282938">"Алдын ала қарау"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
deleted file mode 100644
index 6339f42..0000000
--- a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP жабу"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Толық экран"</string>
-    <string name="pip_play" msgid="674145557658227044">"Ойнату"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Кідірту"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Бас тарту"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP басқару үшін «Негізгі бет» түймесін ұстап тұрыңыз"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 513a5b8..6baaa78 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"វ៉ាយហ្វាយ"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"គ្មាន​ស៊ីម​កាត។"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"ទិន្នន័យចល័តបានបិទ"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ការ​ភ្ជាប់​ប៊្លូធូស។"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"របៀប​​ពេលជិះ​យន្តហោះ"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"គ្មានស៊ីមកាតទេ។"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ការ​ភ្ជាប់​អេក្រង់"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"មិន​អាច​ចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ទេ។"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"ច្រើនទៀត"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> ទៀត"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ប្រវត្តិ"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"សម្អាត"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"បំបែកផ្តេក"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"បំបែកបញ្ឈរ"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"បំបែកផ្ទាល់ខ្លួន"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"ពណ៌ធម្មតា"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"ពណ៌ពេលយប់"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"ពណ៌ផ្ទាល់ខ្លួន"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"ស្វ័យប្រវត្តិ"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"ពណ៌មិនស្គាល់"</string>
     <string name="color_transform" msgid="6985460408079086090">"ការកែសម្រួលពណ៌"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"បង្ហាញផ្ទាំងប្រអប់ការកំណត់រហ័ស"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"បានភ្ជាប់កាស"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"បានភ្ជាប់កាស"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"បើក ឬបិទដំណើរការបង្ហាញរូបតំណាងនៅលើរបារស្ថានភាព"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"កម្មវិធីសន្សំសំចៃទិន្នន័យ"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"កម្មវិធីសន្សំសំចៃទិន្នន័យបានបើក"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"កម្មវិធីសន្សំសំចៃទិន្នន័យបានបិទ"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"បើក"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"របាររុករក"</string>
+    <string name="start" msgid="6873794757232879664">"ចាប់ផ្ដើម"</string>
+    <string name="center" msgid="4327473927066010960">"កណ្តាល"</string>
+    <string name="end" msgid="125797972524818282">"បញ្ចប់"</string>
+    <string name="space" msgid="804232271282109749">"ចន្លោះ"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"កម្មវិធីប្តូរក្តារចុច / ម៉ឺនុយ"</string>
+    <string name="select_button" msgid="1597989540662710653">"ជ្រើសប៊ូតុងដែលត្រូវថែម"</string>
+    <string name="add_button" msgid="4134946063432258161">"បន្ថែមប៊ូតុង"</string>
+    <string name="save" msgid="2311877285724540644">"រក្សាទុក"</string>
+    <string name="reset" msgid="2448168080964209908">"កំណត់​ឡើងវិញ"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"រកមិនឃើញប៊ូតុងដើមទេ"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"តម្រូវឲ្យមានប៊ូតុងដើមដើម្បីអាចរុករកឧបករណ៍នេះបាន។ សូមបន្ថែមប៊ូតុងដើមមុនពេលរក្សាទុក។"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"កែសម្រួលទទឹងប៊ូតុង"</string>
+    <string name="clipboard" msgid="1313879395099896312">"ក្ដារ​តម្បៀត​ខ្ទាស់"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"ក្តារតម្បៀតខ្ទាស់អនុញ្ញាតឲ្យមានការអូសធាតុដោយផ្ទាល់ទៅកាន់ក្តារតម្បៀតខ្ទាស់នោះ។ នៅពេលដែលមានធាតុស្រាប់ក្នុងក្តារតម្បៀតខ្ទាស់ ធាតុទាំងនោះក៏អាចអូសដោយផ្ទាល់ចេញពីក្តារតម្បៀតខ្ទាស់បានដែរ។"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"ប៊ូតុងរុករកផ្ទាល់ខ្លួន"</string>
+    <string name="keycode" msgid="7335281375728356499">"លេខកូដគ្រាប់ចុច"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"ប៊ូតុងលេខកូដគ្រាប់ចុចអនុញ្ញាតឲ្យមានការបន្ថែមគ្រាប់ចុចនៃក្តារចុចទៅក្នុងរបាររុករក។ នៅពេលចុចប៊ូតុងទាំងនោះ ពួកវាបង្កើតមុខងារឲ្យគ្រាប់ចុចនៃក្តារចុចដែលបានជ្រើស។ សូមជ្រើសរើសគ្រាប់ចុចសម្រាប់ប៊ូតុងជាមុនសិន មុនពេលដែលរូបភាពត្រូវបានបង្ហាញនៅលើប៊ូតុង។"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"ជ្រើសប៊ូតុងក្តារចុច"</string>
+    <string name="preview" msgid="9077832302472282938">"មើលជាមុន"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings_tv.xml b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
deleted file mode 100644
index 6e6172c..0000000
--- a/packages/SystemUI/res/values-km-rKH/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"បិទ PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"ពេញអេក្រង់"</string>
-    <string name="pip_play" msgid="674145557658227044">"ចាក់"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"ផ្អាក"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"បោះបង់"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"សង្កត់ប៊ូតុងដើម ដើម្បីគ្រប់គ្រង PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index a64fe5a..1c38684 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"ಎಡ್ಜ್‌"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"ಯಾವುದೇ ಸಿಮ್‌ ಇಲ್ಲ."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"ಸೆಲ್ಯುಲಾರ್ ಡೇಟಾ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ಬ್ಲೂಟೂತ್‌‌ ಟೆಥರಿಂಗ್."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"ಏರೋಪ್ಲೇನ್‌ ಮೋಡ್‌"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"ಯಾವುದೇ ಸಿಮ್‌ ಇಲ್ಲ."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ಸ್ಕ್ರೀನ್ ಪಿನ್ನಿಂಗ್"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ಹುಡುಕಾಟ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲು ಸಾದ್ಯವಿಲ್ಲ."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"ಇನ್ನಷ್ಟು"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> ಇನ್ನಷ್ಟು"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ಇತಿಹಾಸ"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ತೆರವುಗೊಳಿಸು"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ಅಡ್ಡಲಾಗಿ ವಿಭಜಿಸಿದ"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ಲಂಬವಾಗಿ ವಿಭಜಿಸಿದ"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ಕಸ್ಟಮ್ ವಿಭಜಿಸಿದ"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"ಸಾಮಾನ್ಯ ಬಣ್ಣಗಳು"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"ರಾತ್ರಿ ಬಣ್ಣಗಳು"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"ಕಸ್ಟಮ್ ಬಣ್ಣಗಳು"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"ಸ್ವಯಂ"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"ಅಪರಿಚಿತ ಬಣ್ಣಗಳು"</string>
     <string name="color_transform" msgid="6985460408079086090">"ಬಣ್ಣ ಬದಲಾವಣೆ"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಟೈಲ್ ತೋರಿಸು"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ಹೆಡ್‌ಫೋನ್ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ಹೆಡ್‌ಸೆಟ್ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಐಕಾನ್‌ಗಳು ತೋರಿಸುವುದನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"ಡೇಟಾ ಉಳಿಸುವಿಕೆ"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ಡೇಟಾ ಉಳಿಸುವಿಕೆ ಆನ್ ಆಗಿದೆ"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ಡೇಟಾ ಉಳಿಸುವಿಕೆ ಆಫ್ ಆಗಿದೆ"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"ಆನ್"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್"</string>
+    <string name="start" msgid="6873794757232879664">"ಪ್ರಾರಂಭ"</string>
+    <string name="center" msgid="4327473927066010960">"ಮಧ್ಯ"</string>
+    <string name="end" msgid="125797972524818282">"ಮುಕ್ತಾಯ"</string>
+    <string name="space" msgid="804232271282109749">"ಸ್ಪೇಸರ್"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"ಮೆನು / ಕೀಬೋರ್ಡ್ ಬದಲಾಯಿಸುವಿಕೆ"</string>
+    <string name="select_button" msgid="1597989540662710653">"ಸೇರಿಸಲು ಬಟನ್ ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="add_button" msgid="4134946063432258161">"ಬಟನ್ ಸೇರಿಸು"</string>
+    <string name="save" msgid="2311877285724540644">"ಉಳಿಸು"</string>
+    <string name="reset" msgid="2448168080964209908">"ಮರುಹೊಂದಿಸು"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"ಯಾವುದೇ ಹೋಮ್ ಬಟನ್ ಕಂಡುಬಂದಿಲ್ಲ"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ಈ ಸಾಧನವನ್ನು ನ್ಯಾವಿಗೇಟ್ ಮಾಡಲು ಹೋಮ್ ಬಟನ್ ಅಗತ್ಯವಿರುತ್ತದೆ. ಉಳಿಸುವ ಮೊದಲು ದಯವಿಟ್ಟು ಹೋಮ್ ಬಟನ್ ಸೇರಿಸಿ."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"ಬಟನ್ ಅಳತೆ ಹೊಂದಿಸು"</string>
+    <string name="clipboard" msgid="1313879395099896312">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"ಐಟಂಗಳನ್ನು ನೇರವಾಗಿ ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಲು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ಅನುಮತಿಸುತ್ತದೆ. ಐಟಂಗಳು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವಾಗ ಅವುಗಳನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ನಿಂದ ನೇರವಾಗಿ ಹೊರಗೆ ಹಾಕಬಹುದಾಗಿರುತ್ತದೆ."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"ಕಸ್ಟಮ್ ನ್ಯಾವಿಗೇಷನ್ ಬಟನ್"</string>
+    <string name="keycode" msgid="7335281375728356499">"ಕೀಕೋಡ್"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"ಕೀಕೋಡ್ ಬಟನ್‌ಗಳು ಕೀಬೋರ್ಡ್ ಕೀಗಳನ್ನು ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್‌ಗೆ ಸೇರಿಸಲು ಆನುಮತಿಸುತ್ತದೆ. ಒತ್ತಿದಾಗ ಆಯ್ಕೆಮಾಡಲಾದ ಕೀಬೋರ್ಡ್ ಕೀಯನ್ನು ಅವುಗಳು ಅನುಕರಿಸುತ್ತವೆ. ಮೊದಲು ಬಟನ್‌ಗೆ ಕೀಯನ್ನು ಆಯ್ಕೆಮಾಡಬೇಕು ನಂತರ ಬಟನ್‌ನಲ್ಲಿ ತೋರಿಸಬೇಕಾದ ಚಿತ್ರವನ್ನು ಅನುಸರಿಸಬೇಕು."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"ಕೀಬೋರ್ಡ್ ಬಟನ್ ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="preview" msgid="9077832302472282938">"ಪೂರ್ವವೀಕ್ಷಣೆ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
deleted file mode 100644
index c2a7095..0000000
--- a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP ಮುಚ್ಚಿ"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"ಪೂರ್ಣ ಪರದೆ"</string>
-    <string name="pip_play" msgid="674145557658227044">"ಪ್ಲೇ"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"ವಿರಾಮ"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"ರದ್ದುಮಾಡು"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP ನಿಯಂತ್ರಿಸಲು HOME ಹೋಲ್ಡ್‌ ಮಾಡಿ"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 30a9422..f7c3d3a 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM이 없습니다."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"모바일 데이터가 사용 중지됨"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"블루투스 테더링입니다."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"비행기 모드입니다."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM 카드가 없습니다."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"화면 고정"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>을(를) 시작할 수 없습니다."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"더보기"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g>개 더보기"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"기록"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"삭제"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"수평 분할"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"수직 분할"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"맞춤 분할"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"일반 색상"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"야간 색상"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"맞춤 색상"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"자동"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"알 수 없는 색상"</string>
     <string name="color_transform" msgid="6985460408079086090">"색상 수정"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"빠른 설정 타일 표시"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"헤드폰 연결됨"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"헤드셋 연결됨"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"아이콘이 상태 표시줄에 표시되도록 사용 설정 또는 중지합니다."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"데이터 세이버"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"데이터 세이버 사용"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"데이터 세이버 사용 안함"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"사용"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"탐색 메뉴"</string>
+    <string name="start" msgid="6873794757232879664">"시작"</string>
+    <string name="center" msgid="4327473927066010960">"중앙"</string>
+    <string name="end" msgid="125797972524818282">"끝"</string>
+    <string name="space" msgid="804232271282109749">"공백"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"메뉴/키보드 전환 도구"</string>
+    <string name="select_button" msgid="1597989540662710653">"추가할 버튼 선택"</string>
+    <string name="add_button" msgid="4134946063432258161">"버튼 추가"</string>
+    <string name="save" msgid="2311877285724540644">"저장"</string>
+    <string name="reset" msgid="2448168080964209908">"초기화"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"홈 버튼을 찾지 못함"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"이 기기를 탐색하려면 홈 버튼을 사용해야 합니다. 홈 버튼을 추가한 다음 저장하세요."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"버튼 너비 조정"</string>
+    <string name="clipboard" msgid="1313879395099896312">"클립보드"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"클립보드를 사용하면 항목을 클립보드로 바로 드래그할 수 있습니다. 또한 발표 시 항목을 클립보드 밖으로 바로 드래그할 수도 있습니다."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"맞춤 탐색 버튼"</string>
+    <string name="keycode" msgid="7335281375728356499">"키 코드"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"키 코드 버튼을 사용하면 키보드 키를 탐색 메뉴에 추가할 수 있습니다. 키 코드 버튼을 누르면 선택된 키보드 키가 에뮬레이션됩니다. 먼저 버튼에 대해 키를 선택하고 그다음 버튼에 표시될 이미지를 선택해야 합니다."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"키보드 버튼 선택"</string>
+    <string name="preview" msgid="9077832302472282938">"미리보기"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings_car.xml b/packages/SystemUI/res/values-ko/strings_car.xml
index e18e587..fcc2d7b 100644
--- a/packages/SystemUI/res/values-ko/strings_car.xml
+++ b/packages/SystemUI/res/values-ko/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"안전 운전"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"도로 상황에 주의를 기울이고 관련 법규를 항상 준수하세요. 길찾기는 부정확하거나 불완전하거나 위험하거나 부적당하거나 금지되거나 여러 행정구역에 걸친 지역을 지나도록 안내할 수 있습니다. 비즈니스 정보 또한 부정확하거나 불완전할 수 있습니다. 데이터는 실시간이 아니며 위치의 정확도를 보증할 수 없습니다. 운전 중에 휴대기기를 조작하거나 Android Auto가 지원되지 않는 앱을 사용해서는 안 됩니다."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"도로 상황에 주의를 기울이고 관련 법규를 항상 준수하세요. 경로가 정확하지 않거나 불완전하거나 위험하거나 적합하지 않을 수 있으며 금지된 지역이나 여러 행정 구역을 통과할 수 있습니다. 비즈니스 정보 또한 부정확하거나 불완전할 수 있습니다. 데이터는 실시간이 아니며 위치의 정확도를 보증할 수 없습니다. 운전 중에 휴대기기를 조작하거나 Android Auto가 지원되지 않는 앱을 사용해서는 안 됩니다."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
deleted file mode 100644
index 158f4ad..0000000
--- a/packages/SystemUI/res/values-ko/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP 닫기"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"전체화면"</string>
-    <string name="pip_play" msgid="674145557658227044">"재생"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"일시중지"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"취소"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP를 제어하려면 홈을 누르세요."</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 873cf37..66f79e7 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM карта жок."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Мобилдик дайындарды өткөрүү өчүрүлгөн"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth аркылуу интернет бөлүшүү."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Учак тартиби."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM-карта жок"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экран кадоо"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"издөө"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> баштай алган жок."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Дагы"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Дагы <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Таржымал"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Тазалоо"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Туурасынан бөлүү"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Тигинен бөлүү"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ыңгайлаштырылган бөлүү"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Кадимки түстөр"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Түнкү түстөр"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Ыңгайлаштырылган түстөр"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Авто"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Белгисиз түстөр"</string>
     <string name="color_transform" msgid="6985460408079086090">"Түсүн өзгөртүү"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Ыкчам жөндөөлөр тактасын көрсөтүү"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Гарнитуралар туташкан"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Гарнитура туташты"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Абал тилкесиндеги сүрөтчөнү иштетүү же өчүрүү."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Дайындарды үнөмдөгүч"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Дайындарды үнөмдөгүч күйүк"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Дайындарды үнөмдөгүч өчүрүлгөн"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Күйүк"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Чабыттоо тилкеси"</string>
+    <string name="start" msgid="6873794757232879664">"Баштоо"</string>
+    <string name="center" msgid="4327473927066010960">"Экрандын ортосунда"</string>
+    <string name="end" msgid="125797972524818282">"Бүтүрүү"</string>
+    <string name="space" msgid="804232271282109749">"Боштук калтыргыч"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Меню / Баскычтоп которуштургуч"</string>
+    <string name="select_button" msgid="1597989540662710653">"Кошула турган баскычты тандоо"</string>
+    <string name="add_button" msgid="4134946063432258161">"Баскыч кошуу"</string>
+    <string name="save" msgid="2311877285724540644">"Сактоо"</string>
+    <string name="reset" msgid="2448168080964209908">"Баштапкы абалга келтирүү"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Башкы бет баскычы табылган жок"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Бул түзмөктө чабыттоо үчүн башкы бет баскычы керек. Сактаардан мурун, башкы бет баскычын кошуңуз."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Баскычтын жазылыгын тууралоо"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Алмашуу буфери"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Бул баскычтын жардамы менен файлдарды алмашуу буферине көчүрүп, анын ичинен сүйрөп чыгууга болот."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Ыңгайлаштырылган чабыттоо баскычы"</string>
+    <string name="keycode" msgid="7335281375728356499">"Баскыч коду"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Бул баскычтын жардамы менен баскычтоптогу баскычтарды чабыттоо тилкесине кошууга болот. Ал үчүн баскычты жана тийиштүү баскычтын көрүнүшүн тандаңыз."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Баскычтоптогу баскычты тандоо"</string>
+    <string name="preview" msgid="9077832302472282938">"Алдын ала көрүү"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
deleted file mode 100644
index c54d0d2..0000000
--- a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP жабуу"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Толук экран"</string>
-    <string name="pip_play" msgid="674145557658227044">"Ойнотуу"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Тындыруу"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Жокко чыгаруу"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP көзөмөлдөө үчүн БАШКЫ БЕТ баскычын кармап туруңуз"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml
index e0affa1..43e7bac 100644
--- a/packages/SystemUI/res/values-land/config.xml
+++ b/packages/SystemUI/res/values-land/config.xml
@@ -38,6 +38,4 @@
          while the stack is not focused. -->
     <item name="recents_layout_unfocused_range_min" format="float" type="integer">-2</item>
     <item name="recents_layout_unfocused_range_max" format="float" type="integer">1.5</item>
-
-    <integer name="quick_settings_num_columns">4</integer>
 </resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index c75a89f..26a81c8 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -19,8 +19,7 @@
     <!-- thickness (width) of the navigation bar on phones that require it -->
     <dimen name="navigation_bar_size">@*android:dimen/navigation_bar_width</dimen>
 
-    <!-- Standard notification width + gravity -->
-    <dimen name="notification_panel_width">@dimen/standard_notification_panel_width</dimen>
+    <!-- Standard notification gravity -->
     <integer name="notification_panel_layout_gravity">@integer/standard_notification_panel_layout_gravity</integer>
 
     <dimen name="docked_divider_handle_width">2dp</dimen>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 7a85446..d003a04 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"ບໍ່ມີຊິມ."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"ຂໍ້ມູນເຄືອຂ່າຍມືຖືປິດຢູ່"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ການປ່ອຍສັນຍານ Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"ໂໝດໃນຍົນ."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"ບໍ່ມີແຜ່ນ SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ການ​ປັກ​ໝຸດ​ໜ້າ​ຈໍ​"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"ບໍ່​ສາ​ມາດ​ເລີ່ມ <xliff:g id="APP">%s</xliff:g> ໄດ້."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"ເພີ່ມເຕີມ"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> ເພີ່ມເຕີມ"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ປະຫວັດ"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ລຶບ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ການ​ແຍກ​ລວງ​ຂວາງ"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ການ​ແຍກ​ລວງ​ຕັ້ງ"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ການ​ແຍກ​ກຳ​ນົດ​ເອງ"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"ສີ​ປົກ​ກະ​ຕິ"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"ສີ​ຕອນ​ກາງ​ຄືນ"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"ສີແບບກຳນົດເອງ"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"ອັດຕະໂນມັດ"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"ສີທີ່ບໍ່ຮູ້ຈັກ"</string>
     <string name="color_transform" msgid="6985460408079086090">"ການ​ດັດ​ແປງສີ"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"ສະແດງໄທລ໌ການຕັ້ງຄ່າດ່ວນ"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ເຊື່ອມຕໍ່ຊຸດຫູຟັງແລ້ວ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ເຊື່ອມ​ຕໍ່ຊຸດ​ຫູ​ຟັງແລ້ວ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ເປີດ ຫຼື ປິດໄອຄອນຕ່າງໆຈາກການສະແດງໃນແຖບສະຖານະ."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"ຕົວປະຢັດຂໍ້ມູນ"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ຕົວປະຢັດຂໍ້ມູນເປີດຢູ່"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ຕົວປະຢັດຂໍ້ມູນປິດຢູ່"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"ເປີດ"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"ແຖບນຳທາງ"</string>
+    <string name="start" msgid="6873794757232879664">"ເລີ່ມຕົ້ນ"</string>
+    <string name="center" msgid="4327473927066010960">"ເຄິ່ງກາງ"</string>
+    <string name="end" msgid="125797972524818282">"ທ້າຍ"</string>
+    <string name="space" msgid="804232271282109749">"Spacer"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"ຕົວປ່ຽນເມນູ / ແປ້ນພິມ"</string>
+    <string name="select_button" msgid="1597989540662710653">"ເລືອກປຸ່ມເພື່ອເພີ່ມ"</string>
+    <string name="add_button" msgid="4134946063432258161">"ເພີ່ມປຸ່ມ"</string>
+    <string name="save" msgid="2311877285724540644">"ບັນທຶກ"</string>
+    <string name="reset" msgid="2448168080964209908">"ຣີເຊັດ"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"ບໍ່ພົບປຸ່ມໜ້າຫຼັກ"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ຈຳເປັນຕ້ອງມີປຸ່ມໜ້າຫຼັກເພື່ອໃຫ້ສາມາດນຳທາງອຸປະກອນນີ້. ກະລຸນາເພີ່ມປຸ່ມໜ້າຫຼັກກ່ອນທີ່ຈະບັນທຶກ."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"ປັບຄວາມກວ້າງຂອງປຸ່ມ"</string>
+    <string name="clipboard" msgid="1313879395099896312">"​ຄລິບບອດ"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"ຄລິບບອດອະນຸຍາດໃຫ້ລາກລາຍການຕ່າງໆໂດຍກົງຫາຄລິບບອດ. ນອກນັ້ນ ຍັງສາມາດລາກລາຍການໂດຍກົງອອກຈາກຄລິບບອດໄດ້ ເມື່ອມີຢູ່."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"ປຸ່ມນຳທາງແບບກຳນົດເອງ"</string>
+    <string name="keycode" msgid="7335281375728356499">"Keycode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"ປຸ່ມ Keycode ອະນຸຍາດໃຫ້ເພີ່ມປຸ່ມແປ້ນພິມໃສ່ແຖບການນຳທາງ. ເມື່ອກົດແລ້ວພວກມັນຈະຮຽນແບບປຸ່ມແປ້ນພິມທີ່ເລືອກ. ທຳອິດຕ້ອງເລືອກປຸ່ມແປ້ນພິມສຳລັບປຸ່ມນັ້ນ, ຕາມດ້ວຍຮູບທີ່ຈະປາກົດຂຶ້ນເທິງປຸ່ມນັ້ນ."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"ເລືອກປຸ່ມແປ້ນພິມ"</string>
+    <string name="preview" msgid="9077832302472282938">"ສະແດງຕົວຢ່າງ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
deleted file mode 100644
index 289d4e2..0000000
--- a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"ປິດ PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"ເຕັມໜ້າຈໍ"</string>
-    <string name="pip_play" msgid="674145557658227044">"ຫຼິ້ນ"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"ຢຸດຊົ່ວຄາວ"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"ຍົກເລີກ"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"ກົດຄ້າງປຸ່ມ HOME ເພື່ອຄວບຄຸມ PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index c9a5959..7ea958b 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -148,6 +148,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Kraštas"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nėra SIM kortelės."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobiliojo ryšio duomenys išjungti"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"„Bluetooth“ įrenginio kaip modemo naudojimas."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Lėktuvo režimas."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Nėra SIM kortelės."</string>
@@ -302,8 +303,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekrano prisegimas"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nepavyko paleisti <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Daugiau"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Dar <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Istorija"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Išvalyti"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontalus skaidymas"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikalus skaidymas"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tinkintas skaidymas"</string>
@@ -469,6 +470,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Įprastos spalvos"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Nakties spalvos"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Tinkintos spalvos"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatinis"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Nežinomos spalvos"</string>
     <string name="color_transform" msgid="6985460408079086090">"Spalvų keitimas"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Rodyti Sparčiųjų nustatymų išklotinės elementą"</string>
@@ -495,10 +497,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Ausinės prijungtos"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Ausinės prijungtos"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Įgalinti arba išjungti piktogramų rodymą būsenos juostoje."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Duomenų taupymo priemonė"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Duomenų taupymo priemonė įjungta"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Duomenų taupymo priemonė išjungta"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Įjungti"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Naršymo juosta"</string>
+    <string name="start" msgid="6873794757232879664">"Pradėti"</string>
+    <string name="center" msgid="4327473927066010960">"Centre"</string>
+    <string name="end" msgid="125797972524818282">"Baigti"</string>
+    <string name="space" msgid="804232271282109749">"Skirtukas"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Meniu / klaviatūros perjung."</string>
+    <string name="select_button" msgid="1597989540662710653">"Norimo pridėti mygt. pasirink."</string>
+    <string name="add_button" msgid="4134946063432258161">"Pridėti mygtuką"</string>
+    <string name="save" msgid="2311877285724540644">"Išsaugoti"</string>
+    <string name="reset" msgid="2448168080964209908">"Atstatyti"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Pagr. pusl. mygtukas nerastas"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Kad būtų galima naršyti šį įrenginį, reikalingas pagrindinio puslapio mygtukas. Prieš išsaugodami pridėkite pagrindinio puslapio mygtuką."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Mygtuko pločio koregavimas"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Iškarpinė"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Naudojant Iškarpinę galima vilkti elementus tiesiai į iškarpinę. Be to, rodomus elementus galima vilkti tiesiai iš iškarpinės."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Tinkintas naršymo mygtukas"</string>
+    <string name="keycode" msgid="7335281375728356499">"Klavišo kodas"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Klavišų kodų mygtukais galima pridėti klaviatūros klavišus prie naršymo juostos. Paspaudus jie imituoja pasirinktą klaviatūros klavišą. Pirmiausia reikia pasirinkti mygtuko klavišą su vaizdu, kuris turėtų būti rodomas ant mygtuko."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Klaviatūros mygtuko pasirinkimas"</string>
+    <string name="preview" msgid="9077832302472282938">"Peržiūrėti"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
deleted file mode 100644
index b9719c4..0000000
--- a/packages/SystemUI/res/values-lt/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Uždaryti PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Visas ekranas"</string>
-    <string name="pip_play" msgid="674145557658227044">"Leisti"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pristabdyti"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Atšaukti"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Jei norite valdyti PIP, palaikykite paspaudę mygtuką HOME"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 5e115a8..da3ff25 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -147,6 +147,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nav SIM kartes."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobilie dati ir atslēgti"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth piesaiste."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Lidmašīnas režīms."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Nav SIM kartes."</string>
@@ -301,8 +302,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Piespraust ekrānu"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nevarēja palaist lietotni <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Vairāk"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Vēl <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Vēsture"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Notīrīt"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontāls dalījums"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikāls dalījums"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pielāgots dalījums"</string>
@@ -468,6 +469,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Parastas krāsas"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Nakts krāsas"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Pielāgotas krāsas"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automātiski"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Nezināmas krāsas"</string>
     <string name="color_transform" msgid="6985460408079086090">"Krāsu pārveidošana"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Ātro iestatījumu elementa rādīšana"</string>
@@ -494,10 +496,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Austiņas ir pievienotas"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Austiņas ar mikrofonu ir pievienotas"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Iespējojiet vai atspējojiet ikonu rādīšanu statusa joslā."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Datu lietojuma samazinātājs"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Datu lietojuma samazinātājs ieslēgts"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Datu lietojuma samazinātājs ir izslēgts."</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Ieslēgts"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigācijas josla"</string>
+    <string name="start" msgid="6873794757232879664">"Sākums"</string>
+    <string name="center" msgid="4327473927066010960">"Centrs"</string>
+    <string name="end" msgid="125797972524818282">"Beigas"</string>
+    <string name="space" msgid="804232271282109749">"Atstarpes elements"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Izvēlnes/tastatūras slēdzis"</string>
+    <string name="select_button" msgid="1597989540662710653">"Pievienojamās pogas atlase"</string>
+    <string name="add_button" msgid="4134946063432258161">"Pievienot pogu"</string>
+    <string name="save" msgid="2311877285724540644">"Saglabāt"</string>
+    <string name="reset" msgid="2448168080964209908">"Atiestatīt"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Netika atrasta poga Sākums"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Navigācijai šajā ierīcē ir nepieciešama poga Sākums. Lūdzu, pirms saglabāšanas pievienojiet pogu Sākums."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Pogas platuma pielāgošana"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Starpliktuve"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Ja ir pieejama starpliktuve, tajā var tieši ievilkt vienumus, kā arī ievietotos vienumus var izvilkt no tās."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Pielāgota navigācijas poga"</string>
+    <string name="keycode" msgid="7335281375728356499">"Taustiņu kods"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Izmantojot taustiņu koda pogas, navigācijas joslai var pievienot tastatūras taustiņus. Nospiežot taustiņu, tiek imitēta atlasītā tastatūras taustiņa funkcija. Vispirms ir jāatlasa taustiņš attiecīgajai pogai, pēc tam ir jāpievieno uz pogas rādāmais attēls."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Tastatūras pogas atlase"</string>
+    <string name="preview" msgid="9077832302472282938">"Priekšskatījums"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
deleted file mode 100644
index 1c42520..0000000
--- a/packages/SystemUI/res/values-lv/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Aizvērt attēlu attēlā"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Pilnekrāna režīms"</string>
-    <string name="pip_play" msgid="674145557658227044">"Atskaņot"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Apturēt"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Atcelt"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Turiet nospiestu taustiņu HOME, lai kontrolētu attēlu attēlā"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 348d679..1c7b94b 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Нема СИМ картичка."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Мобилните податоци се исклучени"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Се поврзува со Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Режим на работа во авион."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Нема СИМ-картичка"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"прикачување екран"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"пребарај"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не може да се вклучи."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Повеќе"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Уште <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Историја"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Исчисти"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Раздели хоризонтално"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Раздели вертикално"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Раздели прилагодено"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Нормални бои"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Ноќни бои"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Приспособени бои"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Автоматски"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Непознати бои"</string>
     <string name="color_transform" msgid="6985460408079086090">"Промена на бојата"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Прикажи плочка Брзи поставки"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Слушалките се поврзани"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Слушалките се поврзани"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Овозможете или оневозможете прикажување на иконите во статусната лента."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Штедач на интернет"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Штедачот на интернет е вклучен"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Штедачот на интернет е исклучен"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Вклучено"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Лента за навигација"</string>
+    <string name="start" msgid="6873794757232879664">"Почеток"</string>
+    <string name="center" msgid="4327473927066010960">"Центар"</string>
+    <string name="end" msgid="125797972524818282">"Крај"</string>
+    <string name="space" msgid="804232271282109749">"Оддалечувач"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Менување мени/тастатура"</string>
+    <string name="select_button" msgid="1597989540662710653">"Изберете копче за додавање"</string>
+    <string name="add_button" msgid="4134946063432258161">"Додај копче"</string>
+    <string name="save" msgid="2311877285724540644">"Зачувај"</string>
+    <string name="reset" msgid="2448168080964209908">"Ресетирај"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Не е пронајдено копче „Дома“"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Потребно е копче „Дома“ за да може да го движите уредот. Додајте копче „Дома“ пред зачувувањето."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Приспособи ја ширината на копчето"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Табла со исечоци"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Таблата со исечоци овозможува ставките да се довлечат директно на неа. Исто така, ставките може да се извлечат директно од таблата со исечоци кога таа е присутна."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Приспособено копче за навигација"</string>
+    <string name="keycode" msgid="7335281375728356499">"Код од тастери"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Копчињата на кодовите од тастери овозможуваат тастерите на тастатурата да се додадат на лентата за навигација. Кога се притиснати тие го поддржуваат избраниот тастер на тастатурата. Прво мора да се избере тастерот за копчето, по што на копчето се прикажува слика."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Изберете копче за тастатура"</string>
+    <string name="preview" msgid="9077832302472282938">"Преглед"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
deleted file mode 100644
index ce7a13a..0000000
--- a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Затвори ја слика во слика"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Цел екран"</string>
-    <string name="pip_play" msgid="674145557658227044">"Пушти"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Пауза"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Откажи"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Задржете ја Почетна страница за да ја контролирате Слика во слика"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index a393e42..5cc33b3 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"വൈഫൈ"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"സിം ഇല്ല."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"സെല്ലുലാർ ഡാറ്റ ഓഫാണ്"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ബ്ലൂടൂത്ത് ടെതറിംഗ്."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"ഫ്ലൈറ്റ് മോഡ്."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM കാർഡൊന്നുമില്ല."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"സ്ക്രീൻ പിൻ ചെയ്യൽ"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"തിരയുക"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കാനായില്ല."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"കൂടുതൽ"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> എണ്ണം കൂടി"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ചരിത്രം"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"മായ്‌ക്കുക"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"തിരശ്ചീനമായി വേർതിരിക്കുക"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ലംബമായി വേർതിരിക്കുക"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ഇഷ്‌ടാനുസൃതമായി വേർതിരിക്കുക"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"സാധാരണ വര്‍ണ്ണങ്ങൾ"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"രാത്രി വര്‍ണ്ണങ്ങൾ"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"ഇഷ്ടാനുസൃത വര്‍ണ്ണങ്ങൾ"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"യാന്ത്രികം"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"തിരിച്ചറിയാനാകാത്ത വർണ്ണങ്ങൾ"</string>
     <string name="color_transform" msgid="6985460408079086090">"വർണ്ണ പരിഷ്കരണം"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"ദ്രുത ക്രമീകരണ ടൈൽ കാണിക്കുക"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ഹെഡ്ഫോണുകൾ കണക്റ്റുചെയ്തു"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ഹെഡ്‌സെറ്റ് കണക്‌റ്റുചെയ്‌തു"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"സ്റ്റാറ്റസ് ബാറിൽ കാണിക്കുന്നതിൽ നിന്ന് ഐക്കണുകളെ പ്രവർത്തനക്ഷമമാക്കുകയോ പ്രവർത്തനരഹിതമാക്കുകയോ ചെയ്യുക"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"ഡാറ്റ സേവർ"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ഡാറ്റാ സേവർ ഓണാണ്"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ഡാറ്റാ സേവർ ഓഫാണ്"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"ഓൺ"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"നാവിഗേഷൻ ബാർ"</string>
+    <string name="start" msgid="6873794757232879664">"ആരംഭിക്കൂ"</string>
+    <string name="center" msgid="4327473927066010960">"മധ്യം"</string>
+    <string name="end" msgid="125797972524818282">"അവസാനിപ്പിക്കുക"</string>
+    <string name="space" msgid="804232271282109749">"സ്പേസർ"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"മെനു / കീബോർഡ് സ്വിച്ചർ"</string>
+    <string name="select_button" msgid="1597989540662710653">"ചേർക്കാൻ, ബട്ടൺ തിരഞ്ഞെടുക്കൂ"</string>
+    <string name="add_button" msgid="4134946063432258161">"ബട്ടൺ ചേർക്കുക"</string>
+    <string name="save" msgid="2311877285724540644">"സംരക്ഷിക്കുക"</string>
+    <string name="reset" msgid="2448168080964209908">"പുനഃസജ്ജമാക്കുക"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"ഒരു ഹോം ബട്ടണും കണ്ടെത്തിയില്ല"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ഈ ഉപകരണം നാവിഗേറ്റ് ചെയ്യുന്നതിന് ഒരു ഹോം ബട്ടൺ ആവശ്യമാണ്, സംരക്ഷിക്കുന്നതിന് മുമ്പ് ഒരു ഹോം ബട്ടൺ ചേർക്കുക."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"ബട്ടൺ വീതി ക്രമീകരിക്കുക"</string>
+    <string name="clipboard" msgid="1313879395099896312">"ക്ലിപ്പ്ബോർഡ്"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"ഇനങ്ങളെ ക്ലിപ്പ്‌ബോർഡിലേക്ക് നേരിട്ട് വലിച്ചിടാൻ ക്ലിപ്പ്‌ബോർഡ് അനുവദിക്കുന്നു. ഇനങ്ങളെ ക്ലിപ്പ്‌ബോർഡിന് പുറത്തേക്ക് നേരിട്ട് വലിച്ചിടുകയുമാകാം."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"ഇഷ്ടാനുസൃത നാവിഗേഷൻ ബട്ടൺ"</string>
+    <string name="keycode" msgid="7335281375728356499">"കീകോഡ്"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"നാവിഗേഷൻ ബാറിലേക്ക് കീബോർഡ് കീകൾ ചേർക്കുന്നതിനെ കീകോഡ് ബട്ടണുകൾ അനുവദിക്കുന്നു. അമർത്തുമ്പോൾ, തിരഞ്ഞെടുത്ത കീയെ അവ അനുകരിക്കുന്നു. ആദ്യം ബട്ടണിനായി കീ തിരഞ്ഞെടുക്കണം, തുടർന്ന് ബട്ടണിൽ കാണിക്കാനുള്ള ചിത്രം തിരഞ്ഞെടുക്കണം."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"കീബോർഡ് ബട്ടൺ തിരഞ്ഞെടുക്കൂ"</string>
+    <string name="preview" msgid="9077832302472282938">"പ്രിവ്യു നടത്തുക"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
deleted file mode 100644
index 4bb15fb..0000000
--- a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP അടയ്ക്കുക"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"പൂര്‍ണ്ണ സ്ക്രീന്‍"</string>
-    <string name="pip_play" msgid="674145557658227044">"പ്ലേ ചെയ്യുക"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"തൽക്കാലം നിർത്തൂ"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"റദ്ദാക്കുക"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP നിയന്ത്രിക്കാൻ ഹോം പിടിക്കുക"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 9b45994..b8ce3b4 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -144,6 +144,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM байхгүй."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Мобайл датаг унтраасан байна"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Блютүүт модем болж байна."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Нислэгийн горим"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM карт байхгүй."</string>
@@ -298,8 +299,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"дэлгэц тогтоох"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж чадсангүй."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Илүү"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> Илүү"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Түүх"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Устгах"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Хэвтээ чиглэлд хуваах"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Босоо чиглэлд хуваах"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Хүссэн хэлбэрээр хуваах"</string>
@@ -465,6 +466,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Хэвийн өнгө"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Шөнийн өнгө"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Өгөгдмөл өнгө"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Автомат"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Үл мэдэгдэх өнгө"</string>
     <string name="color_transform" msgid="6985460408079086090">"Өнгөний өөрчлөлт"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Түргэн тохиргооны хэсгийг харуулах"</string>
@@ -491,10 +493,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Чихэвч холбогдсон"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Чихэвч холбогдсон"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Статусын самбарт харагдах дүрс тэмдгийг идэвхжүүлэх эсвэл идэвхгүй болгоно уу."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Өгөгдөл хамгаалагч"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Өгөгдөл хамгаалагчийг асаасан байна"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Өгөгдөл хамгаалагчийг унтраасан байна"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Идэвхтэй"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Навигацийн самбар"</string>
+    <string name="start" msgid="6873794757232879664">"Эхлэх"</string>
+    <string name="center" msgid="4327473927066010960">"Гол хэсэг"</string>
+    <string name="end" msgid="125797972524818282">"Төгсгөл"</string>
+    <string name="space" msgid="804232271282109749">"Зай авагч"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Цэс / Гар солигч"</string>
+    <string name="select_button" msgid="1597989540662710653">"Нэмэх товчлуурыг сонгох"</string>
+    <string name="add_button" msgid="4134946063432258161">"Нэмэх товчлуур"</string>
+    <string name="save" msgid="2311877285724540644">"Хадгалах"</string>
+    <string name="reset" msgid="2448168080964209908">"Бүгдийг цэвэрлэх"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Нүүр хуудас товчлуур байхгүй"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Энэ төхөөрөмжийг удирдахын тулд нүүр хуудас товчлуур шаардлагатай байна. Хадгалахын өмнө нүүр хуудасны товчлуур нэмнэ үү."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Товчлуурын өргөнг тохируулах"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Түр санах ой"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Түр санах ой нь аливаа зүйлийг түр санах ойд зөөх боломжийг олгодог. Мөн тухайн зүйлсийг түр санах ойгоос зөөх боломжтой."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Навигацийн товчлуурыг өөрчлөх"</string>
+    <string name="keycode" msgid="7335281375728356499">"Түлхүүр код"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Түлхүүр код товчлуур нь гарын түлхүүрийг навигацийн самбарт нэмэхийг зөвшөөрдөг. Дарсан үед гарын сонгосон товчлуурыг дуурайдаг. Эхлээд товчлуурын түлхүүрийг сонгох шаардлагатай бөгөөд дараа нь зохих зургийг сонгоно."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Гарын товчлуур сонгох"</string>
+    <string name="preview" msgid="9077832302472282938">"Урьдчилж харах"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
deleted file mode 100644
index 04df731..0000000
--- a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP-г хаах"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Бүтэн дэлгэц"</string>
-    <string name="pip_play" msgid="674145557658227044">"Тоглуулах"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Түр зогсоох"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Цуцлах"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP-г удирдахын тулд HOME-г дарна уу"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 9329909..bb41693 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"वाय-फाय"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"सिम नाही."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"मोबाइल डेटा बंद"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ब्लूटुथ टिथरिंग."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"विमान मोड."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"सिम कार्ड नाही."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्‍क्रीन पिन करणे"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"शोधा"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करणे शक्य झाले नाही."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"अधिक"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"आणखी <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"इतिहास"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"साफ करा"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"क्षैतिज विभाजित करा"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"अनुलंब विभाजित करा"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"सानुकूल विभाजित करा"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"सामान्य रंग"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"रात्रीचे रंग"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"सानुकूल रंग"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"स्वयं"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"अज्ञात रंग"</string>
     <string name="color_transform" msgid="6985460408079086090">"रंग सुधारणा"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"द्रुत सेटिंग्ज टाइल दर्शवा"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफोन कनेक्ट केले"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हेडसेट कनेक्ट केला"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"चिन्हे स्टेटस बारमध्ये दर्शविले जाण्‍यापासून प्रतिबंधित करण्‍यासाठी ती सक्षम किंवा अक्षम करा."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"डेटा बचतकर्ता"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा बचतकर्ता चालू आहे"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा बचतकर्ता बंद आहे"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"चालू"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"नॅव्हिगेशन बार"</string>
+    <string name="start" msgid="6873794757232879664">"प्रारंभ"</string>
+    <string name="center" msgid="4327473927066010960">"मध्यवर्ती"</string>
+    <string name="end" msgid="125797972524818282">"समाप्ती"</string>
+    <string name="space" msgid="804232271282109749">"स्पेसर"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"मेनू / कीबोर्ड स्विचर"</string>
+    <string name="select_button" msgid="1597989540662710653">"जोडण्यासाठी बटण निवडा"</string>
+    <string name="add_button" msgid="4134946063432258161">"बटण जोडा"</string>
+    <string name="save" msgid="2311877285724540644">"जतन करा"</string>
+    <string name="reset" msgid="2448168080964209908">"रीसेट करा"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"मुख्यपृष्ठ बटण आढळले नाही"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"हे डिव्हाइस नेव्हिगेट करण्यासाठी मुख्यपृष्ठ बटण सक्षम असणे आवश्यक आहे. कृपया जतन करण्यापूर्वी एक मुख्यपृष्ठ बटण जोडा."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"बटण रूंदी समायोजित करा"</string>
+    <string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"थेट क्लिपबोर्डवर ड्रॅग केले जाण्यासाठी क्लिपबोर्ड आयटमना अनुमती देते. क्लिपबोर्डवर आयटम असताना ते थेट क्लिपबोर्ड बाहेर देखील ड्रॅग केले जाऊ शकतात."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"सानुकूल नेव्हिगेशन बटण"</string>
+    <string name="keycode" msgid="7335281375728356499">"कीकोड"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"कीकोड बटणे नेव्हिगेशन बारमध्ये कीबोर्ड की ना जोडण्यासाठी अनुमती देतात. दाबल्यानंतर ते निवडलेल्या कीबोर्ड की चे अनुकरण करतात. बटणासाठी प्रथम की त्यानंतर बटणावर दर्शविली जाण्यासाठी प्रतिमा निवडणे आवश्यक आहे."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"कीबोर्ड बटण निवडा"</string>
+    <string name="preview" msgid="9077832302472282938">"पूर्वावलोकन"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
deleted file mode 100644
index 021f34c..0000000
--- a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP बंद करा"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्क्रीन"</string>
-    <string name="pip_play" msgid="674145557658227044">"प्ले करा"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"विराम द्या"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"रद्द करा"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP नियंत्रित करण्‍यासाठी मुख्‍यपृष्‍ठ धरून ठेवा"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index a4e90c0..2f2a238 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Tiada SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Data Selular Dimatikan"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Penambatan Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mod pesawat"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Tiada kad SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"penyematan skrin"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulakan <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Lagi"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> Lagi"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Sejarah"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Kosongkan"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Mendatar Terpisah"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Menegak Terpisah"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tersuai Terpisah"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Warna biasa"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Warna malam"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Warna tersuai"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Warna tidak diketahui"</string>
     <string name="color_transform" msgid="6985460408079086090">"Pengubahsuaian warna"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Tunjukkan jubin Tetapan Pantas"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fon kepala disambungkan"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Set kepala disambungkan"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Dayakan atau lumpuhkan ikon daripada dipaparkan dalam bar status."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Penjimat Data"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Penjimat Data dihidupkan"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Penjimat Data dimatikan"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Hidup"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Bar navigasi"</string>
+    <string name="start" msgid="6873794757232879664">"Mula"</string>
+    <string name="center" msgid="4327473927066010960">"Tengah"</string>
+    <string name="end" msgid="125797972524818282">"Tamat"</string>
+    <string name="space" msgid="804232271282109749">"Peruang"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Penukar Menu/Papan Kekunci"</string>
+    <string name="select_button" msgid="1597989540662710653">"Pilih butang untuk ditambahkan"</string>
+    <string name="add_button" msgid="4134946063432258161">"Tambahkan butang"</string>
+    <string name="save" msgid="2311877285724540644">"Simpan"</string>
+    <string name="reset" msgid="2448168080964209908">"Tetapkan semula"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Butang laman utama tdk ditemui"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Butang laman utama diperlukan untuk menavigasi peranti ini. Sila tambahkan butang laman utama sebelum menyimpan."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Laraskan lebar butang"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Papan Keratan"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Papan Keratan membolehkan item diseret secara langsung ke papan keratan. Jika terdapat item pada papan keratan, item itu boleh diseret keluar daripada papan keratan juga."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Butang navigasi tersuai"</string>
+    <string name="keycode" msgid="7335281375728356499">"Kod Kunci"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Butang Kod Kunci membolehkan kunci papan kekunci ditambahkan pada Bar Navigasi. Apabila ditekan, butang ini meniru kunci papan kekunci yang dipilih. Mula-mula, kunci mesti dipilih untuk butang tersebut, diikuti dengan imej yang hendak dipaparkan pada butang."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Pilih Butang Papan Kekunci"</string>
+    <string name="preview" msgid="9077832302472282938">"Pratonton"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
deleted file mode 100644
index 850910b..0000000
--- a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Tutup PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Skrin penuh"</string>
-    <string name="pip_play" msgid="674145557658227044">"Main"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Jeda"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Batal"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Tahan kekunci HOME untuk mengawal PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index cfcc15ab..32003bf 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"ဝိုင်ဖိုင်"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"ဆင်းကဒ်မရှိပါ။"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"ဆဲလ်လူလာဒေတာပိတ်ထားသည်"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ဘလူးတုသ်မှတဆင့်ပြန်လည်ချိတ်ဆက်ခြင်း"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"လေယာဥ်ပျံပေါ်အသုံးပြုသောစနစ်။"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM ကဒ် မရှိပါ"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"မျက်နှာပြင် ပင်ထိုးမှု"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ကို မစနိုင်ပါ။"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"နောက်ထပ်"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"နောက်ထပ် <xliff:g id="NUMBER">%d</xliff:g> ခု"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"မှတ်တမ်း"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ရှင်းလင်းပါ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ရေပြင်ညီ ပိုင်းမည်"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ဒေါင်လိုက်ပိုင်းမည်"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"စိတ်ကြိုက် ပိုင်းမည်"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"ပုံမှန် အရောင်များ"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"ည အရောင်များ"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"စိတ်ကြိုက် အရောင်များ"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"အလိုအလျောက်"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"မသိသည့် အရောင်များ"</string>
     <string name="color_transform" msgid="6985460408079086090">"အရောင် မွမ်းမံမှု"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"အမြန် ဆက်တင် လေးထောင့်ကွက်ကို ပြပါ"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"နားကြပ်တပ်ဆင်ပြီးပါပြီ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"မိုက်ခွက်ပါနားကြပ်တပ်ဆင်ပြီးပါပြီ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"အခြေအနေဘားတန်းတွင် သင်္ကေတပုံပြခြင်းကို ဖွင့်ရန် သို့မဟုတ် ပိတ်ရန်"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"ဒေတာချွေတာမှု"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ဒေတာချွေတာမှု ဖွင့်ထားသည်"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ဒေတာချွေတာမှု ပိတ်ထားသည်"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"ဖွင့်ပါ"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"ရွှေ့လျားရန်ဘားတန်း"</string>
+    <string name="start" msgid="6873794757232879664">"စတင်ပါ"</string>
+    <string name="center" msgid="4327473927066010960">"ဌာန"</string>
+    <string name="end" msgid="125797972524818282">"ပြီးပါပြီ"</string>
+    <string name="space" msgid="804232271282109749">"နေရာလွတ်ခြားစနစ်"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"မန်နယူး / ကီးဘုတ်ပြောင်းစနစ်"</string>
+    <string name="select_button" msgid="1597989540662710653">"ပေါင်းထည့်ရန် ခလုတ်ကိုရွေးပါ"</string>
+    <string name="add_button" msgid="4134946063432258161">"ခလုတ်ပေါင်းထည့်ပါ"</string>
+    <string name="save" msgid="2311877285724540644">"သိမ်းဆည်းပါ"</string>
+    <string name="reset" msgid="2448168080964209908">"ပြန်လည်စတင်စေရန်"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"ပင်မခလုတ်မတွေ့ပါ"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ဤစက်ပစ္စည်းကိုရွှေ့လျားနိုင်ရန် ပင်မခလုတ် လိုအပ်ပါသည်။ မသိမ်းဆည်းမီ ပင်မခလုတ်ကို ပေါင်းထည့်ပါ။"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"ခလုတ်အလျားကို ချိန်ညှိပါ"</string>
+    <string name="clipboard" msgid="1313879395099896312">"ကလစ်ဘုတ်"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"ကလစ်ဘုတ်သည် အရာဝတ္တုများကို ကလစ်ဘုတ်သို့တိုက်ရိုက် ဆွဲသွင်းရန်ခွင့်ပြုပါသည်။ အရာဝတ္တုများရှိနေလျှင်လည်း ကလစ်ဘုတ်၏အပြင်သို့ ၎င်းတို့ကိုတိုက်ရိုက် ဆွဲထုတ်နိုင်သည်။"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"စိတ်ကြိုက်ရွှေ့လျားရန် ခလုတ်"</string>
+    <string name="keycode" msgid="7335281375728356499">"ကီးကုဒ်"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"ကီးကုဒ်ခလုတ်များသည် ကီးဘုတ်ခလုတ်များကို ရွှေ့လျားရန်ဘားတန်းသို့ ပေါင်းထည့်ရန်ခွင့်ပြုသည်။ နှိပ်လိုက်လျှင် ၎င်းသည် ရွေးချယ်ထားသည့် ကီးဘုတ်ခလုတ်အတိုင်း လုပ်ဆောင်ပါသည်။ ပထမဦးစွာ ခလုတ်အတွက် ကီးကိုရွေးချယ်ပြီး ခလုတ်ပေါ်တွင် ပြမည့်ပုံကို ဆက်လက်ရွေးချယ်ရပါမည်။"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"ကီးဘုတ်ခလုတ်ကို ရွေးချယ်ပါ"</string>
+    <string name="preview" msgid="9077832302472282938">"အစမ်းကြည့်ပါ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings_tv.xml b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
deleted file mode 100644
index 98d05a9..0000000
--- a/packages/SystemUI/res/values-my-rMM/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP ကို ပိတ်ပါ"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"မျက်နှာပြင် အပြည့်"</string>
-    <string name="pip_play" msgid="674145557658227044">"ဖွင့်ပါ"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"ဆိုင်းငံ့ပါ"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"ဖျက်သိမ်းပါ"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP ကို ​​ထိန်းချုပ်ရန် HOME ကို ကိုင်ထားပါ"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 377642b..f88445f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Uten SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobildata er av"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-internettdeling."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Flymodus."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Mangler SIM-kort."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"én-appsmodus"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Kunne ikke starte <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mer"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> til"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Logg"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Tøm"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Del horisontalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Del vertikalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Del tilpasset"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normale farger"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Nattfarger"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Spesialtilpassede farger"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatisk"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Ukjente farger"</string>
     <string name="color_transform" msgid="6985460408079086090">"Fargemodifisering"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Vis ruten for hurtiginnstillinger"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Øretelefoner er tilkoblet"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Hodetelefoner er tilkoblet"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Vis eller skjul ikoner i statusfeltet."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Datasparing"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Datasparing er på"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Datasparing er av"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"På"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigasjonsrad"</string>
+    <string name="start" msgid="6873794757232879664">"Start"</string>
+    <string name="center" msgid="4327473927066010960">"Midtstilt"</string>
+    <string name="end" msgid="125797972524818282">"Slutt"</string>
+    <string name="space" msgid="804232271282109749">"Mellomrom"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Bytteknapp for meny/tastatur"</string>
+    <string name="select_button" msgid="1597989540662710653">"Velg en knapp du vil legge til"</string>
+    <string name="add_button" msgid="4134946063432258161">"Legg til knapp"</string>
+    <string name="save" msgid="2311877285724540644">"Lagre"</string>
+    <string name="reset" msgid="2448168080964209908">"Tilbakestill"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Fant ingen startsideknapp"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Det kreves en startsideknapp for å kunne navigere på denne enheten. Legg til en startsideknapp før du lagrer."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Juster bredden på knappen"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Utklippstavle"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Med Clipboard-funksjonen kan elementer dras direkte til utklippstavlen. Hvis det finnes elementer på utklippstavlen, kan de også dras ut derfra."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Spesialtilpasset navigasjonsknapp"</string>
+    <string name="keycode" msgid="7335281375728356499">"Nøkkelkode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Du kan bruke nøkkelkodeknapper for å legge tastaturtaster direkte på navigasjonsraden. Når du trykker på disse knappene, fungerer de på samme måte som de valgte tastaturtastene. Du må først velge hvilken tast hver knapp skal fungere som, og deretter et bilde som vises på knappen."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Velg tastaturtast"</string>
+    <string name="preview" msgid="9077832302472282938">"Forhåndsvisning"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
deleted file mode 100644
index ba191a4..0000000
--- a/packages/SystemUI/res/values-nb/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Lukk PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Fullskjerm"</string>
-    <string name="pip_play" msgid="674145557658227044">"Spill av"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Sett på pause"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Avbryt"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Hold inne STARTSIDEN for å kontrollere PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 2a15c87..ffd2b8f 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"वाइफाइ"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM छैन।"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"सेलुलर डेटा अफ छ"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ब्लुटुथ टेदर गर्दै।"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"हवाइजहाज मोड।"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM कार्ड छैन।"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रिन पिन गर्दै"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"खोजी गर्नुहोस्"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"सुरु गर्न सकिएन <xliff:g id="APP">%s</xliff:g>।"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"थप"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> थप"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"इतिहास"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"मेटाउनुहोस्"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"तेर्सो रूपमा विभाजन गर्नुहोस्"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ठाडो रूपमा विभाजन गर्नुहोस्"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"अनुकूलन विभाजन गर्नुहोस्"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"सामान्य रङहरू"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"रात्री रङहरू"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"अनुकूलन रङहरू"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"स्वतः"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"अज्ञात रङहरू"</string>
     <string name="color_transform" msgid="6985460408079086090">"रङ परिमार्जन"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"द्रुत सेटिङ टाइल देखाउनुहोस्"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफोनहरू जडान गरियो"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हेडसेट जडान गरियो"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"वस्तुस्थिति पट्टीमा देखाइनको लागि आइकनहरू सक्रिय वा निष्क्रिय गर्नुहोस्।"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"डेटा सेभर"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"डेटा सेभर अन छ"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"डेटा सेभर बन्द छ"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"सक्रिय गर्नुहोस्"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"नेभिगेशन पट्टी"</string>
+    <string name="start" msgid="6873794757232879664">"सुरु गर्नुहोस्"</string>
+    <string name="center" msgid="4327473927066010960">"केन्द्र"</string>
+    <string name="end" msgid="125797972524818282">"अन्त्य गर्नुहोस्"</string>
+    <string name="space" msgid="804232271282109749">"स्पेसर"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"मेनु / किबोर्ड स्विचर"</string>
+    <string name="select_button" msgid="1597989540662710653">"थप्नका लागि बटन चयन गर्नुहोस्"</string>
+    <string name="add_button" msgid="4134946063432258161">"बटन थप्नुहोस्"</string>
+    <string name="save" msgid="2311877285724540644">"सुरक्षित गर्नुहोस्"</string>
+    <string name="reset" msgid="2448168080964209908">"पुनःसेट गर्नु"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"गृह बटन फेला परेन"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"यस यन्त्रलाई नेभिगेट गर्न सक्षम हुन गृह बटन आवश्यक छ। कृपया सुरक्षित गर्नु पूर्व गृह बटन थप्नुहोस्।"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"बटनको चौडाइ समायोजन गर्नुहोस्"</string>
+    <string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"क्लिपबोर्डले वस्तुहरूलाई क्लिपबोर्डमा प्रत्यक्ष तान्न अनुमति दिन्छ। प्रस्तुत गर्दा वस्तुहरूलाई क्लिपबोर्डबाट प्रत्यक्ष रूपमा बाहिर तान्न पनि सकिन्छ।"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"अनुकूलनको नेभिगेशन बटन"</string>
+    <string name="keycode" msgid="7335281375728356499">"Keycode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Keycode बटनहरूले किबोर्ड कुञ्जीहरूलाई नेभिगेशन पट्टीमा थपिने अनुमति दिन्छ। थिच्दा तिनीहरूले चयन गरिएको किबोर्ड कुञ्जी अनुकरण गर्छन्। सुरुमा बटनका लागि कुञ्जी चयन गर्नुपर्छ, त्यसपछि बटनमा छवि देखिनुपर्छ।"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"किबोर्ड बटन चयन गर्नुहोस्"</string>
+    <string name="preview" msgid="9077832302472282938">"पूर्वावलोकन"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
deleted file mode 100644
index 09cc01d..0000000
--- a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP बन्द गर्नुहोस्"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्क्रिन"</string>
-    <string name="pip_play" msgid="674145557658227044">"प्ले गर्नुहोस्"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"रोक्नुहोस्"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"रद्द गर्नुहोस्"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP नियन्त्रण गर्न HOME थिचिरहनुहोस्"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 3e91b5c..814a1a8 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wifi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Geen simkaart."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobiele data uit"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-tethering."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Vliegtuigmodus."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Geen simkaart."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"scherm vastzetten"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Kan <xliff:g id="APP">%s</xliff:g> niet starten."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Meer"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Nog <xliff:g id="NUMBER">%d</xliff:g> andere"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Geschiedenis"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Wissen"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontaal splitsen"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verticaal splitsen"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Aangepast splitsen"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normale kleuren"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Nachtkleuren"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Aangepaste kleuren"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatisch"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Onbekende kleuren"</string>
     <string name="color_transform" msgid="6985460408079086090">"Kleuraanpassing"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Tegel voor \'Snelle instellingen\' weergeven"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Hoofdtelefoon aangesloten"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset aangesloten"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"De weergave van pictogrammen in de statusbalk in- of uitschakelen."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Databesparing"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Databesparing is ingeschakeld"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Databesparing is uitgeschakeld"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Aan"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigatiebalk"</string>
+    <string name="start" msgid="6873794757232879664">"Begin"</string>
+    <string name="center" msgid="4327473927066010960">"Midden"</string>
+    <string name="end" msgid="125797972524818282">"Einde"</string>
+    <string name="space" msgid="804232271282109749">"Opvulling"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menu/toetsenbord-schakelaar"</string>
+    <string name="select_button" msgid="1597989540662710653">"Knop kiezen om toe te voegen"</string>
+    <string name="add_button" msgid="4134946063432258161">"Knop toevoegen"</string>
+    <string name="save" msgid="2311877285724540644">"Opslaan"</string>
+    <string name="reset" msgid="2448168080964209908">"Resetten"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Geen startknop gevonden"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Er is een startknop vereist om te navigeren op dit apparaat. Voeg een startknop toe voordat je opslaat."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Breedte van knop aanpassen"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Klembord"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Met Klembord kunnen items rechtstreeks naar het klembord worden gesleept. Indien aanwezig, kunnen items ook rechtstreeks van het klembord worden gesleept."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Aangepaste navigatieknop"</string>
+    <string name="keycode" msgid="7335281375728356499">"Toetscode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Met toetscodeknoppen kunnen toetsenbordtoetsen worden toegevoegd aan de navigatiebalk. Wanneer hierop wordt gedrukt, emuleren ze de geselecteerde toetsenbordtoets. Eerst moet de toets voor de knop worden geselecteerd, gevolgd door een afbeelding die wordt weergegeven op de knop."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Toetsenbordknop selecteren"</string>
+    <string name="preview" msgid="9077832302472282938">"Voorbeeld"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
deleted file mode 100644
index 59c711d..0000000
--- a/packages/SystemUI/res/values-nl/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP sluiten"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Volledig scherm"</string>
-    <string name="pip_play" msgid="674145557658227044">"Afspelen"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Onderbreken"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Annuleren"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Houd HOME ingedrukt om PIP te bedienen"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 1c98369..d83de21 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"ਕਿਨਾਰਾ"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"ਕੋਈ SIM ਨਹੀਂ।"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"ਸੈਲਿਊਲਰ ਡੈਟਾ ਬੰਦ ਹੈ"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth ਟੀਥਰਿੰਗ।"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"ਏਅਰਪਲੇਨ ਮੋਡ।"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"ਕੋਈ SIM ਕਾਰਡ ਨਹੀਂ।"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ਸਕ੍ਰੀਨ ਪਿਨਿੰਗ"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ਖੋਜੋ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਚਾਲੂ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"ਹੋਰ"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> ਹੋਰ"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ਇਤਿਹਾਸ"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ਸਾਫ਼ ਕਰੋ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ਹੌਰੀਜ਼ੌਂਟਲ ਸਪਲਿਟ"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ਵਰਟੀਕਲ ਸਪਲਿਟ"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ਕਸਟਮ ਸਪਲਿਟ"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"ਸਧਾਰਨ ਰੰਗ"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"ਰਾਤ ਦੇ ਰੰਗ"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"ਕਸਟਮ ਰੰਗ"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"ਸਵੈ"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"ਅਗਿਆਤ ਰੰਗ"</string>
     <string name="color_transform" msgid="6985460408079086090">"ਰੰਗ ਸੋਧ"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਟਾਇਲ ਵਿਖਾਓ"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ਹੈੱਡਫੋਨਾਂ ਨੂੰ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ਹੈੱਡਸੈੱਟ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ਚਿੰਨ੍ਹਾਂ ਦੇ ਸਥਿਤੀ ਪੱਟੀ ਵਿੱਚ ਵਿਖਾਏ ਜਾਣ ਨੂੰ ਯੋਗ ਜਾਂ ਅਯੋਗ ਬਣਾਓ।"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"ਡੈਟਾ ਸੇਵਰ"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ਡੈਟਾ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ਡੈਟਾ ਸੇਵਰ ਬੰਦ ਹੈ"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"ਚਾਲੂ"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"ਆਵਾਗੌਣ ਪੱਟੀ"</string>
+    <string name="start" msgid="6873794757232879664">"ਸ਼ੁਰੂ ਕਰੋ"</string>
+    <string name="center" msgid="4327473927066010960">"ਕੇਂਦਰ"</string>
+    <string name="end" msgid="125797972524818282">"ਸਮਾਪਤ"</string>
+    <string name="space" msgid="804232271282109749">"ਸਪੇਸਰ"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"ਮੀਨੂ/ਕੀ-ਬੋਰਡ ਸਵਿੱਚਰ"</string>
+    <string name="select_button" msgid="1597989540662710653">"ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਬਟਨ ਚੁਣੋ"</string>
+    <string name="add_button" msgid="4134946063432258161">"ਬਟਨ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="save" msgid="2311877285724540644">"ਰੱਖਿਅਤ ਕਰੋ"</string>
+    <string name="reset" msgid="2448168080964209908">"ਰੀਸੈਟ ਕਰੋ"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"ਕੋਈ ਹੋਮ ਬਟਨ ਨਹੀਂ ਮਿਲਿਆ"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ਇਸ ਡੀਵਾਈਸ ਵਿੱਚ ਆਵਾਗੌਣ ਕਰਨ ਲਈ ਇੱਕ ਹੋਮ ਬਟਨ ਦੀ ਲੋੜ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਰੱਖਿਅਤ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਇੱਕ ਹੋਮ ਬਟਨ ਸ਼ਾਮਲ ਕਰੋ।"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"ਬਟਨ ਚੁੜਾਈ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
+    <string name="clipboard" msgid="1313879395099896312">"ਕਲਿੱਪਬੋਰਡ"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"ਕਲਿੱਪਬੋਰਡ ਆਈਟਮਾਂ ਨੂੰ ਸਿੱਧੇ ਕਲਿੱਪਬੋਰਡ ਵਿੱਚ ਘਸੀਟਣ ਦਿੰਦਾ ਹੈ। ਮੌਜੂਦ ਹੋਣ \'ਤੇ ਆਈਟਮਾਂ ਸਿੱਧੇ ਕਲਿੱਪਬੋਰਡ ਤੋਂ ਬਾਹਰ ਵੀ ਘਸੀਟੀਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ।"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਆਵਾਗੌਣ ਬਟਨ"</string>
+    <string name="keycode" msgid="7335281375728356499">"ਕੀਕੋਡ"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"ਕੀਕੋਡ ਬਟਨ ਕੀ-ਬੋਰਡ ਕੁੰਜੀਆਂ ਨੂੰ ਆਵਾਗੌਣ ਪੱਟੀ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰਨ ਦਿੰਦੇ ਹਨ। ਦਬਾਏ ਜਾਣ \'ਤੇ ਇਹ ਚੁਣੀਆਂ ਗਈਆਂ ਕੀ-ਬੋਰਡ ਕੁੰਜੀਆਂ ਨੂੰ ਇਮੂਲੇਟ ਕਰਦੇ ਹਨ। ਬਟਨ \'ਤੇ ਵਿਖਾਈ ਜਾਣ ਵਾਲੀ ਤਸਵੀਰ ਦਾ ਅਨੁਸਰਣ ਕਰਦੇ ਹੋਏ, ਪਹਿਲਾਂ ਬਟਨ ਲਈ ਇੱਕ ਕੁੰਜੀ ਨੂੰ ਚੁਣਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ।"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"ਕੀ-ਬੋਰਡ ਬਟਨ ਚੁਣੋ"</string>
+    <string name="preview" msgid="9077832302472282938">"ਝਲਕ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
deleted file mode 100644
index 26cc94a..0000000
--- a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP ਬੰਦ ਕਰੋ"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
-    <string name="pip_play" msgid="674145557658227044">"ਚਲਾਓ"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"ਰੋਕੋ"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"ਰੱਦ ਕਰੋ"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਲਈ ਹੋਮ ਨੂੰ ਹੋਲਡ ਕਰੋ"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index fde806b..728b6da 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -148,6 +148,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Brak karty SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Komórkowa transmisja danych jest wyłączona"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Powiązanie Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Tryb samolotowy."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Brak karty SIM."</string>
@@ -302,8 +303,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"przypinanie ekranu"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nie udało się uruchomić aplikacji <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Więcej"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"i jeszcze <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Wyczyść"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podziel poziomo"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podziel pionowo"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podziel niestandardowo"</string>
@@ -469,6 +470,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Kolory standardowe"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Kolory nocne"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Kolory niestandardowe"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatycznie"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Nieznane kolory"</string>
     <string name="color_transform" msgid="6985460408079086090">"Zmiana koloru"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Pokazuj kafelek szybkich ustawień"</string>
@@ -495,10 +497,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Słuchawki są podłączone"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Zestaw słuchawkowy jest podłączony"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Włącz lub wyłącz wyświetlanie ikon na pasku stanu."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Oszczędzanie danych"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Oszczędzanie danych jest włączone"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Oszczędzanie danych jest wyłączone"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Wł."</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Pasek nawigacji"</string>
+    <string name="start" msgid="6873794757232879664">"Na początku"</string>
+    <string name="center" msgid="4327473927066010960">"Na środku"</string>
+    <string name="end" msgid="125797972524818282">"Na końcu"</string>
+    <string name="space" msgid="804232271282109749">"Spacja"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menu / przełączanie klawiatury"</string>
+    <string name="select_button" msgid="1597989540662710653">"Wybierz przycisk do dodania"</string>
+    <string name="add_button" msgid="4134946063432258161">"Dodaj przycisk"</string>
+    <string name="save" msgid="2311877285724540644">"Zapisz"</string>
+    <string name="reset" msgid="2448168080964209908">"Resetuj"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Brak przycisku ekranu głównego"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Do prawidłowej obsługi urządzenia potrzebny jest przycisk ekranu głównego. Dodaj go, zanim zapiszesz zmiany."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Regulacja szerokości przycisku"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Schowek"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Możesz przeciągać elementy bezpośrednio do schowka. Możesz też przeciągać umieszczone tam wcześniej elementy poza schowek."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Niestandardowy przycisk nawigacji"</string>
+    <string name="keycode" msgid="7335281375728356499">"Klawisz"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Na pasku nawigacji możesz umieszczać przyciski, które po naciśnięciu emulują funkcje klawiszy klawiatury. Najpierw musisz wybrać, jaki klawisz ma być przypisany do danego przycisku, a następnie wybrać dla niego grafikę."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Wybierz przycisk klawiatury"</string>
+    <string name="preview" msgid="9077832302472282938">"Podgląd"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
deleted file mode 100644
index 270ef86..0000000
--- a/packages/SystemUI/res/values-pl/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Zamknij PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Pełny ekran"</string>
-    <string name="pip_play" msgid="674145557658227044">"Odtwórz"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Wstrzymaj"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Anuluj"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Przytrzymaj przycisk STRONA GŁÓWNA, by sterować PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 38a6b79..c2fd0d1d 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Dados da rede celular desativados"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tethering Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avião."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Sem cartão SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação de tela"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mais"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Mais <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Histórico"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Limpar"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Cores normais"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Cores noturnas"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Cores personalizadas"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automáticas"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Cores desconhecidas"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modificação de cor"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar bloco de configurações rápidas"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fones de ouvido conectados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Fone de ouvido conectado"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ativar ou desativar a exibição de ícones na barra de status."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Economia de dados"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Economia de dados ativada"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"A Economia de dados está desativada"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Ativado"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barra de navegação"</string>
+    <string name="start" msgid="6873794757232879664">"Iniciar"</string>
+    <string name="center" msgid="4327473927066010960">"Centralizar"</string>
+    <string name="end" msgid="125797972524818282">"Fim"</string>
+    <string name="space" msgid="804232271282109749">"Espaçador"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Alternador de teclado / menu"</string>
+    <string name="select_button" msgid="1597989540662710653">"Selecione o botão p/ adicionar"</string>
+    <string name="add_button" msgid="4134946063432258161">"Adicionar botão"</string>
+    <string name="save" msgid="2311877285724540644">"Salvar"</string>
+    <string name="reset" msgid="2448168080964209908">"Redefinir"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Nenhum botão de início encontrado"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"É necessário um botão de início para navegar neste dispositivo. Adicione um botão de início antes de salvar."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Ajustar largura do botão"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Prancheta"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"A Prancheta permite que itens sejam arrastados diretamente para a área de transferência. Também é possível arrastar os itens diretamente para fora da área de transferência, quando estiver presente."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Botão de navegação personalizado"</string>
+    <string name="keycode" msgid="7335281375728356499">"Código de tecla"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Os botões de código de tecla permitem que as teclas do teclado sejam adicionadas à barra de navegação. Quando pressionados, eles emulam a tecla selecionada. Primeiro, a tecla deve ser selecionada para o botão, seguida de uma imagem a ser exibida no botão."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Escolha um botão do teclado"</string>
+    <string name="preview" msgid="9077832302472282938">"Visualização"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_car.xml b/packages/SystemUI/res/values-pt-rBR/strings_car.xml
index 072f614..5d754ef 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_car.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Dirija com segurança"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se atento às condições de direção e sempre obedeça às leis aplicáveis. As instruções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver o cruzamento de áreas administrativas. As informações comerciais também podem ser imprecisas ou incompletas. Os dados não são exibidos em tempo real, e a precisão da localização não pode ser garantida. Enquanto dirige, não manuseie seu dispositivo móvel nem use apps que não tenham sido criados para o Android Auto."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se atento às condições da estrada  e sempre obedeça às leis aplicáveis. As instruções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver o cruzamento de áreas administrativas. As informações comerciais também podem ser imprecisas ou incompletas. Os dados não são exibidos em tempo real, e a precisão da localização não pode ser garantida. Enquanto dirige, não manuseie seu dispositivo móvel nem use apps que não tenham sido criados para o Android Auto."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
deleted file mode 100644
index 131507c..0000000
--- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Fechar PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Tela cheia"</string>
-    <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancelar"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Mantenha \"PÁGINA INICIAL\" pressionado para controlar o PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 7e66dcf..41ba4bc 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Dados móveis desativados"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Ligação Bluetooth via telemóvel."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo de avião"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Nenhum cartão SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação no ecrã"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar o <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mais"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Mais <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Histórico"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Limpar"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Cores normais"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Cores noturnas"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Cores personalizadas"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automáticas"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Cores desconhecidas"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modificação de cor"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar o mosaico de Definições rápidas"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auscultadores ligados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auscultadores com microfone integrado ligados"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ativar ou desativar a apresentação de ícones na barra de estado."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Poupança de dados"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Poupança de dados ativada"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Poupança de dados desativada"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Ativado"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barra de navegação"</string>
+    <string name="start" msgid="6873794757232879664">"Início"</string>
+    <string name="center" msgid="4327473927066010960">"Centro"</string>
+    <string name="end" msgid="125797972524818282">"Fim"</string>
+    <string name="space" msgid="804232271282109749">"Espaçador"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menu/comutador de teclado"</string>
+    <string name="select_button" msgid="1597989540662710653">"Selecionar o botão a adicionar"</string>
+    <string name="add_button" msgid="4134946063432258161">"Adicionar botão"</string>
+    <string name="save" msgid="2311877285724540644">"Guardar"</string>
+    <string name="reset" msgid="2448168080964209908">"Repor"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Sem botão de página inicial"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"É necessário um botão de página inicial para navegar neste dispositivo. Adicione um botão de página inicial antes de guardar."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Ajustar largura do botão"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Área de transferência"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"A Área de transferência permite arrastar itens diretamente para a área de transferência. Também é possível arrastar itens diretamente para fora da mesma, quando aí se encontram."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Botão de navegação personalizado"</string>
+    <string name="keycode" msgid="7335281375728356499">"Código de tecla"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Os códigos de tecla permitem adicionar teclas do teclado à Barra de navegação. Quando são premidos, emulam a tecla do teclado selecionada. É necessário selecionar primeiro a tecla para botão e depois uma imagem que será apresentada no mesmo."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Selecionar o botão do teclado"</string>
+    <string name="preview" msgid="9077832302472282938">"Pré-visualizar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_car.xml b/packages/SystemUI/res/values-pt-rPT/strings_car.xml
index e53774b7..afb030a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_car.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Conduza com segurança"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se completamente atento às condições de condução e respeite sempre as leis aplicáveis. As direções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver a travessia de zonas administrativas. Os dados das empresas também podem ser imprecisos ou incompletos. Os dados não são fornecidos em tempo real e não é possível garantir a precisão da localização. Não manuseie o dispositivo móvel nem utilize aplicações não destinadas ao Android Auto durante a condução."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se completamente atento às condições de condução e respeite sempre as leis aplicáveis. As direções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver a travessia de áreas administrativas. Os dados das empresas também podem ser imprecisos ou incompletos. Os dados não são fornecidos em tempo real e não é possível garantir a precisão da localização. Não manuseie o dispositivo móvel nem utilize aplicações não destinadas ao Android Auto durante a condução."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
deleted file mode 100644
index e0ca35d..0000000
--- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Fechar PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Ecrã inteiro"</string>
-    <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Interromper"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancelar"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Prima sem soltar a tecla HOME para controlar o PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 38a6b79..c2fd0d1d 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Dados da rede celular desativados"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tethering Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avião."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Sem cartão SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação de tela"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mais"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Mais <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Histórico"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Limpar"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Cores normais"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Cores noturnas"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Cores personalizadas"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automáticas"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Cores desconhecidas"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modificação de cor"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Mostrar bloco de configurações rápidas"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fones de ouvido conectados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Fone de ouvido conectado"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ativar ou desativar a exibição de ícones na barra de status."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Economia de dados"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Economia de dados ativada"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"A Economia de dados está desativada"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Ativado"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Barra de navegação"</string>
+    <string name="start" msgid="6873794757232879664">"Iniciar"</string>
+    <string name="center" msgid="4327473927066010960">"Centralizar"</string>
+    <string name="end" msgid="125797972524818282">"Fim"</string>
+    <string name="space" msgid="804232271282109749">"Espaçador"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Alternador de teclado / menu"</string>
+    <string name="select_button" msgid="1597989540662710653">"Selecione o botão p/ adicionar"</string>
+    <string name="add_button" msgid="4134946063432258161">"Adicionar botão"</string>
+    <string name="save" msgid="2311877285724540644">"Salvar"</string>
+    <string name="reset" msgid="2448168080964209908">"Redefinir"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Nenhum botão de início encontrado"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"É necessário um botão de início para navegar neste dispositivo. Adicione um botão de início antes de salvar."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Ajustar largura do botão"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Prancheta"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"A Prancheta permite que itens sejam arrastados diretamente para a área de transferência. Também é possível arrastar os itens diretamente para fora da área de transferência, quando estiver presente."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Botão de navegação personalizado"</string>
+    <string name="keycode" msgid="7335281375728356499">"Código de tecla"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Os botões de código de tecla permitem que as teclas do teclado sejam adicionadas à barra de navegação. Quando pressionados, eles emulam a tecla selecionada. Primeiro, a tecla deve ser selecionada para o botão, seguida de uma imagem a ser exibida no botão."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Escolha um botão do teclado"</string>
+    <string name="preview" msgid="9077832302472282938">"Visualização"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings_car.xml b/packages/SystemUI/res/values-pt/strings_car.xml
index 072f614..5d754ef 100644
--- a/packages/SystemUI/res/values-pt/strings_car.xml
+++ b/packages/SystemUI/res/values-pt/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Dirija com segurança"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se atento às condições de direção e sempre obedeça às leis aplicáveis. As instruções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver o cruzamento de áreas administrativas. As informações comerciais também podem ser imprecisas ou incompletas. Os dados não são exibidos em tempo real, e a precisão da localização não pode ser garantida. Enquanto dirige, não manuseie seu dispositivo móvel nem use apps que não tenham sido criados para o Android Auto."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se atento às condições da estrada  e sempre obedeça às leis aplicáveis. As instruções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver o cruzamento de áreas administrativas. As informações comerciais também podem ser imprecisas ou incompletas. Os dados não são exibidos em tempo real, e a precisão da localização não pode ser garantida. Enquanto dirige, não manuseie seu dispositivo móvel nem use apps que não tenham sido criados para o Android Auto."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
deleted file mode 100644
index 131507c..0000000
--- a/packages/SystemUI/res/values-pt/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Fechar PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Tela cheia"</string>
-    <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Cancelar"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Mantenha \"PÁGINA INICIAL\" pressionado para controlar o PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index e045fc8..78b9f1f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -147,6 +147,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Niciun card SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Datele mobile sunt dezactivate"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Conectarea ca modem prin Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mod Avion."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Niciun card SIM."</string>
@@ -301,8 +302,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixare pe ecran"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nu a putut porni."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mai mult"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Încă <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Istoric"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Ștergeți"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divizare pe orizontală"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divizare pe verticală"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divizare personalizată"</string>
@@ -468,6 +469,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Culori normale"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Culori de noapte"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Culori personalizate"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automat"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Culori necunoscute"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modificarea culorilor"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Afișați caseta cu Setările rapide"</string>
@@ -494,10 +496,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Căștile sunt conectate"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Setul căști-microfon este conectat"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activați sau dezactivați afișarea pictogramelor în bara de stare."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Economizor de date"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Economizorul de date este activat"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Economizorul de date este dezactivat"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Activați"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Bară de navigare"</string>
+    <string name="start" msgid="6873794757232879664">"La început"</string>
+    <string name="center" msgid="4327473927066010960">"În centru"</string>
+    <string name="end" msgid="125797972524818282">"La final"</string>
+    <string name="space" msgid="804232271282109749">"Buton de spațiu"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Comutator meniu/tastatură"</string>
+    <string name="select_button" msgid="1597989540662710653">"Selectați butonul de adăugat"</string>
+    <string name="add_button" msgid="4134946063432258161">"Adăugați un buton"</string>
+    <string name="save" msgid="2311877285724540644">"Salvați"</string>
+    <string name="reset" msgid="2448168080964209908">"Resetaţi"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Nu s-a găsit niciun buton Ecran de pornire"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Pentru a naviga pe acest dispozitiv este necesar un buton Ecran de pornire. Adăugați un buton Ecran de pornire înainte să salvați."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Ajustați lățimea butonului"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Clipboard"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Folosind butonul Clipboard puteți să trageți elemente direct în clipboard. De asemenea, elementele pot fi trase direct din clipboard atunci când există."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Buton personalizat pentru navigare"</string>
+    <string name="keycode" msgid="7335281375728356499">"Cod de tastă"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Folosind butoanele cu coduri de taste puteți să adăugați taste de la tastatură în Bara de navigare. Când le apăsați, acestea simulează tasta selectată de la tastatură. Mai întâi, trebuie să selectați o tastă pentru un buton, apoi o imagine care să apară pe buton."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Selectați butonul de la tastatură"</string>
+    <string name="preview" msgid="9077832302472282938">"Previzualizare"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
deleted file mode 100644
index b3cd663..0000000
--- a/packages/SystemUI/res/values-ro/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Închideți PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Ecran complet"</string>
-    <string name="pip_play" msgid="674145557658227044">"Redați"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Întrerupeți"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Anulați"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Pentru a controla PIP, atingeți lung ECRAN DE PORNIRE"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d9f7a9b..abecde7 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -148,6 +148,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM-карта отсутствует."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Передача мобильных данных отключена"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-модем"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Режим полета."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Нет SIM-карты."</string>
@@ -302,8 +303,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Заблокировать в приложении"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Не удалось запустить приложение \"<xliff:g id="APP">%s</xliff:g>\""</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Ещё"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Ещё <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Журнал"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Очистить"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Разделить по горизонтали"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Разделить по вертикали"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Разделить по-другому"</string>
@@ -469,6 +470,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Обычные цвета"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Ночные цвета"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Собственные цвета"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Авто"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Неизвестные цвета"</string>
     <string name="color_transform" msgid="6985460408079086090">"Цветовые настройки"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Показывать панель быстрых настроек"</string>
@@ -495,10 +497,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Наушники подключены"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Гарнитура подключена"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Включение и отключение показа значков в строке состояния"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Экономия трафика"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Режим экономии трафика включен"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Режим экономии трафика отключен"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Включено"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Панель навигации"</string>
+    <string name="start" msgid="6873794757232879664">"Вверху"</string>
+    <string name="center" msgid="4327473927066010960">"В центре"</string>
+    <string name="end" msgid="125797972524818282">"Внизу"</string>
+    <string name="space" msgid="804232271282109749">"Пробел"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Меню/переключение раскладки"</string>
+    <string name="select_button" msgid="1597989540662710653">"Выберите кнопку"</string>
+    <string name="add_button" msgid="4134946063432258161">"Добавить кнопку"</string>
+    <string name="save" msgid="2311877285724540644">"Сохранить"</string>
+    <string name="reset" msgid="2448168080964209908">"Сбросить"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Ошибка"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Прежде чем сохранить настройки, добавьте кнопку перехода на главный экран."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Выбор ширины кнопки"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Буфер обмена"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"С помощью этой кнопки можно копировать файлы в буфер обмена и извлекать их из него."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Персонализированная кнопка навигации"</string>
+    <string name="keycode" msgid="7335281375728356499">"Код клавиши"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"С помощью этой кнопки можно добавлять клавиши с клавиатуры на панель навигации. Необходимо выбрать клавишу и изображение для соответствующей кнопки."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Выберите клавишу"</string>
+    <string name="preview" msgid="9077832302472282938">"Просмотр"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
deleted file mode 100644
index 35ecb1c..0000000
--- a/packages/SystemUI/res/values-ru/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Выйти из режима \"Кадр в кадре\""</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Во весь экран"</string>
-    <string name="pip_play" msgid="674145557658227044">"Воспроизвести"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Приостановить"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Отмена"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Управляйте режимом \"Кадр в кадре\", удерживая кнопку ГЛАВНАЯ"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 69514d4..919e67a 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM නැත."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"සෙලියුලර් දත්ත ක්‍රියාවිරහිතයි"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"බ්ලූටූත් ටෙදරින්."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"අහස්යානා ආකාරය."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM කාඩ්පත නැත."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"තිර ඇමිණීම"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"සෙවීම"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කළ නොහැක."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"තවත්"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"තව <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ඉතිහාසය"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"හිස් කරන්න"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"තිරස්ව වෙන් කරන්න"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"සිරස්ව වෙන් කරන්න"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"අභිමත ලෙස වෙන් කරන්න"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"සාමාන්‍ය වර්ණ"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"රාත්‍රී වර්ණ"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"අභිරුචි වර්ණ"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"ස්වයංක්‍රිය"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"නොදන්නා වර්ණ"</string>
     <string name="color_transform" msgid="6985460408079086090">"වර්ණ වෙනස් කිරීම"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"ඉක්මන් සැකසීම් ටයිලය පෙන්වන්න"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"හෙඩ්ෆෝන් සම්බන්ධ කළ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"හෙඩ්සෙට් සම්බන්ධ කළ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"තත්ත්ව තීරුව මත අයිකන පෙන්වීම සබල හෝ අබල කරන්න."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"දත්ත සුරැකුම"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"දත්ත සුරැකුම ක්‍රියාත්මකයි"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"දත්ත සුරැකුම ක්‍රියාවිරහිතයි"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"ක්‍රියාත්මකයි"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"සංචලන තීරුව"</string>
+    <string name="start" msgid="6873794757232879664">"ආරම්භ කරන්න"</string>
+    <string name="center" msgid="4327473927066010960">"මධ්‍ය"</string>
+    <string name="end" msgid="125797972524818282">"අවසානයි"</string>
+    <string name="space" msgid="804232271282109749">"ඉඩ"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"මෙනු / යතුරු පුවරු මාරුව"</string>
+    <string name="select_button" msgid="1597989540662710653">"එක් කිරීමට බොත්තම තෝරන්න"</string>
+    <string name="add_button" msgid="4134946063432258161">"එක් කරන්න බොත්තම"</string>
+    <string name="save" msgid="2311877285724540644">"සුරකින්න"</string>
+    <string name="reset" msgid="2448168080964209908">"යළි පිහිටුවන්න"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"මුල් පිටු බොත්තමක් හමු නොවිණි"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"මෙම උපාංගය සංචලනය කිරීමට හැකි වීමට මුල් පිටු යතුරක් අවශ්‍යයි. කරුණාකර සුරැකීමට පෙර මුල් පිටු යතුරක් එක් කරන්න."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"බොත්තම් පළල සීරුමාරු කරන්න"</string>
+    <string name="clipboard" msgid="1313879395099896312">"පසුරු පුවරුව"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"අයිතම කෙලින්ම පසුරු පුවරුවට ඇද ගෙන ඒමට පසුරු පුවරුව ඉඩ දෙයි. අයිතම පසුරු පුවරුවෙහි ඇති විට කෙලින්ම ඉවතට ඇද ගෙන යාමටද හැකිය."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"අභිරුචි සංචලන බොත්තම"</string>
+    <string name="keycode" msgid="7335281375728356499">"යතුරු කේතය"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"යතුරු කේත බොත්තම් යතුරු පුවරු යතුරු සංචලන තීරුවට එක් කිරීමට ඉඩ දෙයි. එබූ විට ඒවා තෝරන ලද යතුරු පුවරු යතුර ලබා දෙයි. පළමුව යතුර, ඊට පසු බොත්තම මත පෙන්වන රූපයක් සමගින් බොත්තම සඳහා තේරිය යුතුය."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"යතුරු පුවරු බොත්තම තෝරන්න"</string>
+    <string name="preview" msgid="9077832302472282938">"පෙරදසුන"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings_tv.xml b/packages/SystemUI/res/values-si-rLK/strings_tv.xml
deleted file mode 100644
index b3beef3..0000000
--- a/packages/SystemUI/res/values-si-rLK/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP වසන්න"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"සම්පූර්ණ තිරය"</string>
-    <string name="pip_play" msgid="674145557658227044">"ධාවනය කරන්න"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"විරාමය"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"අවලංගු කරන්න"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP පාලනය කිරීමට HOME අල්ලාගෙන සිටින්න"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 9ef3d47..27c2cf8 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -148,6 +148,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Žiadna SIM karta."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobilné dáta sú vypnuté"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Pripojenie cez Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim v lietadle."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Žiadna SIM karta."</string>
@@ -302,8 +303,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripnutie k obrazovke"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikáciu <xliff:g id="APP">%s</xliff:g> sa nepodarilo spustiť"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Viac"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Ďalšie (<xliff:g id="NUMBER">%d</xliff:g>)"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"História"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Vymazať"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Rozdeliť vodorovné"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Rozdeliť zvislé"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Rozdeliť vlastné"</string>
@@ -469,6 +470,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normálne farby"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Nočné farby"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Vlastné farby"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatické"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Neznáme farby"</string>
     <string name="color_transform" msgid="6985460408079086090">"Úprava farieb"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Zobraziť dlaždicu Rýchle nastavenia"</string>
@@ -495,10 +497,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slúchadlá pripojené"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Náhlavná súprava pripojená"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Umožňuje aktivovať alebo deaktivovať zobrazenie ikon v stavovom riadku."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Šetrič dát"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Šetrič dát je zapnutý"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Šetrič dát je vypnutý"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Zapnuté"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigačný panel"</string>
+    <string name="start" msgid="6873794757232879664">"Začiatok"</string>
+    <string name="center" msgid="4327473927066010960">"Stred"</string>
+    <string name="end" msgid="125797972524818282">"Koniec"</string>
+    <string name="space" msgid="804232271282109749">"Medzerník"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Prepínač – ponuka/klávesnica"</string>
+    <string name="select_button" msgid="1597989540662710653">"Výber tlačidla, ktoré sa má pridať"</string>
+    <string name="add_button" msgid="4134946063432258161">"Pridať tlačidlo"</string>
+    <string name="save" msgid="2311877285724540644">"Uložiť"</string>
+    <string name="reset" msgid="2448168080964209908">"Obnoviť"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Tlačidlo Plocha sa nenašlo"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Ak chcete používať navigáciu v tomto zariadení, musíte použiť tlačidlo Plocha. Pred uložením pridajte tlačidlo Plocha."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Upraviť šírku tlačidla"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Schránka"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Schránka umožňuje presunúť položky priamo do schránky. Ak ju máte k dispozícii, môžete ich z nej aj priamo vytiahnuť."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Vlastné tlačidlo navigácie"</string>
+    <string name="keycode" msgid="7335281375728356499">"Kód klávesnice"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Tlačidlá kódov klávesnice umožňujú pridanie klávesov na navigačný panel. Po stlačení simulujú funkcie vybraných klávesov. Najprv musíte pre tlačidlo vybrať kláves a následne musí byť na tlačidle obrázok."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Výber tlačidla klávesnice"</string>
+    <string name="preview" msgid="9077832302472282938">"Ukážka"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
deleted file mode 100644
index 24c42d1..0000000
--- a/packages/SystemUI/res/values-sk/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Zavrieť režim PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Celá obrazovka"</string>
-    <string name="pip_play" msgid="674145557658227044">"Prehrať"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pozastaviť"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Zrušiť"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Ak chcete ovládať režim PIP, podržte tlačidlo plochy"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 9fda17b..55899f8 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -148,6 +148,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Ni kartice SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Prenos podatkov v mobilnih omrežjih je izklopljen"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Internet prek Bluetootha."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Način za letalo."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Ni kartice SIM."</string>
@@ -302,8 +303,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripenjanje zaslona"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacije <xliff:g id="APP">%s</xliff:g> ni bilo mogoče zagnati."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Več"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"In še <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Zgodovina"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Izbriši"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Razdeli vodoravno"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Razdeli navpično"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Razdeli po meri"</string>
@@ -469,6 +470,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Običajne barve"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Nočne barve"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Barve po meri"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Samodejno"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Neznane barve"</string>
     <string name="color_transform" msgid="6985460408079086090">"Spreminjanje barv"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Prikaz ploščice s hitrimi nastavitvami"</string>
@@ -495,10 +497,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalke priključene"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Slušalke z mikrofonom priključene"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Omogoči ali onemogoči prikaz ikon v vrstici stanja."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Varčevanje s podatki"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Varčevanje s podatki je vklopljeno"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Varčevanje s podatki je izklopljeno"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Vklopljeno"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Vrstica za krmarjenje"</string>
+    <string name="start" msgid="6873794757232879664">"Začetek"</string>
+    <string name="center" msgid="4327473927066010960">"Sredina"</string>
+    <string name="end" msgid="125797972524818282">"Konec"</string>
+    <string name="space" msgid="804232271282109749">"Preslednica"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Preklopnik menija/tipkovnice"</string>
+    <string name="select_button" msgid="1597989540662710653">"Izbira gumba za dodajanje"</string>
+    <string name="add_button" msgid="4134946063432258161">"Dodaj gumb"</string>
+    <string name="save" msgid="2311877285724540644">"Shrani"</string>
+    <string name="reset" msgid="2448168080964209908">"Ponastavi"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Ni gumba za začetni zaslon"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Če želite krmariti po tej napravi, potrebujete gumb za začetni zaslon. Pred shranjevanjem dodajte gumb za začetni zaslon."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Prilagajanje širine gumba"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Odložišče"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Odložišče omogoča, da elemente povlečete neposredno vanj. Ko je odložišče na voljo, je elemente prav tako mogoče povleči iz njega."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Gumb za krmarjenje po meri"</string>
+    <string name="keycode" msgid="7335281375728356499">"Koda tipke"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Gumbi za kode tipk omogočajo dodajanje tipk tipkovnice v vrstico za krmarjenje. Ko jih pritisnete, posnemajo izbrano tipko tipkovnice. Najprej je treba izbrati tipko za gumb, nato pa sliko, ki bo prikazana na gumbu."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Izbira gumba tipkovnice"</string>
+    <string name="preview" msgid="9077832302472282938">"Predogled"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
deleted file mode 100644
index 28e9d98..0000000
--- a/packages/SystemUI/res/values-sl/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Zapri način PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Celozaslonsko"</string>
-    <string name="pip_play" msgid="674145557658227044">"Predvajanje"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Zaustavitev"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Prekliči"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Pridržite tipko HOME za upravljanje načina PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index a43ac7e..3c913c9 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nuk ka kartë SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Të dhënat celulare joaktive"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Po lidhet me \"bluetooth\"."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"modaliteti i aeroplanit"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Nuk ka kartë SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"gozhdimi i ekranit"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"kërko"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nuk mundi të nisej."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Më shumë"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> të tjera"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historiku"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Pastro"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Ndaje horizontalisht"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ndaj vertikalisht"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ndaj të personalizuarën"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Ngjyrat normale"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Ngjyrat e natës"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Ngjyrat e personalizuara"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatike"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Ngjyra të panjohura"</string>
     <string name="color_transform" msgid="6985460408079086090">"Modifikimi i ngjyrës"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Pllakëza Shfaq cilësimet e shpejta"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Kufjet u lidhën"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Kufjet me mikrofon u lidhën"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Aktivizo ose çaktivizo shfaqjen e ikonave në shiritin e statusit."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Kursyesi i të dhënave"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Kursyesi i të dhënave është aktiv"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Kursyesi i të dhënave është joaktiv"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Aktiv"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Shiriti i navigimit"</string>
+    <string name="start" msgid="6873794757232879664">"Nis"</string>
+    <string name="center" msgid="4327473927066010960">"Qendror"</string>
+    <string name="end" msgid="125797972524818282">"Fundi"</string>
+    <string name="space" msgid="804232271282109749">"Tasti i hapësirës"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Ndërruesi i menysë/tastierës"</string>
+    <string name="select_button" msgid="1597989540662710653">"Zgjidh butonin për ta shtuar"</string>
+    <string name="add_button" msgid="4134946063432258161">"Shto buton"</string>
+    <string name="save" msgid="2311877285724540644">"Ruaj"</string>
+    <string name="reset" msgid="2448168080964209908">"Rivendos"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Nuk u gjet asnjë buton \"Kreu\""</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Kërkohet një buton \"Kreu\" për të naviguar në këtë pajisje. Shto një buton \"Kreu\" përpara se ta ruash."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Rregullo gjerësinë e butonit"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Kujtesa e fragmenteve"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Kujtesa e fragmenteve lejon që artikujt të zvarriten direkt në kujtesën e fragmenteve. Artikujt mund të zvarriten gjithashtu direkt jashtë kujtesës së fragmenteve kur janë të pranishëm."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Butoni i personalizuar i navigimit"</string>
+    <string name="keycode" msgid="7335281375728356499">"Kodi i tasteve"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Butonat e kodit të tasteve lejojnë që të shtohen në shiritin e navigimit tastet e tastierës. Kur shtypen ato shfaqin tastin e zgjedhur të tastierës. Në fillim duhet të zgjidhet tasti për butonin, i ndjekur nga një imazh që do të tregohet në buton."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Zgjidh butonin e tastierës"</string>
+    <string name="preview" msgid="9077832302472282938">"Pamja paraprake"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
deleted file mode 100644
index 31298a4..0000000
--- a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Mbyll PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Ekrani i plotë"</string>
-    <string name="pip_play" msgid="674145557658227044">"Luaj"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pauzë"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Anulo"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Mbaj shtypur HOME për të kontrolluar PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 765df27..1c3113b 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -147,6 +147,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Нема SIM картице."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Подаци за мобилне уређаје су искључени"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth привезивање."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Режим рада у авиону."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Нема SIM картице."</string>
@@ -301,8 +302,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"качење екрана"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Покретање апликације <xliff:g id="APP">%s</xliff:g> није успело."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Још"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Још <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Историја"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Обриши"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Подели хоризонтално"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Подели вертикално"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Прилагођено дељење"</string>
@@ -468,6 +469,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Нормалне боје"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Ноћне боје"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Прилагођене боје"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Аутоматски"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Непознате боје"</string>
     <string name="color_transform" msgid="6985460408079086090">"Измена боја"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Прикажи плочицу Брза подешавања"</string>
@@ -494,10 +496,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Слушалице су повезане"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Наглавне слушалице су повезане"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Омогућите или онемогућите приказивање икона на статусној траци."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Уштеда података"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Уштеда података је укључена"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Уштеда података је искључена"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Укључено"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Трака за навигацију"</string>
+    <string name="start" msgid="6873794757232879664">"Покрени"</string>
+    <string name="center" msgid="4327473927066010960">"Центар"</string>
+    <string name="end" msgid="125797972524818282">"Дно"</string>
+    <string name="space" msgid="804232271282109749">"Ознака за размак"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Мени/Тастатура пребацивач"</string>
+    <string name="select_button" msgid="1597989540662710653">"Изаберите дугме за додавање"</string>
+    <string name="add_button" msgid="4134946063432258161">"Додај дугме"</string>
+    <string name="save" msgid="2311877285724540644">"Сачувај"</string>
+    <string name="reset" msgid="2448168080964209908">"Поново постави"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Нисмо пронашли дугме Почетна"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Дугме Почетна је неопходно за навигацију на овом уређају. Додајте дугме Почетна пре него што сачувате измене."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Прилагоди ширину дугмета"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Привремена меморија"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Привремена меморија омогућава да се ставке превлаче директно у привремену меморију. Постојеће ставке могу да се превлаче и директно из привремене меморије."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Прилагођено дугме за навигацију"</string>
+    <string name="keycode" msgid="7335281375728356499">"Кôд тастера"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Дугмад за кодове тастера омогућава да се на траку за навигацију додају тастери на тастатури. Када притиснете дугме, симулира се изабрани тастер на тастатури. Прво морате да изаберете тастер за дугме, па слику коју ће се приказивати на дугмету."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Изаберите дугме за тастатуру"</string>
+    <string name="preview" msgid="9077832302472282938">"Преглед"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
deleted file mode 100644
index 3c6b59e..0000000
--- a/packages/SystemUI/res/values-sr/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Затвори PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Цео екран"</string>
-    <string name="pip_play" msgid="674145557658227044">"Пусти"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Паузирај"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Откажи"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Задржите тастер за ПОЧЕТНИ ЕКРАН да бисте контролисали PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index c76d1d3..c2a31cc 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Inget SIM-kort."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobildata inaktiverat"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Internetdelning via Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Flygplansläge"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Inget SIM-kort."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fästa skärmen"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Det gick inte att starta appen <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Mer"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> till"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historik"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Rensa"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dela horisontellt"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dela vertikalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dela anpassad"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normala färger"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Nattfärger"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Anpassade färger"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Automatiskt"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Okända färger"</string>
     <string name="color_transform" msgid="6985460408079086090">"Färgändring"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Visa rutan Snabbinställningar"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Hörlurar anslutna"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset anslutet"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Visa eller dölj ikoner i statusfältet."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Databesparing"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Databesparing är aktiverat"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Databesparing är inaktiverat"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"På"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigeringsfält"</string>
+    <string name="start" msgid="6873794757232879664">"Början"</string>
+    <string name="center" msgid="4327473927066010960">"Centrera"</string>
+    <string name="end" msgid="125797972524818282">"Slutet"</string>
+    <string name="space" msgid="804232271282109749">"Mellanslag"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Byt mellan meny/tangentbord"</string>
+    <string name="select_button" msgid="1597989540662710653">"Välj en knapp att lägga till"</string>
+    <string name="add_button" msgid="4134946063432258161">"Lägg till knapp"</string>
+    <string name="save" msgid="2311877285724540644">"Spara"</string>
+    <string name="reset" msgid="2448168080964209908">"Återställ"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Startskärmsknapp hittades inte"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Det behövs en startskärmsknapp för att kunna navigera den här enheten. Lägg till en startskärmsknapp innan du sparar."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Justera knappens bredd"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Urklipp"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Objekt kan dras direkt till urklipp. Objekt kan också dras direkt från urklipp när de visas."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Anpassad navigeringsknapp"</string>
+    <string name="keycode" msgid="7335281375728356499">"Tangentkod"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Med knappar för tangentkod kan tangenter läggas till i navigeringsfältet. När du trycker på dem förvandlas de till den valda tangenten. Först måste du välja en tangent för knappen och därefter en bild som ska visas på knappen."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Välj tangentbordsknapp"</string>
+    <string name="preview" msgid="9077832302472282938">"Förhandsgranskning"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
deleted file mode 100644
index b36c19f..0000000
--- a/packages/SystemUI/res/values-sv/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Stäng PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Helskärm"</string>
-    <string name="pip_play" msgid="674145557658227044">"Spela upp"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pausa"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Avbryt"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Håll ned HOME om du vill styra PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 031e2b1..bc05d79 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Ukingo"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Hakuna SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Data ya simu za mkononi Imezimwa"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Shiriki intaneti kwa Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Hali ya ndege."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Hakuna SIM kadi."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kudumisha programu moja"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Haikuweza kuanzisha <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Zaidi"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Nyingine <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Historia"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Futa"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gawanya Mlalo"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Gawanya Wima"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Maalum Iliyogawanywa"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Rangi za kawaida"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Rangi za usiku"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Rangi maalum"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Otomatiki"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Rangi zisizojulikana"</string>
     <string name="color_transform" msgid="6985460408079086090">"Ubadilishaji wa rangi"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Onyesha kigae cha Mipangilio ya Haraka"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Imeunganisha spika za masikioni"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Imeunganisha vifaa vya sauti"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Washa au uzime aikoni ili zisionekane kwenye sehemu ya arifa"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Kiokoa Data"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Kiokoa Data kimewashwa"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Kiokoa Data kimezimwa"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Imewashwa"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Sehemu ya viungo muhimu"</string>
+    <string name="start" msgid="6873794757232879664">"Anza"</string>
+    <string name="center" msgid="4327473927066010960">"Weka katikati"</string>
+    <string name="end" msgid="125797972524818282">"Mwisho"</string>
+    <string name="space" msgid="804232271282109749">"Kiweka nafasi"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Swichi ya Menyu / Kibodi"</string>
+    <string name="select_button" msgid="1597989540662710653">"Chagua kitufe ili uongeze"</string>
+    <string name="add_button" msgid="4134946063432258161">"Ongeza kitufe"</string>
+    <string name="save" msgid="2311877285724540644">"Hifadhi"</string>
+    <string name="reset" msgid="2448168080964209908">"Weka upya"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Kitufe cha mwanzo hakijapatikana"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Kitufe cha Mwanzo kinahitajika ili uweze kutumia viungo vya kifaa hiki. Tafadhali ongeza kitufe cha mwanzo kabla ya kuhifadhi."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Rekebisha upana wa kitufe"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Ubao klipu"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Kipengele cha Ubao klipu hukuwezesha kuburuta vipengee moja kwa moja hadi kwenye ubao klipu. Unaweza pia kuburuta vipengee moja kwa moja kutoka kwenye ubao klipu kama vipo."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Kitufe maalum cha uelekezaji"</string>
+    <string name="keycode" msgid="7335281375728356499">"Msimbo wa ufunguo"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Vitufe vya msimbo wa ufunguo vinaruhusu vitufe vya kibodi kuongezwa kwenye Sehemu ya viungo muhimu. Vikibonyezwa, vinaiga kitufe kilichochaguliwa cha kibodi. Kwanza, ufunguo lazima uchaguliwe kwa kitufe, kisha picha itakayoonyeshwa kwenye kitufe."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Chagua Kitufe cha Kibodi"</string>
+    <string name="preview" msgid="9077832302472282938">"Onyesho la kuchungulia"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
deleted file mode 100644
index fc0f414..0000000
--- a/packages/SystemUI/res/values-sw/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Funga PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Skrini nzima"</string>
-    <string name="pip_play" msgid="674145557658227044">"Cheza"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Sitisha"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Ghairi"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Shikilia kitufe cha HOME ili udhibiti PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 71f92fd..c0652d8 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -93,4 +93,6 @@
 
     <dimen name="navigation_key_width">128dp</dimen>
     <dimen name="navigation_key_padding">25dp</dimen>
+
+    <dimen name="qs_expand_margin">0dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index b64ef74..914c544 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"வைஃபை"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"சிம் இல்லை."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"செல்லுலார் தரவு முடக்கப்பட்டது"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"புளூடூத் டெதெரிங்."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"விமானப் பயன்முறை."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"சிம் கார்டு இல்லை."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"திரையை பின் செய்தல்"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"தேடு"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ஐத் தொடங்க முடியவில்லை."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"மேலும்"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"மேலும் <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"வரலாறு"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"அழி"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"கிடைமட்டமாகப் பிரி"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"செங்குத்தாகப் பிரி"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"தனிவிருப்பத்தில் பிரி"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"இயல்பான வண்ணங்கள்"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"இரவுநேர வண்ணங்கள்"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"தனிப்பயன் வண்ணங்கள்"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"தானியங்கு"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"அறியப்படாத வண்ணங்கள்"</string>
     <string name="color_transform" msgid="6985460408079086090">"வண்ண மாற்றம்"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"விரைவு அமைப்புகள் டைலைக் காட்டு"</string>
@@ -485,7 +487,7 @@
     <string name="tuner_full_zen_title" msgid="5905081395132280054">"ஒலி உரையாடலில் தொந்தரவு செய்ய வேண்டாம் என்பதைக் காட்டு"</string>
     <string name="tuner_full_zen_summary" msgid="6883568374520596402">"ஒலி உரையாடலில் தொந்தரவு செய்ய வேண்டாம் என்பதன் முழுக் கட்டுப்பாட்டையும் அனுமதி."</string>
     <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ஒலி மற்றும் தொந்தரவு செய்ய வேண்டாம்"</string>
-    <string name="volume_down_silent" msgid="66962568467719591">"ஒலியைக் குறைக்கும் போது தொந்தரவு செய்ய வேண்டாம் என்பதை இயக்கு"</string>
+    <string name="volume_down_silent" msgid="66962568467719591">"ஒலியைக் குறைக்கும்போது தொந்தரவு செய்ய வேண்டாம் என்பதை இயக்கு"</string>
     <string name="volume_up_silent" msgid="7141255269783588286">"ஒலியைக் கூட்டும் போது தொந்தரவு செய்ய வேண்டாம் என்பதை முடக்கு"</string>
     <string name="battery" msgid="7498329822413202973">"பேட்டரி"</string>
     <string name="clock" msgid="7416090374234785905">"கடிகாரம்"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ஹெட்ஃபோன்கள் இணைக்கப்பட்டன"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ஹெட்செட் இணைக்கப்பட்டது"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"நிலைப் பட்டியில் ஐகான்களைக் காட்டுவதை இயக்கும் அல்லது முடக்கும்."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"தரவுச்சேமிப்பான்"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"தரவு சேமிப்பான் இயக்கப்பட்டது"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"தரவு சேமிப்பான் முடக்கப்பட்டது"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"இயக்கு"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"வழிசெலுத்தல் பட்டி"</string>
+    <string name="start" msgid="6873794757232879664">"தொடங்கு"</string>
+    <string name="center" msgid="4327473927066010960">"மையம்"</string>
+    <string name="end" msgid="125797972524818282">"முடிவு"</string>
+    <string name="space" msgid="804232271282109749">"இடைவெளி"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"மெனு / விசைப்பலகை மாற்றி"</string>
+    <string name="select_button" msgid="1597989540662710653">"சேர்க்க, பொத்தானை தேர்வுசெய்க"</string>
+    <string name="add_button" msgid="4134946063432258161">"பொத்தானைச் சேர்"</string>
+    <string name="save" msgid="2311877285724540644">"சேமி"</string>
+    <string name="reset" msgid="2448168080964209908">"மீட்டமை"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"முகப்புப் பொத்தான் இல்லை"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"இந்தச் சாதனத்தில் வழிசெலுத்த, முகப்புப் பொத்தான் தேவை. சேமிக்கும் முன், முகப்புப் பொத்தானைச் சேர்க்கவும்."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"பொத்தானின் அகலத்தை மாற்று"</string>
+    <string name="clipboard" msgid="1313879395099896312">"கிளிப்போர்டு"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"கிளிப்ஃபோர்டில் உருப்படிகளை இழுத்து விடுவதற்கு கிளிப்போர்டு அனுமதிக்கும். கிளிப்போர்டிலிருந்து உருப்படிகளை வெளியேயும் இழுத்து விடலாம்."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"தனிப்பயன் வழிசெலுத்தல் பொத்தான்"</string>
+    <string name="keycode" msgid="7335281375728356499">"விசைக்குறியீடு"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"விசைக்குறியீட்டுப் பொத்தான்கள் மூலம் விசைப்பலகை விசைகளை வழிசெலுத்தல் பட்டியில் சேர்க்கலாம். அழுத்தும் போது, தேர்ந்தெடுத்த விசைப்பலகை விசையானது செயல்படும். பொத்தானுக்கான விசையை முதலில் தேர்ந்தெடுக்க வேண்டும், பிறகு பொத்தானில் காட்ட வேண்டிய படத்தைத் தேர்வுசெய்யவும்."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"விசைப்பலகைப் பொத்தானைத் தேர்ந்தெடுக்கவும்"</string>
+    <string name="preview" msgid="9077832302472282938">"மாதிரிக்காட்சி"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings_car.xml b/packages/SystemUI/res/values-ta-rIN/strings_car.xml
index b40ba76..7ddd5e0 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings_car.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings_car.xml
@@ -19,6 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"பாதுகாப்பாக ஓட்டவும்"</string>
+    <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"பாதுகாப்பாக வண்டியோட்டவும்"</string>
     <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"வாகனம் ஓட்டுவதற்கான சூழ்நிலைகளை முழுவதுமாகத் தெரிந்து வைத்திருக்கவும் மற்றும் பொருந்தும் விதிகளை எப்போதும் பின்பற்றவும். வழிகள் துல்லியமற்றதாக, முழுமையற்றதாக, ஆபத்துக்குரியதாக, பொருத்தமில்லாததாக, தடைசெய்யப்பட்டதாக அல்லது அரசின் கட்டுப்பாட்டில் உள்ள எல்லைகளைக் கடப்பதாக இருக்கலாம். வணிகத் தகவலும் துல்லியமற்றதாக அல்லது முழுமையற்றதாக இருக்கலாம். தரவு நிகழ்நேர அடிப்படையிலானது அல்ல மற்றும் இருப்பிடத் துல்லியத்திற்கு உத்தரவாதம் வழங்க முடியாது. வாகனம் ஓட்டும் போது மொபைல் சாதனத்தையோ அல்லது Android Auto மூலம் கட்டுப்படுத்த முடியாத பயன்பாடுகளையோ பயன்படுத்த வேண்டாம்."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
deleted file mode 100644
index 3f15396..0000000
--- a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIPஐ மூடு"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"முழுத்திரை"</string>
-    <string name="pip_play" msgid="674145557658227044">"இயக்கு"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"இடைநிறுத்து"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"ரத்துசெய்"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIPஐக் கட்டுப்படுத்த, முகப்பைப் பிடித்திருக்கவும்"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 1e953d8..cb408b9 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"ఎడ్జ్"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"సిమ్ లేదు."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"సెల్యులార్ డేటా ఆఫ్‌లో ఉంది"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"బ్లూటూత్ టెథెరింగ్."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"ఎయిర్‌ప్లేన్ మోడ్."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM కార్డ్ లేదు."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"స్క్రీన్ పిన్నింగ్"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"శోధించు"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"మరింత"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"మరో <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"చరిత్ర"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"తీసివేయి"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"సమతలంగా విభజించు"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"లంబంగా విభజించు"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"అనుకూలంగా విభజించు"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"సాధారణ రంగులు"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"రాత్రి రంగులు"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"అనుకూల రంగులు"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"స్వయంచాలకం"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"తెలియని రంగులు"</string>
     <string name="color_transform" msgid="6985460408079086090">"రంగు సవరణ"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"శీఘ్ర సెట్టింగ్‌ల టైల్‌ను చూపండి"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"హెడ్‌ఫోన్‌లు కనెక్ట్ చేయబడ్డాయి"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"హెడ్‌సెట్ కనెక్ట్ చేయబడింది"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"స్థితి పట్టీలో చిహ్నాలు ప్రదర్శించడాన్ని ప్రారంభించండి లేదా నిలిపివేయండి."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"డేటా సేవర్"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"డేటా సేవర్ ఆన్‌లో ఉంది"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"డేటా సేవర్ ఆఫ్‌లో ఉంది"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"ఆన్"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"నావిగేషన్ బార్"</string>
+    <string name="start" msgid="6873794757232879664">"ప్రారంభం"</string>
+    <string name="center" msgid="4327473927066010960">"మధ్య"</string>
+    <string name="end" msgid="125797972524818282">"ముగించు"</string>
+    <string name="space" msgid="804232271282109749">"స్పేసర్"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"మెను / కీబోర్డ్ స్విచర్"</string>
+    <string name="select_button" msgid="1597989540662710653">"జోడించడానికి బటన్‌ను ఎంచుకోండి"</string>
+    <string name="add_button" msgid="4134946063432258161">"బటన్‌ను జోడించు"</string>
+    <string name="save" msgid="2311877285724540644">"సేవ్ చేయి"</string>
+    <string name="reset" msgid="2448168080964209908">"రీసెట్ చేయి"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"హోమ్ బటన్ ఏదీ కనుగొనబడలేదు"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ఈ పరికరాన్ని నావిగేట్ చేయడానికి హోమ్ బటన్ అవసరం. దయచేసి సేవ్ చేయడానికి ముందు హోమ్ బటన్‌ను జోడించండి."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"బటన్ వెడల్పును సర్దుబాటు చేయండి"</string>
+    <string name="clipboard" msgid="1313879395099896312">"క్లిప్‌బోర్డ్"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"క్లిప్‌బోర్డ్ అంశాలను నేరుగా క్లిప్‌బోర్డ్‌కి లాగడానికి అనుమతిస్తుంది. అలాగే క్లిప్‌బోర్డ్‌లో అంశాలు ఉన్నప్పుడు వాటిని నేరుగా క్లిప్‌బోర్డ్ నుండి బయటకు లాగవచ్చు."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"అనుకూల నావిగేషన్ బటన్"</string>
+    <string name="keycode" msgid="7335281375728356499">"కీకోడ్"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"కీకోడ్ బటన్‌లు నావిగేషన్ బార్‌లో కీబోర్డ్ కీలను జోడించడానికి అనుమతిస్తాయి. నొక్కినప్పుడు అవి ఎంచుకోబడిన కీబోర్డ్ కీ చర్యను పునరుత్పాదిస్తాయి. ముందుగా బటన్ కోసం తప్పనిసరిగా కీని ఎంచుకోవాలి, తర్వాత బటన్‌పై చూపాల్సిన చిత్రాన్ని ఎంచుకోవాలి."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"కీబోర్డ్ బటన్‌ను ఎంచుకోండి"</string>
+    <string name="preview" msgid="9077832302472282938">"పరిదృశ్యం"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings_tv.xml b/packages/SystemUI/res/values-te-rIN/strings_tv.xml
deleted file mode 100644
index a3148ddf..0000000
--- a/packages/SystemUI/res/values-te-rIN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIPని మూసివేయి"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"పూర్తి స్క్రీన్"</string>
-    <string name="pip_play" msgid="674145557658227044">"ప్లే చేయి"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"పాజ్ చేయి"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"రద్దు చేయి"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIPని నియంత్రించడానికి HOMEని నొక్కి ఉంచండి"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index c09b50f..9201b29 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WiFi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"ไม่มีซิมการ์ด"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"ปิดข้อมูลเครือข่ายมือถือแล้ว"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"การปล่อยสัญญาณบลูทูธ"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"โหมดใช้งานบนเครื่องบิน"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"ไม่มีซิมการ์ด"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"การตรึงหน้าจอ"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"ไม่สามารถเริ่มใช้ <xliff:g id="APP">%s</xliff:g>"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"เพิ่มเติม"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"อีก <xliff:g id="NUMBER">%d</xliff:g> งาน"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"ประวัติ"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ล้าง"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"แยกในแนวนอน"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"แยกในแนวตั้ง"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"แยกแบบกำหนดเอง"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"สีปกติ"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"สียามค่ำคืน"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"สีที่กำหนดเอง"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"อัตโนมัติ"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"สีที่ไม่รู้จัก"</string>
     <string name="color_transform" msgid="6985460408079086090">"การปรับเปลี่ยนสี"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"แสดงไทล์การตั้งค่าด่วน"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"เชื่อมต่อหูฟังแล้ว"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"เชื่อมต่อชุดหูฟังแล้ว"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"เปิดหรือปิดไอคอนจากการแสดงในแถบสถานะ"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"โปรแกรมประหยัดอินเทอร์เน็ต"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"โปรแกรมประหยัดอินเทอร์เน็ตเปิดอยู่"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"โปรแกรมประหยัดอินเทอร์เน็ตปิดอยู่"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"เปิด"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"แถบนำทาง"</string>
+    <string name="start" msgid="6873794757232879664">"บนสุด"</string>
+    <string name="center" msgid="4327473927066010960">"กึ่งกลาง"</string>
+    <string name="end" msgid="125797972524818282">"ล่างสุด"</string>
+    <string name="space" msgid="804232271282109749">"Spacer"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"ปุ่มสลับเมนู/แป้นพิมพ์"</string>
+    <string name="select_button" msgid="1597989540662710653">"เลือกปุ่มที่จะเพิ่ม"</string>
+    <string name="add_button" msgid="4134946063432258161">"เพิ่มปุ่ม"</string>
+    <string name="save" msgid="2311877285724540644">"บันทึก"</string>
+    <string name="reset" msgid="2448168080964209908">"รีเซ็ต"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"ไม่พบปุ่มหน้าแรก"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"ต้องใช้ปุ่มหน้าแรกเพื่อให้สามารถไปยังส่วนต่างๆ ในอุปกรณ์นี้ โปรดเพิ่มปุ่มหน้าแรกก่อนที่จะบันทึก"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"ปรับความกว้างของปุ่ม"</string>
+    <string name="clipboard" msgid="1313879395099896312">"คลิปบอร์ด"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"คลิปบอร์ดช่วยให้สามารถลากรายการไปยังคลิปบอร์ดได้โดยตรง นอกจากนี้ คุณยังสามารถลากรายการออกจากคลิปบอร์ดได้โดยตรงหากมีรายการอยู่ในคลิปบอร์ด"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"ปุ่มนำทางที่กำหนดเอง"</string>
+    <string name="keycode" msgid="7335281375728356499">"Keycode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"ปุ่ม Keycode ช่วยให้สามารถเพิ่มแป้นของแป้นพิมพ์ไปยังแถบนำทาง เมื่อกดปุ่มนี้ ปุ่มจะเลียนแบบการทำงานของแป้นพิมพ์ที่เลือก โดยจะต้องเลือกแป้นให้กับปุ่มก่อน จากนั้นเลือกรูปภาพที่จะแสดงบนปุ่ม"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"เลือกปุ่มแป้นพิมพ์"</string>
+    <string name="preview" msgid="9077832302472282938">"ดูตัวอย่าง"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
deleted file mode 100644
index 5921a18..0000000
--- a/packages/SystemUI/res/values-th/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"ปิด PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"เต็มหน้าจอ"</string>
-    <string name="pip_play" msgid="674145557658227044">"เล่น"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"หยุดชั่วคราว"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"ยกเลิก"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"กดค้างที่ HOME เพื่อควบคุม PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e76b40c..00aab01 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Walang SIM."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Naka-off ang Cellular Data"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Pag-tether ng Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode na eroplano."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Walang SIM card."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pagpi-pin sa screen"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Hindi masimulan <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Higit pa"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> Pa"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"History"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"I-clear"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Custom"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Mga karaniwang kulay"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Madidilim na kulay"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Mga custom na kulay"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Auto"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Mga hindi kilalang kulay"</string>
     <string name="color_transform" msgid="6985460408079086090">"Pagbago sa kulay"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Ipakita ang tile ng Mga Mabilisang Setting"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Nakakonekta ang mga headphone"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Nakakonekta ang headset"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"I-enable o i-disable ang pagpapakita sa mga icon sa status bar."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Naka-on ang Data Saver"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Naka-off ang Data Saver"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"I-on"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigation bar"</string>
+    <string name="start" msgid="6873794757232879664">"Simula"</string>
+    <string name="center" msgid="4327473927066010960">"Gitna"</string>
+    <string name="end" msgid="125797972524818282">"Dulo"</string>
+    <string name="space" msgid="804232271282109749">"Spacer"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menu / Keyboard Switcher"</string>
+    <string name="select_button" msgid="1597989540662710653">"Pumili ng button na idaragdag"</string>
+    <string name="add_button" msgid="4134946063432258161">"Magdagdag ng button"</string>
+    <string name="save" msgid="2311877285724540644">"I-save"</string>
+    <string name="reset" msgid="2448168080964209908">"I-reset"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Walang nakitang home button"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Kailangan ng home button upang ma-navigate ang device na ito. Mangyaring magdagdag ng home button bago mag-save."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Isaayos ang lapad ng button"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Clipboard"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Nagbibigay-daan ang Clipboard na direktang ma-drag sa clipboard ang mga item. Maaari ding direktang i-drag ang mga item palabas sa clipboard."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Custom na button ng navigation"</string>
+    <string name="keycode" msgid="7335281375728356499">"Keycode"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Nagbibigay-daan ang mga button na Keycode na maidagdag ang mga keyboard key sa Navigation Bar. Kapag pinindot, ginagaya ng mga ito ang napiling keyboard key. Una, dapat munang piliin ang key para sa button, kasunod ng larawan na ipapakita sa button."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Pumili ng Button na Keyboard"</string>
+    <string name="preview" msgid="9077832302472282938">"I-preview"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
deleted file mode 100644
index 7940251..0000000
--- a/packages/SystemUI/res/values-tl/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Isara ang PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
-    <string name="pip_play" msgid="674145557658227044">"I-play"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"I-pause"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Kanselahin"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Pindutin nang matagal ang HOME upang kontrolin ang PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index a16adfd..4ee97a7 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Kablosuz"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM kart yok."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Hücresel Veri Kapalı"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth tethering"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Uçak modu."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM kart yok."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekran sabitleme"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlatılamadı."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Diğer"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> Tane Daha"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Geçmiş"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Sil"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Yatay Ayırma"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dikey Ayırma"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Özel Ayırma"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Normal renkler"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Gece renkleri"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Özel renkler"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Otomatik"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Bilinmeyen renkler"</string>
     <string name="color_transform" msgid="6985460408079086090">"Renk değişikliği"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Hızlı Ayarlar kutusunu göster"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Mikrofonlu kulaklık bağlı"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Mikrofonlu kulaklık bağlı"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Simgelerin durum çubuğunda görüntülenmesini etkinleştir veya devre dışı bırak"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Veri Tasarrufu"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Veri Tasarrufu açık"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Veri Tasarrufu kapalı"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Açık"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Gezinme çubuğu"</string>
+    <string name="start" msgid="6873794757232879664">"Başlangıç"</string>
+    <string name="center" msgid="4327473927066010960">"Merkez"</string>
+    <string name="end" msgid="125797972524818282">"Son"</string>
+    <string name="space" msgid="804232271282109749">"Ayırıcı"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menü / Klavye Değiştirici"</string>
+    <string name="select_button" msgid="1597989540662710653">"Eklenecek düğmeyi seçin"</string>
+    <string name="add_button" msgid="4134946063432258161">"Düğme ekle"</string>
+    <string name="save" msgid="2311877285724540644">"Kaydet"</string>
+    <string name="reset" msgid="2448168080964209908">"Sıfırla"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Ana ekran düğmesi bulunamadı"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Ana ekran düğmesi bu cihazda gezinebilmek için gereklidir. Kaydetmeden önce lütfen bir ana ekran düğmesi ekleyin."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Düğme genişliğini düzenle"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Pano"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Pano, öğelerin doğrudan panoya sürüklenmesine olanak sağlar. Panoda bulunan öğeler ayrıca doğrudan panodan dışarı sürüklenebilir."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Özel gezinme düğmesi"</string>
+    <string name="keycode" msgid="7335281375728356499">"Tuş kodu"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Tuş kodu düğmeleri klavye tuşlarının Gezinme Çubuğu\'na eklenmesini sağlar. Tuşa basıldığında, seçili klavye tuşu taklit edilir. İlgili düğme için ilk olarak tuş, ardından düğmede görüntülenecek resim seçilmelidir."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Klavye Düğmesini Seçin"</string>
+    <string name="preview" msgid="9077832302472282938">"Önizle"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
deleted file mode 100644
index 69ed9c8..0000000
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP\'yi kapat"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Tam ekran"</string>
-    <string name="pip_play" msgid="674145557658227044">"Oynat"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Duraklat"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"İptal"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP\'yi kontrol etmek için ANA EKRAN düğmesini basılı tutun"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 1c0e04e..ca6e39e 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -148,6 +148,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Немає SIM-карти."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Мобільний трафік вимкнено"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Прив’язка Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Режим польоту."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Немає SIM-карти."</string>
@@ -302,8 +303,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"закріпити екран"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Не вдалося запустити <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Більше"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"Ще <xliff:g id="NUMBER">%d</xliff:g>"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Історія"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Очистити"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Розділити горизонтально"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Розділити вертикально"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Розділити (власний варіант)"</string>
@@ -469,6 +470,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Стандартні кольори"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Нічні кольори"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Користувацькі кольори"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Авто"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Невідомі кольори"</string>
     <string name="color_transform" msgid="6985460408079086090">"Змінення кольорів"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Показати опцію швидких налаштувань"</string>
@@ -495,10 +497,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Навушники під’єднано"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Гарнітуру під’єднано"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Показати або сховати значки в рядку стану."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Заощадження трафіку"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Заощадження трафіку ввімкнено"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Заощадження трафіку вимкнено"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Увімкнено"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Панель навігації"</string>
+    <string name="start" msgid="6873794757232879664">"На початку"</string>
+    <string name="center" msgid="4327473927066010960">"У центрі"</string>
+    <string name="end" msgid="125797972524818282">"У кінці"</string>
+    <string name="space" msgid="804232271282109749">"Розділювач"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Вибір меню або клавіатури"</string>
+    <string name="select_button" msgid="1597989540662710653">"Виберіть, яку кнопку додати"</string>
+    <string name="add_button" msgid="4134946063432258161">"Додати кнопку"</string>
+    <string name="save" msgid="2311877285724540644">"Зберегти"</string>
+    <string name="reset" msgid="2448168080964209908">"Віднов."</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Немає кнопки \"Головний екран\""</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Для навігації пристроєм потрібна кнопка \"Головний екран\". Перш ніж зберегти, додайте цю кнопку."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Змінити ширину кнопки"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Буфер обміну"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"За допомогою кнопки \"Буфер обміну\" можна перетягувати елементи просто в буфер або з нього."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Спеціальна кнопка навігації"</string>
+    <string name="keycode" msgid="7335281375728356499">"Код клавіші"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"За допомогою кнопок кодів клавіш можна додавати клавіші клавіатури на панель навігації. Якщо натиснути кнопку, вона імітує вибрану клавішу клавіатури. Потрібно вибрати клавішу та зображення для кнопки."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Вибрати кнопку клавіатури"</string>
+    <string name="preview" msgid="9077832302472282938">"Переглянути"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
deleted file mode 100644
index d36c5bc..0000000
--- a/packages/SystemUI/res/values-uk/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Закрити PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"На весь екран"</string>
-    <string name="pip_play" msgid="674145557658227044">"Відтворити"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Призупинити"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Скасувати"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Щоб керувати PIP, утримуйте кнопку \"ГОЛОВНИЙ ЕКРАН\""</string>
-</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 67b52fd..415a38f 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"‏کوئی SIM نہیں ہے۔"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"سیلولر ڈیٹا آف ہے"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"بلوٹوتھ مربوط کرنا۔"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"ہوائی جہاز وضع۔"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"‏کوئی SIM کارڈ نہیں ہے۔"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"اسکرین کو پن کرنا"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"تلاش کریں"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> کو شروع نہیں کیا جا سکا۔"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"مزید"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> مزید"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"سرگزشت"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"صاف کریں"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"بلحاظ افقی الگ کریں"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"بلحاظ عمودی الگ کریں"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"بلحاظ حسب ضرورت الگ کریں"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"عام رنگ"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"رات کے رنگ"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"حسب ضرورت رنگ"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"خودکار"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"نامعلوم رنگ"</string>
     <string name="color_transform" msgid="6985460408079086090">"رنگوں کی تبدیلی"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"فوری ترتیبات والی ٹائل دکھائیں"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ہیڈ فونز منسلک ہیں"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ہیڈ سیٹ منسلک ہے"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"اسٹیٹس بار میں دکھائے جانے کیلئے آئیکنز فعال یا غیر فعال کریں۔"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"ڈیٹا سیور"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ڈیٹا سیور آن ہے"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ڈیٹا سیور آف ہے"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"آن"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"نیویگیشن بار"</string>
+    <string name="start" msgid="6873794757232879664">"شروع کریں"</string>
+    <string name="center" msgid="4327473927066010960">"مرکز"</string>
+    <string name="end" msgid="125797972524818282">"اختتام"</string>
+    <string name="space" msgid="804232271282109749">"سپیسر"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"مینو/ کی بورڈ سوئچر"</string>
+    <string name="select_button" msgid="1597989540662710653">"شامل کرنے کیلئے بٹن منتخب کریں"</string>
+    <string name="add_button" msgid="4134946063432258161">"بٹن شامل کریں"</string>
+    <string name="save" msgid="2311877285724540644">"محفوظ کریں"</string>
+    <string name="reset" msgid="2448168080964209908">"دوبارہ ترتیب دیں"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"کوئی ہوم بٹن نہیں ملا"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"اس آلہ کو نیویگیٹ کرنے کیلئے ایک ہوم بٹن درکار ہے۔ براہ کرم محفوظ کرنے سے پہلے ایک ہوم بٹن شامل کریں۔"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"بٹن کی چوڑائی ایڈجسٹ کریں"</string>
+    <string name="clipboard" msgid="1313879395099896312">"کلپ بورڈ"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"کلب بورڈ آئٹمز کو براہ راست کلپ بورڈ پر گھسیٹنے کی اجازت دیتا ہے۔ کلپ بورڈ پر آئٹمز موجود ہونے کی صورت میں انہیں بھی براہ راست باہر گھسیٹا جا سکتا ہے۔"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"حسب ضرورت نیویگیشن بٹن"</string>
+    <string name="keycode" msgid="7335281375728356499">"کی کوڈ"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"کی کوڈ بٹنز نیویگیشن بار میں کی بورڈ کلیدوں کو شامل ہونے کی اجازت دیتے ہیں۔ دبائے جانے پر یہ منتخب کردہ کی بورڈ کلید کی نقل کرتے ہیں۔ بٹن کیلئے پہلے کلید منتخب ہونی چاہیئے، اس کے بعد بٹن پر دکھائے جانے کیلئے ایک تصویر۔"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"کی بورڈ بٹن منتخب کریں"</string>
+    <string name="preview" msgid="9077832302472282938">"پیش منظر"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
deleted file mode 100644
index b7af745..0000000
--- a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"‏PIP بند کریں"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"فُل اسکرین"</string>
-    <string name="pip_play" msgid="674145557658227044">"چلائیں"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"موقوف کریں"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"منسوخ کریں"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"‏pip کو کنٹرول کرنے کیلئے ہوم دبا کے رکھیں"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index dd91bad..4f6251e 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM karta yo‘q."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Mobil internet o‘chiq"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth modem"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Parvoz rejimi"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Hech qanday SIM karta yo‘q."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"o‘zgarmas ekran"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"qidirish"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"“<xliff:g id="APP">%s</xliff:g>” ilovasini ishga tushirib bo‘lmadi."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Ko‘proq"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> ta"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Jurnal"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Tozalash"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gorizontal yo‘nalishda bo‘lish"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikal yo‘nalishda bo‘lish"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Boshqa usulda bo‘lish"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Odatiy ranglar"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Qoramtir ranglar"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Foydalanuvchi rangi"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Avtomatik"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Noma’lum ranglar"</string>
     <string name="color_transform" msgid="6985460408079086090">"Rang sozlamalari"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Tezkor sozlamalar panelini ko‘rsatish"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Quloqchinlar ulandi"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Audio moslama ulandi"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Holat qatorida begilarning ko‘rsatilishini yoqish yoki o‘chirish."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Trafik tejash"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Trafik tejash yoniq"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Trafik tejash o‘chiq"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Yoniq"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Navigatsiya paneli"</string>
+    <string name="start" msgid="6873794757232879664">"Boshlash"</string>
+    <string name="center" msgid="4327473927066010960">"Markazda"</string>
+    <string name="end" msgid="125797972524818282">"Oxiri"</string>
+    <string name="space" msgid="804232271282109749">"Ajratuvchi"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Menyu yoki klaviatura"</string>
+    <string name="select_button" msgid="1597989540662710653">"Qo‘shish uchun tugmani tanlang"</string>
+    <string name="add_button" msgid="4134946063432258161">"Tugma qo‘shish"</string>
+    <string name="save" msgid="2311877285724540644">"Saqlash"</string>
+    <string name="reset" msgid="2448168080964209908">"Tiklash"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"“Bosh ekran” tugmasi topilmadi"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Qurilma bo‘ylab o‘tish uchun “Bosh ekran” tugmasi kerak. Saqlashdan oldin mazkur tugmani qo‘shing."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Tugma enini moslashtiring"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Vaqtinchalik xotira"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"“Vaqtinchalik xotira” tugmasi yordamida elementlarni vaqtinchalik xotiraga olish va undan chiqarish qulay."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Maxsus navigatsiya tugmasi"</string>
+    <string name="keycode" msgid="7335281375728356499">"Tugma kodi"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Tugmalar kodi yordamida klaviatura tugmalarini navigatsiya paneliga qo‘shish mumkin. Ular bosilganda tanlangan klaviatura tugmasining bosilishini taqlid qiladi. Tugmalar kodi uchun klaviatura tugmasi va rasm tanlanishi kerak."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Klaviatura tugmasini tanlang"</string>
+    <string name="preview" msgid="9077832302472282938">"Oldindan ko‘rish"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
deleted file mode 100644
index 7a1b69c..0000000
--- a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"PIP’ni yopish"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"To‘liq ekran"</string>
-    <string name="pip_play" msgid="674145557658227044">"Ijro"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Pauza"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Bekor qilish"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"PIP’ni boshqarish uchun BOSHIGA tugmasini bosing"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index a95e312..f7ab59a 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Cạnh"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Không có SIM nào."</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Dữ liệu di động bị tắt"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Truy cập Internet qua Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Chế độ trên máy bay."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Không có thẻ SIM nào."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"khóa màn hình"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Không thể khởi động <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Thêm"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> tác vụ khác"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Lịch sử"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Xóa"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Phân tách ngang"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Phân tách dọc"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tùy chỉnh phân tách"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Màu thông thường"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Màu tối"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Màu tùy chỉnh"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Tự động"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Màu không xác định"</string>
     <string name="color_transform" msgid="6985460408079086090">"Sửa đổi màu"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Hiển thị ô Cài đặt nhanh"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Đã kết nối tai nghe"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Đã kết nối tai nghe"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Bật hoặc tắt biểu tượng hiển thị trong thanh trạng thái."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Trình tiết kiệm dữ liệu"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Trình tiết kiệm dữ liệu đang bật"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Trình tiết kiệm dữ liệu đang tắt"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Bật"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Thanh điều hướng"</string>
+    <string name="start" msgid="6873794757232879664">"Đầu"</string>
+    <string name="center" msgid="4327473927066010960">"Căn giữa"</string>
+    <string name="end" msgid="125797972524818282">"Cuối"</string>
+    <string name="space" msgid="804232271282109749">"Ký tự cách"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Trình chuyển đổi bàn phím / menu"</string>
+    <string name="select_button" msgid="1597989540662710653">"Chọn nút để thêm"</string>
+    <string name="add_button" msgid="4134946063432258161">"Thêm nút"</string>
+    <string name="save" msgid="2311877285724540644">"Lưu"</string>
+    <string name="reset" msgid="2448168080964209908">"Đặt lại"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Không tìm thấy nút trang chủ"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Cần có nút trang chủ để có thể điều hướng thiết bị này. Vui lòng thêm nút trang chủ trước khi lưu."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Điều chỉnh chiều rộng nút"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Khay nhớ tạm"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Khay nhớ tạm cho phép kéo trực tiếp mục vào khay nhớ tạm. Bạn cũng có thể kéo trực tiếp mục ra khỏi khay nhớ tạm khi hiển thị."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Nút điều hướng tùy chỉnh"</string>
+    <string name="keycode" msgid="7335281375728356499">"Mã phím"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Các nút mã phím cho phép thêm các phím trên bàn phím vào Thanh điều hướng. Khi bạn nhấn, các nút này sẽ mô phỏng phím trên bàn phím được chọn. Trước tiên, bạn phải chọn phím cho nút, sau đó chọn một hình ảnh để hiển thị trên nút."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Chọn nút trên bàn phím"</string>
+    <string name="preview" msgid="9077832302472282938">"Xem trước"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
deleted file mode 100644
index ae5f6da..0000000
--- a/packages/SystemUI/res/values-vi/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Đóng PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Toàn màn hình"</string>
-    <string name="pip_play" msgid="674145557658227044">"Phát"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Tạm dừng"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Hủy"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Giữ HOME để điều khiển PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-w550dp-land/config.xml b/packages/SystemUI/res/values-w550dp-land/config.xml
new file mode 100644
index 0000000..71e54a1
--- /dev/null
+++ b/packages/SystemUI/res/values-w550dp-land/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_columns">4</integer>
+</resources>
diff --git a/wifi/java/android/net/wifi/ScanInfo.aidl b/packages/SystemUI/res/values-w550dp-land/dimens.xml
similarity index 65%
copy from wifi/java/android/net/wifi/ScanInfo.aidl
copy to packages/SystemUI/res/values-w550dp-land/dimens.xml
index 18ae508..4160c83 100644
--- a/wifi/java/android/net/wifi/ScanInfo.aidl
+++ b/packages/SystemUI/res/values-w550dp-land/dimens.xml
@@ -1,5 +1,6 @@
-/**
- * Copyright (c) 2015, The Android Open Source Project
+<?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.
@@ -12,8 +13,11 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- */
+*/
+-->
+<resources>
+    <!-- Standard notification width + gravity -->
+    <dimen name="notification_panel_width">544dp</dimen>
 
-package android.net.wifi;
-
-parcelable ScanInfo;
+    <dimen name="qs_expand_margin">32dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index e276fb5..318997c6 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WLAN"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"无 SIM 卡。"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"移动数据网络已关闭"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"蓝牙网络共享。"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"飞行模式。"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"没有 SIM 卡。"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"固定屏幕"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"无法启动<xliff:g id="APP">%s</xliff:g>。"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"更多"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"还有 <xliff:g id="NUMBER">%d</xliff:g> 项"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"历史记录"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"清除"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自定义分割"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"常规颜色"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"夜间颜色"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"自定义颜色"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"自动"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"未知颜色"</string>
     <string name="color_transform" msgid="6985460408079086090">"颜色修改"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"显示“快捷设置”图块"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已连接到耳机"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已连接到耳机"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"指定在状态栏中显示或隐藏图标。"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"流量节省程序"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"流量节省程序已开启"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"流量节省程序已关闭"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"开启"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"导航栏"</string>
+    <string name="start" msgid="6873794757232879664">"顶部"</string>
+    <string name="center" msgid="4327473927066010960">"中心位置"</string>
+    <string name="end" msgid="125797972524818282">"底部"</string>
+    <string name="space" msgid="804232271282109749">"空格键"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"菜单/键盘切换器"</string>
+    <string name="select_button" msgid="1597989540662710653">"选择要添加的按钮"</string>
+    <string name="add_button" msgid="4134946063432258161">"添加按钮"</string>
+    <string name="save" msgid="2311877285724540644">"保存"</string>
+    <string name="reset" msgid="2448168080964209908">"重置"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"未找到主屏幕按钮"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"要在此设备上导航,您必须使用主屏幕按钮。请先添加主屏幕按钮,然后再保存。"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"调整按钮宽度"</string>
+    <string name="clipboard" msgid="1313879395099896312">"剪贴板"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"您可以利用“剪贴板”按钮将相应内容直接拖动到剪贴板中。剪贴板中有内容时,您也可以将剪贴板中的内容直接拖出来。"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"自定义导航按钮"</string>
+    <string name="keycode" msgid="7335281375728356499">"键码"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"您可以利用“键码”按钮将键盘按键添加到导航栏中。只要按下这些按钮,按钮即可模仿所选键盘按键执行相应的操作。要使用这项功能,您必须先为按钮选择相应的按键,然后再选择要在按钮上显示的图片。"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"选择键盘按钮"</string>
+    <string name="preview" msgid="9077832302472282938">"预览"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
deleted file mode 100644
index 25d3ff0..0000000
--- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"关闭 PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"全屏"</string>
-    <string name="pip_play" msgid="674145557658227044">"播放"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"暂停"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"取消"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"按住主屏幕图标即可控制 PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 86f78e4..9d1f912 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"無 SIM 卡。"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"流動數據已關閉"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"藍牙網絡共享。"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"飛航模式。"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"沒有 SIM 卡。"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"更多"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"還有 <xliff:g id="NUMBER">%d</xliff:g> 項"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"記錄"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"清除"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"一般色系"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"深沉色系"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"自訂顏色"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"自動"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"不明色系"</string>
     <string name="color_transform" msgid="6985460408079086090">"顏色修改"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"顯示「快速設定」圖塊"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已連接至耳機"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已連接至耳機"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"顯示或隱藏狀態列上的圖示。"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"數據節省程式"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"數據節省程式已開啟"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"數據節省程式已關閉"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"開啟"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"導覽列"</string>
+    <string name="start" msgid="6873794757232879664">"畫面頂部"</string>
+    <string name="center" msgid="4327473927066010960">"畫面中央"</string>
+    <string name="end" msgid="125797972524818282">"畫面底部"</string>
+    <string name="space" msgid="804232271282109749">"間隔"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"選單/鍵盤切換工具"</string>
+    <string name="select_button" msgid="1597989540662710653">"選取要新增的按鈕"</string>
+    <string name="add_button" msgid="4134946063432258161">"新增按鈕"</string>
+    <string name="save" msgid="2311877285724540644">"儲存"</string>
+    <string name="reset" msgid="2448168080964209908">"重設"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"找不到主按鈕"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"您必須設定主按鈕才能操作此裝置。請先新增主按鈕,然後再儲存。"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"調整按鈕寬度"</string>
+    <string name="clipboard" msgid="1313879395099896312">"剪貼簿"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"「剪貼簿」讓您直接將項目拖曳至剪貼簿,亦可直接將剪貼簿內現有的項目拖曳出來。"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"自訂導覽按鈕"</string>
+    <string name="keycode" msgid="7335281375728356499">"按鍵碼"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"「按鍵碼」按鈕讓您將鍵盤按鍵新增至導覽列。按下按鈕後,系統便會執行與所選鍵盤按鍵對應的操作。如要使用此功能,請先為按鈕選取按鍵要模擬的鍵盤按鍵,然後指定按鈕的顯示圖像。"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"選取鍵盤按鈕"</string>
+    <string name="preview" msgid="9077832302472282938">"預覽"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
deleted file mode 100644
index 1b46b64..0000000
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"關閉 PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"全螢幕"</string>
-    <string name="pip_play" msgid="674145557658227044">"播放"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"暫停"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"取消"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"按住主按鈕即可控制 PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 00eb788..2fc50de 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"沒有 SIM 卡。"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"行動數據連線已關閉"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"藍牙網路共用"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"飛行模式。"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"沒有 SIM 卡。"</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"更多"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"還有 <xliff:g id="NUMBER">%d</xliff:g> 項"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"紀錄"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"清除"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"水平分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"垂直分割"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"自訂分割"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"一般顏色"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"夜間顏色"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"自訂顏色"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"自動"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"不明顏色"</string>
     <string name="color_transform" msgid="6985460408079086090">"顏色修改"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"顯示快速設定圖塊"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已與耳機連線"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已與耳機連線"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"指定在狀態列中顯示或隱藏圖示。"</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Data Saver"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver 已開啟"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver 已關閉"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"開啟"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"導覽列"</string>
+    <string name="start" msgid="6873794757232879664">"畫面頂端"</string>
+    <string name="center" msgid="4327473927066010960">"畫面中央"</string>
+    <string name="end" msgid="125797972524818282">"畫面底部"</string>
+    <string name="space" msgid="804232271282109749">"空格字元"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"選單/鍵盤切換工具"</string>
+    <string name="select_button" msgid="1597989540662710653">"選取要新增的按鈕"</string>
+    <string name="add_button" msgid="4134946063432258161">"新增按鈕"</string>
+    <string name="save" msgid="2311877285724540644">"儲存"</string>
+    <string name="reset" msgid="2448168080964209908">"重設"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"找不到「主畫面」按鈕"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"您必須設定「主畫面」按鈕才能操作這部裝置。請先新增「主畫面」按鈕再儲存。"</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"調整按鈕寬度"</string>
+    <string name="clipboard" msgid="1313879395099896312">"剪貼簿"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"您可以利用「剪貼簿」按鈕將所需項目直接拖曳到剪貼簿中,或是將剪貼簿中的項目直接拖曳出來。"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"自訂導覽按鈕"</string>
+    <string name="keycode" msgid="7335281375728356499">"按鍵碼"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"您可以利用「按鍵碼」按鈕將鍵盤按鍵加到導覽列。只要按下這些按鈕,即可執行與所選鍵盤按鍵對應的操作。如要使用這項功能,請先為按鈕選取要模擬的鍵盤按鍵,然後指定按鈕的顯示圖示。"</string>
+    <string name="select_keycode" msgid="7413765103381924584">"選取鍵盤按鍵"</string>
+    <string name="preview" msgid="9077832302472282938">"預覽"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
deleted file mode 100644
index 8a085b0..0000000
--- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"關閉子母畫面"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"全螢幕"</string>
-    <string name="pip_play" msgid="674145557658227044">"播放"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"暫停"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"取消"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"按住「主畫面」圖示即可控制子母畫面"</string>
-</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 08dc7cc..76c2696 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -146,6 +146,7 @@
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Ekucupheleni"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"I-Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Ayikho i-SIM"</string>
+    <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Idatha yeselula ivaliwe"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Imodemu nge-Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Imodi yendiza."</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"Alikho ikhadi le-SIM."</string>
@@ -300,8 +301,8 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ukuphina isikrini"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Ayikwazanga ukuqala i-<xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="recents_show_history_button_label" msgid="7062088196449747245">"Okuningi"</string>
-    <string name="recents_history_label_format" msgid="6337155608055062429">"<xliff:g id="NUMBER">%d</xliff:g> Okuningi"</string>
+    <string name="recents_history_button_label" msgid="5153358867807604821">"Umlando"</string>
+    <string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Sula"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Hlukanisa okuvundlile"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Hlukanisa okumile"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Hlukanisa kwezifiso"</string>
@@ -467,6 +468,7 @@
     <string name="color_matrix_none" msgid="2121957926040543148">"Imibala ejwayelekile"</string>
     <string name="color_matrix_night" msgid="5943817622105307072">"Imibala yasebusuku"</string>
     <string name="color_matrix_custom" msgid="3655576492322298713">"Imibala yangokwezifiso"</string>
+    <string name="color_matrix_auto" msgid="4896624757412029265">"Okuzenzakalelayo"</string>
     <string name="color_matrix_unknown" msgid="2709202104256265107">"Imibala engaziwa"</string>
     <string name="color_transform" msgid="6985460408079086090">"Ukulungiswa kombala"</string>
     <string name="color_matrix_show_qs" msgid="1763244354399276679">"Bonisa ithayili lezilungiselelo ezisheshayo"</string>
@@ -493,10 +495,28 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Amahedfoni axhunyiwe"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Ama-earphone axhunyiwe"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Nika amandla noma khubaza izithonjana kusukela ekubonisweni kubha yesimo."</string>
-    <!-- no translation found for data_saver (5037565123367048522) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
-    <skip />
-    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
-    <skip />
+    <string name="data_saver" msgid="5037565123367048522">"Iseva yedatha"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Iseva yedatha ivuliwe"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Iseva yedatha ivaliwe"</string>
+    <string name="switch_bar_on" msgid="1142437840752794229">"Vuliwe"</string>
+    <string name="nav_bar" msgid="1993221402773877607">"Ibha yokuzula"</string>
+    <string name="start" msgid="6873794757232879664">"Qala"</string>
+    <string name="center" msgid="4327473927066010960">"Maphakathi"</string>
+    <string name="end" msgid="125797972524818282">"Phelisa"</string>
+    <string name="space" msgid="804232271282109749">"Okwenza isikhala"</string>
+    <string name="menu_ime" msgid="4943221416525250684">"Isishintshi semenyu / sekhibhodi"</string>
+    <string name="select_button" msgid="1597989540662710653">"Khetha inkinobho ongayengeza"</string>
+    <string name="add_button" msgid="4134946063432258161">"Inkinobho yokwengeza"</string>
+    <string name="save" msgid="2311877285724540644">"Londoloza"</string>
+    <string name="reset" msgid="2448168080964209908">"Setha kabusha"</string>
+    <string name="no_home_title" msgid="1563808595146071549">"Ayikho inkinobho yasekhaya etholakele"</string>
+    <string name="no_home_message" msgid="5408485011659260911">"Inkinobho yasekhaya iyadingeka ukuthi inikwe amandla ukuze uzule kule divayisi. Sicela ungeze inkinobho yasekhaya ngaphambi kokulondoloza."</string>
+    <string name="adjust_button_width" msgid="6138616087197632947">"Lungisa ububanzi benkinobho"</string>
+    <string name="clipboard" msgid="1313879395099896312">"Ibhodi lokunamathisela"</string>
+    <string name="clipboard_description" msgid="3819919243940546364">"Ibhodi lokunamathisela livumela izinto ukuthi zihudulelwe ngqo ebhodini lokunamathisela. Izinto zingahudulelwa ngqo ngaphandle kwebhodi lokunamathisela uma zikhona."</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"Inkinobho yokuzula yangokwezifiso"</string>
+    <string name="keycode" msgid="7335281375728356499">"Ikhodi yokhiye"</string>
+    <string name="keycode_description" msgid="1403795192716828949">"Izinkinobho zebhodi yokhiye zivumela okhiye bekhibhodi ukuthi bangezwe kwibha yokuzula. Uma zicindezelwa zisula ukhiye wekhibhodi okhethiwe. Kokuqala ukhiye kufanele ukhethelwe inkinobho, ulandelwe isithombe esizoboniswa kwinkinobho."</string>
+    <string name="select_keycode" msgid="7413765103381924584">"Khetha inkinobho yekhibhodi"</string>
+    <string name="preview" msgid="9077832302472282938">"Hlola kuqala"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
deleted file mode 100644
index 17764f4..0000000
--- a/packages/SystemUI/res/values-zu/strings_tv.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="pip_exit" msgid="6423523158795119008">"Vala i-PIP"</string>
-    <string name="pip_fullscreen" msgid="8604643018538487816">"Iskrini esigcwele"</string>
-    <string name="pip_play" msgid="674145557658227044">"Dlala"</string>
-    <string name="pip_pause" msgid="8412075640017218862">"Misa isikhashana"</string>
-    <string name="pip_cancel" msgid="5173898361050559462">"Khansela"</string>
-    <string name="pip_hold_home" msgid="883546189749854120">"Bamba okuthi Ekhaya ukuze ulawule i-PIP"</string>
-</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 9bb6dc6..a9b8df2 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -158,5 +158,4 @@
     <!-- Keyboard shortcuts colors -->
     <color name="ksh_system_group_color">#ff00bcd4</color>
     <color name="ksh_application_group_color">#fff44336</color>
-    <color name="ksh_dialog_background_color">#ffffffff</color>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index ebe0d97..a6ba8b5 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -103,7 +103,7 @@
 
     <!-- The default tiles to display in QuickSettings -->
     <string name="quick_settings_tiles_default" translatable="false">
-        wifi,bt,flashlight,dnd,cell,battery,rotation,airplane,location,cast,work
+        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location
     </string>
 
     <!-- The tiles to display in QuickSettings -->
@@ -138,12 +138,6 @@
     <!-- The duration in seconds to wait before the dismiss buttons are shown. -->
     <integer name="recents_task_bar_dismiss_delay_seconds">1000</integer>
 
-    <!-- The duration of the window transition when coming to Recents from an app.
-         In order to defer the in-app animations until after the transition is complete,
-         we also need to use this value as the starting delay when animating the first
-         task decorations in. -->
-    <integer name="recents_enter_from_app_transition_duration">325</integer>
-
     <!-- The duration for animating the task decorations in after transitioning from an app. -->
     <integer name="recents_task_enter_from_app_duration">200</integer>
 
@@ -153,24 +147,6 @@
     <!-- The duration for animating the task decorations out before transitioning to an app. -->
     <integer name="recents_task_exit_to_app_duration">125</integer>
 
-    <!-- The duration of the window transition when coming to Recents from the Launcher.
-         In order to defer the in-app animations until after the transition is complete,
-         we also need to use this value as the starting delay when animating the task views
-         in from the bottom of the screen. -->
-    <integer name="recents_enter_from_home_transition_duration">100</integer>
-
-    <!-- The duration for animating the task from the bottom of the screen when transitioning
-     from home. -->
-    <integer name="recents_task_enter_from_home_duration">225</integer>
-
-    <!-- The stagger for each task when animating the task from the bottom of the screen when 
-     transitioning from home. -->
-    <integer name="recents_task_enter_from_home_stagger_delay">12</integer>
-
-    <!-- The duration of the animation of the tasks to the bottom of the screen when leaving
-     Recents to go back to the Launcher. -->
-    <integer name="recents_task_exit_to_home_duration">225</integer>
-
     <!-- The min animation duration for animating the nav bar scrim in. -->
     <integer name="recents_nav_bar_scrim_enter_duration">400</integer>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 32d09e8..e5e5710 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -124,7 +124,7 @@
     <dimen name="close_handle_underlap">32dp</dimen>
 
     <!-- Height of the status bar header bar -->
-    <dimen name="status_bar_header_height">90dp</dimen>
+    <dimen name="status_bar_header_height">80dp</dimen>
 
     <!-- Height of the status bar header bar when expanded -->
     <dimen name="status_bar_header_height_expanded">116dp</dimen>
@@ -186,6 +186,7 @@
     <dimen name="qs_detail_empty_text_size">14sp</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="segmented_button_spacing">0dp</dimen>
     <dimen name="borderless_button_radius">2dp</dimen>
@@ -606,4 +607,7 @@
 
     <dimen name="docked_divider_handle_width">16dp</dimen>
     <dimen name="docked_divider_handle_height">2dp</dimen>
+
+    <dimen name="battery_height">14.5dp</dimen>
+    <dimen name="battery_width">9.5dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 32da3c6..6ff9be1 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -897,10 +897,10 @@
     <!-- Message for add user confirmation dialog - short version. [CHAR LIMIT=none] -->
     <string name="user_add_user_message_short" msgid="1511354412249044381">When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. </string>
 
-    <!-- Title of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
+    <!-- Title of the confirmation dialog for deleting a user [CHAR LIMIT=NONE] -->
     <string name="user_remove_user_title">Remove user?</string>
 
-    <!-- Message of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
+    <!-- Message of the confirmation dialog for deleting a user [CHAR LIMIT=NONE] -->
     <string name="user_remove_user_message">All apps and data of this user will be deleted.</string>
 
     <!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
@@ -1044,9 +1044,6 @@
     <!-- VolumeUI restoration notification: text -->
     <string name="volumeui_notification_text">Touch to restore the original.</string>
 
-    <!-- Describes the way 2 names are concatenated. An example would be ", " to produce "Peter Muller, Paul Curry". Please also include a space here if it's appropriate in the language and if it's a RTL language include it on the left. The translation should start and end with " to keep the white space if desired [CHAR LIMIT=5] -->
-    <string name="group_summary_concadenation">", "</string>
-
     <!-- Toast shown when user unlocks screen and managed profile activity is in the foreground -->
     <string name="managed_profile_foreground_toast">You\'re using your work profile</string>
 
@@ -1187,6 +1184,11 @@
     <!-- Description for the toggle to set the initial scroll state to be paging or stack. DO NOT TRANSLATE -->
     <string name="overview_initial_state_paging_desc">Determines whether Overview will initially be in a stacked or paged state</string>
 
+    <!-- Toggle to enable the gesture to enter split-screen by swiping up from the Overview button. [CHAR LIMIT=60]-->
+    <string name="overview_nav_bar_gesture">Enable split-screen swipe-up accelerator</string>
+    <!-- Description for the toggle to enable the gesture to enter split-screen by swiping up from the Overview button. [CHAR LIMIT=NONE]-->
+    <string name="overview_nav_bar_gesture_desc">Enable gesture to enter split-screen by swiping up from the Overview button</string>
+
     <!-- Category in the System UI Tuner settings, where new/experimental
          settings are -->
     <string name="experimental">Experimental</string>
@@ -1400,4 +1402,7 @@
     <!-- SysUI Tuner: Label for preview area in navigation bar tuner [CHAR LIMIT=NONE] -->
     <string name="preview">Preview</string>
 
+    <!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
+    <string name="drag_to_add_tiles">Drag to add tiles</string>
+
 </resources>
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index c64327d..7c4768d 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -17,6 +17,8 @@
  */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Picture-in-Picture menu -->
+    <eat-comment />
     <!-- Button to close PIP on PIP UI -->
     <string name="pip_exit" translatable="false">Close PIP</string>
     <!-- Button to move PIP screen to the fullscreen on PIP UI -->
@@ -29,4 +31,13 @@
     <string name="pip_cancel" translatable="false">Cancel</string>
     <!-- Overlay text on PIP -->
     <string name="pip_hold_home" translatable="false">Hold HOME to control PIP</string>
+
+    <!-- Picture-in-Picture onboarding screen -->
+    <eat-comment />
+    <!-- Title for onboarding screen. -->
+    <string name="pip_onboarding_title" translatable="false">Picture-in-picture</string>
+    <!-- Description for onboarding screen. -->
+    <string name="pip_onboarding_description" translatable="false">Press and hold the HOME\nbutton to close or control it</string>
+    <!-- Button to close onboarding screen. -->
+    <string name="pip_onboarding_button" translatable="false">Got it</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 9931ab9..60a9fc2 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,10 +16,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="RecentsStyle" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
-        <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
-    </style>
-
     <style name="RecentsTheme" parent="@android:style/Theme.Material">
         <!-- NoTitle -->
         <item name="android:windowNoTitle">true</item>
@@ -27,38 +23,23 @@
         <item name="android:statusBarColor">@android:color/transparent</item>
         <item name="android:navigationBarColor">@android:color/transparent</item>
         <item name="android:windowDrawsSystemBarBackgrounds">true</item>
-        <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
+        <item name="android:windowAnimationStyle">@null</item>
         <item name="android:ambientShadowAlpha">0.35</item>
     </style>
 
 
-    <!-- Alternate Recents theme -->
+    <!-- Recents theme -->
     <style name="RecentsTheme.Wallpaper">
-        <!-- Wallpaper -->
         <item name="android:windowBackground">@color/transparent</item>
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:windowShowWallpaper">true</item>
     </style>
 
-    <!-- Performance optimized alternate Recents theme (no wallpaper) -->
+    <!-- Performance optimized Recents theme (no wallpaper) -->
     <style name="RecentsTheme.NoWallpaper">
         <item name="android:windowBackground">@android:color/black</item>
     </style>
 
-    <!-- Animations for a non-full-screen window or activity. -->
-    <style name="Animation.RecentsActivity" parent="@android:style/Animation.Activity">
-        <item name="android:activityOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
-        <item name="android:activityOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
-        <item name="android:taskOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
-        <item name="android:taskOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
-        <item name="android:taskToFrontEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
-        <item name="android:taskToFrontExitAnimation">@anim/recents_launch_from_launcher_exit</item>
-        <item name="android:wallpaperOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
-        <item name="android:wallpaperOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
-        <item name="android:wallpaperIntraOpenEnterAnimation">@anim/wallpaper_recents_launch_from_launcher_enter</item>
-        <item name="android:wallpaperIntraOpenExitAnimation">@anim/wallpaper_recents_launch_from_launcher_exit</item>
-    </style>
-
     <style name="TextAppearance.StatusBar.HeadsUp"
         parent="@*android:style/TextAppearance.StatusBar">
     </style>
@@ -241,6 +222,10 @@
         parent="@*android:style/TextAppearance.Material.Notification.Info">
     </style>
 
+    <style name="TextAppearance.Material.Notification.HybridNotificationDivider"
+        parent="@*android:style/TextAppearance.Material.Notification">
+    </style>
+
     <style name="SearchPanelCircle">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">match_parent</item>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index febe518..4de4ced 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -122,6 +122,11 @@
             android:title="@string/overview_fast_toggle_via_button"
             android:summary="@string/overview_fast_toggle_via_button_desc" />
 
+        <com.android.systemui.tuner.TunerSwitch
+            android:key="overview_nav_bar_gesture"
+            android:title="@string/overview_nav_bar_gesture"
+            android:summary="@string/overview_nav_bar_gesture_desc" />
+
     </PreferenceScreen>
 
     <SwitchPreference
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
index a0dbad4..454d1ce 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
@@ -51,6 +51,8 @@
     private static final float BOLT_LEVEL_THRESHOLD = 0.3f;  // opaque bolt below this fraction
 
     private final int[] mColors;
+    private final int mIntrinsicWidth;
+    private final int mIntrinsicHeight;
 
     private boolean mShowPercent;
     private float mButtonHeightFraction;
@@ -161,12 +163,26 @@
         mLightModeBackgroundColor =
                 context.getColor(R.color.light_mode_icon_color_dual_tone_background);
         mLightModeFillColor = context.getColor(R.color.light_mode_icon_color_dual_tone_fill);
+
+        mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width);
+        mIntrinsicHeight = context.getResources().getDimensionPixelSize(R.dimen.battery_height);
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mIntrinsicHeight;
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mIntrinsicWidth;
     }
 
     public void startListening() {
         mListening = true;
         mContext.getContentResolver().registerContentObserver(
                 Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
+        updateShowPercent();
         if (mDemoMode) return;
         mBatteryController.addStateChangedCallback(this);
     }
@@ -178,6 +194,11 @@
         mBatteryController.removeStateChangedCallback(this);
     }
 
+    public void disableShowPercent() {
+        mShowPercent = false;
+        postInvalidate();
+    }
+
     private void postInvalidate() {
         mHandler.post(new Runnable() {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/Interpolators.java b/packages/SystemUI/src/com/android/systemui/Interpolators.java
index cd6dce0..5e33a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/Interpolators.java
+++ b/packages/SystemUI/src/com/android/systemui/Interpolators.java
@@ -34,4 +34,10 @@
     public static final Interpolator LINEAR = new LinearInterpolator();
     public static final Interpolator ACCELERATE_DECELERATE = new AccelerateDecelerateInterpolator();
     public static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
+
+    /**
+     * Interpolator to be used when animating a move based on a click. Pair with enough duration.
+     */
+    public static final Interpolator TOUCH_RESPONSE =
+            new PathInterpolator(0.3f, 0f, 0.1f, 1f);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 7933cc6..e2b3777 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -43,6 +43,7 @@
         Key.DND_FAVORITE_BUCKET_INDEX,
         Key.DND_NONE_SELECTED,
         Key.DND_FAVORITE_ZEN,
+        Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN,
     })
     public @interface Key {
         String OVERVIEW_SEARCH_APP_WIDGET_ID = "searchAppWidgetId";
@@ -58,6 +59,7 @@
         String DND_FAVORITE_BUCKET_INDEX = "DndCountdownMinuteIndex";
         String DND_NONE_SELECTED = "DndNoneSelected";
         String DND_FAVORITE_ZEN = "DndFavoriteZen";
+        String TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN = "TvPictureInPictureOnboardingShown";
     }
 
     public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
index ed90904..1df372b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
@@ -24,6 +24,7 @@
 import android.view.ViewGroup;
 import android.widget.ImageView;
 
+import android.widget.ImageView.ScaleType;
 import com.android.systemui.R;
 
 import java.util.Objects;
@@ -96,7 +97,7 @@
     protected View createIcon() {
         final ImageView icon = new ImageView(mContext);
         icon.setId(android.R.id.icon);
-        icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+        icon.setScaleType(ScaleType.FIT_CENTER);
         return icon;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 8979023..1961860 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -41,6 +42,7 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile.DetailAdapter;
 import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.settings.BrightnessController;
 import com.android.systemui.settings.ToggleSlider;
 import com.android.systemui.statusbar.phone.QSTileHost;
@@ -538,6 +540,17 @@
         fireScanStateChanged(scanState);
     }
 
+    public void clickTile(ComponentName tile) {
+        final String spec = CustomTile.toSpec(tile);
+        final int N = mRecords.size();
+        for (int i = 0; i < N; i++) {
+            if (mRecords.get(i).tile.getTileSpec().equals(spec)) {
+                mRecords.get(i).tile.click();
+                break;
+            }
+        }
+    }
+
     private class H extends Handler {
         private static final int SHOW_DETAIL = 1;
         private static final int SET_TILE_VISIBILITY = 2;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 35000d3..d79f4d4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -76,7 +76,7 @@
 
     private String mTileSpec;
 
-    abstract protected TState newTileState();
+    public abstract TState newTileState();
     abstract protected void handleClick();
     abstract protected void handleUpdateState(TState state, Object arg);
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 753efb0..f208470 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -18,12 +18,13 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.content.res.Configuration;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
-
+import android.widget.Space;
 import com.android.systemui.R;
 
 import java.util.ArrayList;
@@ -102,6 +103,8 @@
 
     private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
 
+        private final ImageView mDownArrow;
+
         public HeaderTileLayout(Context context) {
             super(context);
             setClipChildren(false);
@@ -111,23 +114,40 @@
 
             int padding =
                     mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_padding);
-            ImageView downArrow = new ImageView(context);
-            downArrow.setImageResource(R.drawable.ic_expand_more);
-            downArrow.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(
+            mDownArrow = new ImageView(context);
+            mDownArrow.setImageResource(R.drawable.ic_expand_more);
+            mDownArrow.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(
                     android.R.color.white, null)));
-            downArrow.setLayoutParams(generateLayoutParams());
-            downArrow.setPadding(padding, padding, padding, padding);
-            addView(downArrow);
+            mDownArrow.setLayoutParams(generateLayoutParams());
+            mDownArrow.setPadding(padding, padding, padding, padding);
+            updateDownArrowMargin();
+            addView(mDownArrow);
             setOrientation(LinearLayout.HORIZONTAL);
         }
 
         @Override
-        public void addTile(TileRecord tile) {
-            tile.tileView.setLayoutParams(generateLayoutParams());
-            addView(tile.tileView, getChildCount() - 1 /* Leave icon at end */);
+        protected void onConfigurationChanged(Configuration newConfig) {
+            super.onConfigurationChanged(newConfig);
+            updateDownArrowMargin();
         }
 
-        private LayoutParams generateLayoutParams() {
+        private void updateDownArrowMargin() {
+            LayoutParams params = (LayoutParams) mDownArrow.getLayoutParams();
+            params.setMarginStart(mContext.getResources().getDimensionPixelSize(
+                    R.dimen.qs_expand_margin));
+            mDownArrow.setLayoutParams(params);
+        }
+
+        @Override
+        public void addTile(TileRecord tile) {
+            addView(tile.tileView, getChildCount() - 1 /* Leave icon at end */,
+                    generateLayoutParams());
+            // Add a spacer.
+            addView(new Space(mContext), getChildCount() - 1 /* Leave icon at end */,
+                    generateSpaceParams());
+        }
+
+        private LayoutParams generateSpaceParams() {
             int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
             LayoutParams lp = new LayoutParams(0, size);
             lp.weight = 1;
@@ -135,9 +155,30 @@
             return lp;
         }
 
+        private LayoutParams generateLayoutParams() {
+            int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
+            LayoutParams lp = new LayoutParams(size, size);
+            lp.gravity = Gravity.CENTER;
+            return lp;
+        }
+
         @Override
         public void removeTile(TileRecord tile) {
-            removeView(tile.tileView);
+            int childIndex = getChildIndex(tile.tileView);
+            // Remove the tile.
+            removeViewAt(childIndex);
+            // Remove its spacer as well.
+            removeViewAt(childIndex);
+        }
+
+        private int getChildIndex(QSTileBaseView tileView) {
+            final int N = getChildCount();
+            for (int i = 0; i < N; i++) {
+                if (getChildAt(i) == tileView) {
+                    return i;
+                }
+            }
+            return -1;
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
deleted file mode 100644
index 36bed0d..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.customize;
-
-import android.content.ComponentName;
-import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
-import android.graphics.drawable.Drawable;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
-
-public class BlankCustomTile extends QSTile<QSTile.State> {
-    public static final String PREFIX = "custom(";
-
-    private final ComponentName mComponent;
-
-    private BlankCustomTile(Host host, String action) {
-        super(host);
-        mComponent = ComponentName.unflattenFromString(action);
-    }
-
-    public static QSTile<?> create(Host host, String spec) {
-        if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
-            throw new IllegalArgumentException("Bad custom tile spec: " + spec);
-        }
-        final String action = spec.substring(PREFIX.length(), spec.length() - 1);
-        if (action.isEmpty()) {
-            throw new IllegalArgumentException("Empty custom tile spec action");
-        }
-        return new BlankCustomTile(host, action);
-    }
-
-    @Override
-    public void setListening(boolean listening) {
-    }
-
-    @Override
-    protected State newTileState() {
-        return new State();
-    }
-
-    @Override
-    protected void handleUserSwitch(int newUserId) {
-        super.handleUserSwitch(newUserId);
-    }
-
-    @Override
-    protected void handleClick() {
-        MetricsLogger.action(mContext, getMetricsCategory(), mComponent.getPackageName());
-    }
-
-    @Override
-    protected void handleLongClick() {
-    }
-
-    @Override
-    protected void handleUpdateState(State state, Object arg) {
-        try {
-            PackageManager pm = mContext.getPackageManager();
-            ServiceInfo info = pm.getServiceInfo(mComponent, 0);
-            Drawable drawable = info.loadIcon(pm);
-            drawable.setTint(mContext.getColor(R.color.qs_tile_tint_active));
-            state.icon = new DrawableIcon(drawable);
-            state.label = info.loadLabel(pm).toString();
-            state.contentDescription = state.label;
-        } catch (Exception e) {
-        }
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.QS_INTENT;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java
deleted file mode 100644
index 02cb0cf..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.qs.customize;
-
-import android.app.ActivityManager;
-import android.content.ClipData;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings.Secure;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.systemui.R;
-import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.external.CustomTile;
-import com.android.systemui.qs.external.TileLifecycleManager;
-import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.tuner.TunerService;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A version of QSPanel that allows tiles to be dragged around rather than
- * clicked on.  Dragging starting and receiving is handled in the NonPagedTileLayout,
- * and the saving/ordering is handled by the CustomQSTileHost.
- */
-public class CustomQSPanel extends QSPanel {
-    
-    private static final String TAG = "CustomQSPanel";
-    private static final boolean DEBUG = false;
-
-    private List<String> mSavedTiles = Collections.emptyList();
-    private ArrayList<String> mStash;
-    private List<String> mTiles = new ArrayList<>();
-
-    private ArrayList<QSTile<?>> mCurrentTiles = new ArrayList<>();
-
-    public CustomQSPanel(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mTileLayout = (QSTileLayout) LayoutInflater.from(mContext)
-                .inflate(R.layout.qs_customize_layout, mQsContainer, false);
-        mQsContainer.addView((View) mTileLayout, 1 /* Between brightness and footer */);
-        ((NonPagedTileLayout) mTileLayout).setCustomQsPanel(this);
-        removeView(mFooter.getView());
-
-        if (DEBUG) Log.d(TAG, "new CustomQSPanel", new Throwable());
-        TunerService.get(mContext).addTunable(this, QSTileHost.TILES_SETTING);
-    }
-
-    @Override
-    protected void showDetail(boolean show, Record r) {
-        // No detail here.
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        // Don't allow the super to unregister the tunable.
-    }
-
-    @Override
-    public void onTuningChanged(String key, String newValue) {
-        if (key.equals(QS_SHOW_BRIGHTNESS)) {
-            // No Brightness for you.
-            super.onTuningChanged(key, "0");
-        }
-        if (QSTileHost.TILES_SETTING.equals(key)) {
-            mSavedTiles = Collections.unmodifiableList(
-                    QSTileHost.loadTileSpecs(mContext, newValue));
-            if (DEBUG) Log.d(TAG, "New saved tiles " + TextUtils.join(",", mSavedTiles));
-        }
-    }
-
-    @Override
-    protected void createCustomizePanel() {
-        // Already in CustomizePanel.
-    }
-
-    public void tileSelected(QSTile<?> tile, ClipData currentClip) {
-        String sourceSpec = getSpec(currentClip);
-        String destSpec = tile.getTileSpec();
-        if (!sourceSpec.equals(destSpec)) {
-            moveTo(sourceSpec, destSpec);
-        }
-    }
-
-    public ClipData getClip(QSTile<?> tile) {
-        String tileSpec = tile.getTileSpec();
-        // TODO: Something better than plain text.
-        // TODO: Once using something better than plain text, stop listening to non-QS drag events.
-        return ClipData.newPlainText(tileSpec, tileSpec);
-    }
-
-    public String getSpec(ClipData data) {
-        return data.getItemAt(0).getText().toString();
-    }
-
-    public void setSavedTiles() {
-        if (DEBUG) Log.d(TAG, "setSavedTiles " + TextUtils.join(",", mSavedTiles));
-        setTiles(mSavedTiles);
-    }
-
-    public void saveCurrentTiles() {
-        for (int i = 0; i < mSavedTiles.size(); i++) {
-            String tileSpec = mSavedTiles.get(i);
-            if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
-            if (!mTiles.contains(tileSpec)) {
-                Intent intent = new Intent().setComponent(CustomTile.getComponentFromSpec(tileSpec));
-                TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
-                        mContext, intent, new UserHandle(ActivityManager.getCurrentUser()));
-                lifecycleManager.onStopListening();
-                lifecycleManager.onTileRemoved();
-                lifecycleManager.flushMessagesAndUnbind();
-            }
-        }
-        for (int i = 0; i < mTiles.size(); i++) {
-            String tileSpec = mTiles.get(i);
-            if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
-            if (!mSavedTiles.contains(tileSpec)) {
-                Intent intent = new Intent().setComponent(CustomTile.getComponentFromSpec(tileSpec));
-                TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
-                        mContext, intent, new UserHandle(ActivityManager.getCurrentUser()));
-                lifecycleManager.onTileAdded();
-                lifecycleManager.flushMessagesAndUnbind();
-            }
-        }
-        if (DEBUG) Log.d(TAG, "saveCurrentTiles " + mTiles);
-        Secure.putStringForUser(getContext().getContentResolver(), QSTileHost.TILES_SETTING,
-                TextUtils.join(",", mTiles), ActivityManager.getCurrentUser());
-    }
-
-    public void stashCurrentTiles() {
-        mStash = new ArrayList<>(mTiles);
-    }
-
-    public void unstashTiles() {
-        setTiles(mStash);
-    }
-
-    @Override
-    public void setTiles(Collection<QSTile<?>> tiles) {
-        setTilesInternal();
-    }
-
-    private void setTilesInternal() {
-        if (DEBUG) Log.d(TAG, "Set tiles internal");
-        for (int i = 0; i < mCurrentTiles.size(); i++) {
-            mCurrentTiles.get(i).destroy();
-        }
-        mCurrentTiles.clear();
-        for (int i = 0; i < mTiles.size(); i++) {
-            if (mTiles.get(i).startsWith(CustomTile.PREFIX)) {
-                QSTile<?> tile = BlankCustomTile.create(mHost, mTiles.get(i));
-                tile.setTileSpec(mTiles.get(i));
-                mCurrentTiles.add(tile);
-            } else {
-                QSTile<?> tile = mHost.createTile(mTiles.get(i));
-                if (tile != null) {
-                    tile.setTileSpec(mTiles.get(i));
-                    mCurrentTiles.add(tile);
-                } else {
-                    if (DEBUG) Log.d(TAG, "Skipping " + mTiles.get(i));
-                }
-            }
-        }
-        super.setTiles(mCurrentTiles);
-    }
-
-    public void addTile(String spec) {
-        if (DEBUG) Log.d(TAG, "addTile " + spec);
-        mTiles.add(spec);
-        setTilesInternal();
-    }
-
-    public void moveTo(String from, String to) {
-        if (DEBUG) Log.d(TAG, "moveTo " + from + " " + to);
-        int fromIndex = mTiles.indexOf(from);
-        if (fromIndex < 0) {
-            Log.e(TAG, "Unknown from tile " + from);
-            return;
-        }
-        int index = mTiles.indexOf(to);
-        if (index < 0) {
-            Log.e(TAG, "Unknown to tile " + to);
-            return;
-        }
-        mTiles.remove(fromIndex);
-        mTiles.add(index, from);
-        setTilesInternal();
-    }
-
-    public void remove(String spec) {
-        if (!mTiles.remove(spec)) {
-            Log.e(TAG, "Unknown remove spec " + spec);
-        }
-        setTilesInternal();
-    }
-
-    public void setTiles(List<String> tiles) {
-        if (DEBUG) Log.d(TAG, "Set tiles " + TextUtils.join(",", tiles));
-        mTiles = new ArrayList<>(tiles);
-        setTilesInternal();
-    }
-
-    public Collection<QSTile<?>> getTiles() {
-        return mCurrentTiles;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/DropButton.java b/packages/SystemUI/src/com/android/systemui/qs/customize/DropButton.java
deleted file mode 100644
index 3135408..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/DropButton.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-package com.android.systemui.qs.customize;
-
-import android.content.ClipData;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.DragEvent;
-import android.view.View;
-import android.view.View.OnDragListener;
-import android.widget.TextView;
-
-public class DropButton extends TextView implements OnDragListener {
-
-    private OnDropListener mListener;
-
-    public DropButton(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        // TODO: Don't do this, instead make this view the right size...
-        ((View) getParent()).setOnDragListener(this);
-    }
-
-    public void setOnDropListener(OnDropListener listener) {
-        mListener = listener;
-    }
-
-    private void setHovering(boolean hovering) {
-        setAlpha(hovering ? .3f : 1);
-    }
-
-    @Override
-    public boolean onDrag(View v, DragEvent event) {
-        switch (event.getAction()) {
-            case DragEvent.ACTION_DRAG_ENTERED:
-                setHovering(true);
-                break;
-            case DragEvent.ACTION_DROP:
-                if (mListener != null) {
-                    mListener.onDrop(this, event.getClipData());
-                }
-            case DragEvent.ACTION_DRAG_EXITED:
-            case DragEvent.ACTION_DRAG_ENDED:
-                setHovering(false);
-                break;
-        }
-        return true;
-    }
-
-    public interface OnDropListener {
-        void onDrop(View v, ClipData data);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/FloatingActionButton.java b/packages/SystemUI/src/com/android/systemui/qs/customize/FloatingActionButton.java
deleted file mode 100644
index 8791a10..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/FloatingActionButton.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.customize;
-
-import android.animation.AnimatorInflater;
-import android.content.Context;
-import android.graphics.Outline;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewOutlineProvider;
-import android.widget.ImageView;
-
-import com.android.systemui.R;
-
-public class FloatingActionButton extends ImageView {
-
-    public FloatingActionButton(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setScaleType(ScaleType.CENTER);
-        setStateListAnimator(AnimatorInflater.loadStateListAnimator(context, R.anim.fab_elevation));
-        setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                outline.setOval(0, 0, getWidth(), getHeight());
-            }
-        });
-        setClipToOutline(true);
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        super.onSizeChanged(w, h, oldw, oldh);
-        invalidateOutline();
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/NonPagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/customize/NonPagedTileLayout.java
deleted file mode 100644
index 98c7be4..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/NonPagedTileLayout.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.qs.customize;
-
-import android.content.ClipData;
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.DragEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.widget.LinearLayout;
-
-import com.android.systemui.R;
-import com.android.systemui.qs.PagedTileLayout;
-import com.android.systemui.qs.PagedTileLayout.TilePage;
-import com.android.systemui.qs.QSPanel.QSTileLayout;
-import com.android.systemui.qs.QSPanel.TileRecord;
-import com.android.systemui.qs.QSTile;
-
-import java.util.ArrayList;
-
-/**
- * Similar to PagedTileLayout, except that instead of pages it lays them out
- * vertically and expects to be inside a ScrollView.
- * @see CustomQSPanel
- */
-public class NonPagedTileLayout extends LinearLayout implements QSTileLayout, OnTouchListener {
-
-    private final ArrayList<TilePage> mPages = new ArrayList<>();
-    private final ArrayList<TileRecord> mTiles = new ArrayList<TileRecord>();
-    private CustomQSPanel mPanel;
-    private final Rect mHitRect = new Rect();
-
-    private ClipData mCurrentClip;
-    private View mCurrentView;
-
-    public NonPagedTileLayout(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        TilePage page = (PagedTileLayout.TilePage) findViewById(R.id.tile_page);
-        page.setMaxRows(3 /* First page only gets 3 */);
-        mPages.add(page);
-    }
-
-    public void setCustomQsPanel(CustomQSPanel qsPanel) {
-        mPanel = qsPanel;
-    }
-
-    @Override
-    public void addTile(TileRecord record) {
-        mTiles.add(record);
-        distributeTiles();
-        if (record.tileView.getTag() == record.tile) {
-            return;
-        }
-        record.tileView.setTag(record.tile);
-        record.tileView.setVisibility(View.VISIBLE);
-        record.tileView.init(null, null);
-        record.tileView.setOnTouchListener(this);
-        if (mCurrentClip != null && mCurrentClip.getItemAt(0)
-                .getText().toString().equals(record.tile.getTileSpec())) {
-            record.tileView.setAlpha(.3f);
-            mCurrentView = record.tileView;
-        }
-    }
-
-    @Override
-    public void removeTile(TileRecord tile) {
-        if (mTiles.remove(tile)) {
-            distributeTiles();
-        }
-    }
-
-    private void distributeTiles() {
-        final int NP = mPages.size();
-        for (int i = 0; i < NP; i++) {
-            mPages.get(i).removeAllViews();
-        }
-        int index = 0;
-        final int NT = mTiles.size();
-        for (int i = 0; i < NT; i++) {
-            TileRecord tile = mTiles.get(i);
-            mPages.get(index).addTile(tile);
-            // Keep everything in one layout for now.
-            if (false && mPages.get(index).isFull()) {
-                if (++index == mPages.size()) {
-                    LayoutInflater inflater = LayoutInflater.from(mContext);
-                    inflater.inflate(R.layout.horizontal_divider, this);
-                    mPages.add((TilePage) inflater.inflate(R.layout.qs_paged_page, this, false));
-                    addView(mPages.get(mPages.size() - 1));
-                }
-            }
-        }
-    }
-
-    @Override
-    public int getOffsetTop(TileRecord tile) {
-        // No touch feedback, so this isn't required.
-        return 0;
-    }
-
-    @Override
-    public boolean updateResources() {
-        return false;
-    }
-
-    @Override
-    public boolean onDragEvent(DragEvent event) {
-        switch (event.getAction()) {
-            case DragEvent.ACTION_DRAG_LOCATION:
-                float x = event.getX();
-                float y = event.getY();
-                final int NP = mPages.size();
-                for (int i = 0; i < NP; i++) {
-                    TilePage page = mPages.get(i);
-                    if (contains(page, x, y)) {
-                        x -= page.getLeft();
-                        y -= page.getTop();
-                        final int NC = page.getChildCount();
-                        for (int j = 0; j < NC; j++) {
-                            View child = page.getChildAt(j);
-                            if (contains(child, x, y)) {
-                                mPanel.tileSelected((QSTile<?>) child.getTag(), mCurrentClip);
-                            }
-                        }
-                        break;
-                    }
-                }
-                break;
-            case DragEvent.ACTION_DRAG_ENDED:
-                onDragEnded();
-                break;
-        }
-        return true;
-    }
-
-    @Override
-    public boolean onTouch(View v, MotionEvent event) {
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                // Stash the current tiles, in case the drop is on info, that we can restore
-                // the previous state.
-                mPanel.stashCurrentTiles();
-                mCurrentView = v;
-                mCurrentClip = mPanel.getClip((QSTile<?>) v.getTag());
-                View.DragShadowBuilder shadow = new View.DragShadowBuilder(v);
-                ((View) getParent().getParent()).startDrag(mCurrentClip, shadow, null, 0);
-                v.setAlpha(.3f);
-                return true;
-        }
-        return false;
-    }
-
-    public void onDragEnded() {
-        mCurrentView.setAlpha(1f);
-        mCurrentView = null;
-        mCurrentClip = null;
-    }
-
-    private boolean contains(View v, float x, float y) {
-        v.getHitRect(mHitRect);
-        return mHitRect.contains((int) x, (int) y);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index a6c7fe4..edcccac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -16,38 +16,25 @@
 package com.android.systemui.qs.customize;
 
 import android.animation.Animator;
-import android.content.ClipData;
+import android.animation.Animator.AnimatorListener;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnDismissListener;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
-import android.view.DragEvent;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.WindowManager;
 import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.Toolbar;
-import android.widget.Toolbar.OnMenuItemClickListener;
-
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailClipper;
-import com.android.systemui.qs.QSTile.Host.Callback;
-import com.android.systemui.qs.customize.DropButton.OnDropListener;
-import com.android.systemui.qs.customize.TileAdapter.TileSelectedListener;
+import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Allows full-screen customization of QS, through show() and hide().
@@ -55,26 +42,19 @@
  * This adds itself to the status bar window, so it can appear on top of quick settings and
  * *someday* do fancy animations to get into/out of it.
  */
-public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener, Callback,
-        OnDropListener, OnClickListener, Animator.AnimatorListener, TileSelectedListener,
-        OnCancelListener, OnDismissListener {
+public class QSCustomizer extends LinearLayout implements AnimatorListener, OnClickListener {
 
-    private static final int MENU_SAVE = Menu.FIRST;
-    private static final int MENU_RESET = Menu.FIRST + 1;
     private final QSDetailClipper mClipper;
 
     private PhoneStatusBar mPhoneStatusBar;
 
-    private Toolbar mToolbar;
-    private ViewGroup mDragButtons;
-    private CustomQSPanel mQsPanel;
-
     private boolean isShown;
-    private DropButton mInfoButton;
-    private DropButton mRemoveButton;
-    private FloatingActionButton mFab;
-    private SystemUIDialog mDialog;
     private QSTileHost mHost;
+    private RecyclerView mRecyclerView;
+    private TileAdapter mTileAdapter;
+    private View mClose;
+    private View mSave;
+    private View mReset;
 
     public QSCustomizer(Context context, AttributeSet attrs) {
         super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs);
@@ -83,59 +63,42 @@
 
     public void setHost(QSTileHost host) {
         mHost = host;
-        mHost.addCallback(this);
         mPhoneStatusBar = host.getPhoneStatusBar();
-        mQsPanel.setTiles(mHost.getTiles());
-        mQsPanel.setHost(mHost);
-        mQsPanel.setSavedTiles();
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar);
-        TypedValue value = new TypedValue();
-        mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
-        mToolbar.setNavigationIcon(
-                getResources().getDrawable(R.drawable.ic_close_white, mContext.getTheme()));
-        mToolbar.setNavigationOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                hide(0, 0);
-            }
-        });
-        mToolbar.setOnMenuItemClickListener(this);
-        mToolbar.getMenu().add(Menu.NONE, MENU_SAVE, 0, mContext.getString(R.string.save))
-                .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
-        mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
-                mContext.getString(com.android.internal.R.string.reset));
+        mClose = findViewById(R.id.close);
+        mSave = findViewById(R.id.save);
+        mReset = findViewById(R.id.reset);
+        mClose.setOnClickListener(this);
+        mSave.setOnClickListener(this);
+        mReset.setOnClickListener(this);
 
-        mQsPanel = (CustomQSPanel) findViewById(R.id.quick_settings_panel);
-
-        mDragButtons = (ViewGroup) findViewById(R.id.drag_buttons);
-        setDragging(false);
-
-        mInfoButton = (DropButton) findViewById(R.id.info_button);
-        mInfoButton.setOnDropListener(this);
-        mRemoveButton = (DropButton) findViewById(R.id.remove_button);
-        mRemoveButton.setOnDropListener(this);
-
-        mFab = (FloatingActionButton) findViewById(R.id.fab);
-        mFab.setImageResource(R.drawable.ic_add);
-        mFab.setOnClickListener(this);
+        mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
+        mTileAdapter = new TileAdapter(getContext());
+        mRecyclerView.setAdapter(mTileAdapter);
+        new ItemTouchHelper(mTileAdapter.getCallback()).attachToRecyclerView(mRecyclerView);
+        GridLayoutManager layout = new GridLayoutManager(getContext(), 3);
+        layout.setSpanSizeLookup(mTileAdapter.getSizeLookup());
+        mRecyclerView.setLayoutManager(layout);
+        mRecyclerView.addItemDecoration(mTileAdapter.getItemDecoration());
+        DefaultItemAnimator animator = new DefaultItemAnimator();
+        animator.setMoveDuration(TileAdapter.MOVE_DURATION);
+        mRecyclerView.setItemAnimator(animator);
     }
 
     public void show(int x, int y) {
         isShown = true;
-        mQsPanel.setSavedTiles();
         mPhoneStatusBar.getStatusBarWindow().addView(this);
-        mQsPanel.setListening(true);
+        setTileSpecs();
         mClipper.animateCircularClip(x, y, true, this);
+        new TileQueryHelper(mContext, mHost).setListener(mTileAdapter);
     }
 
     public void hide(int x, int y) {
         isShown = false;
-        mQsPanel.setListening(false);
         mClipper.animateCircularClip(x, y, false, this);
     }
 
@@ -149,109 +112,35 @@
         for (String tile : defTiles.split(",")) {
             tiles.add(tile);
         }
-        mQsPanel.setTiles(tiles);
+        mTileAdapter.setTileSpecs(tiles);
     }
 
-    private void setDragging(boolean dragging) {
-        mToolbar.setVisibility(!dragging ? View.VISIBLE : View.INVISIBLE);
+    private void setTileSpecs() {
+        List<String> specs = new ArrayList<>();
+        for (QSTile tile : mHost.getTiles()) {
+            specs.add(tile.getTileSpec());
+        }
+        mTileAdapter.setTileSpecs(specs);
     }
 
     private void save() {
-        Log.d("CustomQSPanel", "Save!");
-        mQsPanel.saveCurrentTiles();
-        // TODO: At save button.
-        hide(0, 0);
-    }
-
-    @Override
-    public boolean onMenuItemClick(MenuItem item) {
-        switch (item.getItemId()) {
-            case MENU_SAVE:
-                Log.d("CustomQSPanel", "Save...");
-                save();
-                break;
-            case MENU_RESET:
-                reset();
-                break;
-        }
-        return true;
-    }
-
-    @Override
-    public void onTileSelected(String spec) {
-        if (mDialog != null) {
-            mQsPanel.addTile(spec);
-            mDialog.dismiss();
-        }
-    }
-
-    @Override
-    public void onTilesChanged() {
-        mQsPanel.setTiles(mHost.getTiles());
-    }
-
-    public boolean onDragEvent(DragEvent event) {
-        switch (event.getAction()) {
-            case DragEvent.ACTION_DRAG_STARTED:
-                setDragging(true);
-                break;
-            case DragEvent.ACTION_DRAG_ENDED:
-                setDragging(false);
-                break;
-        }
-        return true;
-    }
-
-    public void onDrop(View v, ClipData data) {
-        if (v == mRemoveButton) {
-            mQsPanel.remove(mQsPanel.getSpec(data));
-        } else if (v == mInfoButton) {
-            mQsPanel.unstashTiles();
-            SystemUIDialog dialog = new SystemUIDialog(mContext);
-            dialog.setTitle(mQsPanel.getSpec(data));
-            dialog.setPositiveButton(R.string.ok, null);
-            dialog.show();
-        }
+        mTileAdapter.saveSpecs(mHost);
+        hide((int) mSave.getX() + mSave.getWidth() / 2, (int) mSave.getY() + mSave.getHeight() / 2);
     }
 
     @Override
     public void onClick(View v) {
-        if (mFab == v) {
-            mDialog = new SystemUIDialog(mContext,
-                    android.R.style.Theme_Material_Dialog);
-            View view = LayoutInflater.from(mContext).inflate(R.layout.qs_add_tiles_list, null);
-            ListView listView = (ListView) view.findViewById(android.R.id.list);
-            TileAdapter adapter = new TileAdapter(mContext, mQsPanel.getTiles(), mHost);
-            adapter.setListener(this);
-            listView.setDivider(null);
-            listView.setDividerHeight(0);
-            listView.setAdapter(adapter);
-            listView.setEmptyView(view.findViewById(R.id.empty_text));
-            mDialog.setView(view);
-            mDialog.setOnDismissListener(this);
-            mDialog.setOnCancelListener(this);
-            mDialog.show();
-            // Too lazy to figure out what this will be now, but it should probably be something
-            // besides just a dialog.
-            // For now, just make it big.
-            WindowManager.LayoutParams params = mDialog.getWindow().getAttributes();
-            params.width = WindowManager.LayoutParams.MATCH_PARENT;
-            params.height = WindowManager.LayoutParams.WRAP_CONTENT;
-            mDialog.getWindow().setAttributes(params);
+        if (v == mClose) {
+            hide((int) mClose.getX() + mClose.getWidth() / 2,
+                    (int) mClose.getY() + mClose.getHeight() / 2);
+        } else if (v == mSave) {
+            save();
+        } else if (v == mReset) {
+            reset();
         }
     }
 
     @Override
-    public void onDismiss(DialogInterface dialog) {
-        mDialog = null;
-    }
-
-    @Override
-    public void onCancel(DialogInterface dialog) {
-        mDialog = null;
-    }
-
-    @Override
     public void onAnimationEnd(Animator animation) {
         if (!isShown) {
             mPhoneStatusBar.getStatusBarWindow().removeView(this);
@@ -274,4 +163,4 @@
     public void onAnimationRepeat(Animator animation) {
         // Don't care.
     }
-}
\ No newline at end of file
+}
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 a4d7e93..fb3818c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -1,262 +1,293 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
  */
 
 package com.android.systemui.qs.customize;
 
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.os.Looper;
-import android.service.quicksettings.TileService;
-import android.util.Log;
+import android.graphics.Canvas;
+import android.graphics.drawable.ColorDrawable;
+import android.support.v4.view.ViewCompat;
+import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ItemDecoration;
+import android.support.v7.widget.RecyclerView.State;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.support.v7.widget.helper.ItemTouchHelper;
+import android.support.v7.widget.helper.ItemTouchHelper.Callback;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.GridLayout;
-import android.widget.ImageView;
-import android.widget.TextView;
-
+import android.widget.FrameLayout;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.QSTile.Icon;
-import com.android.systemui.qs.external.CustomTile;
+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;
 import com.android.systemui.statusbar.phone.QSTileHost;
 
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
 
-public class TileAdapter extends BaseAdapter {
+public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileStateListener {
 
-    private static final String TAG = "TileAdapter";
+    private static final long DRAG_LENGTH = 100;
+    private static final float DRAG_SCALE = 1.2f;
+    public static final long MOVE_DURATION = 150;
 
-    private final ArrayList<TileGroup> mGroups = new ArrayList<>();
+    private static final int TYPE_TILE = 0;
+    private static final int TYPE_EDIT = 1;
+
     private final Context mContext;
 
-    private TileSelectedListener mListener;
-    private ArrayList<String> mCurrentTiles;
+    private final List<TileInfo> mTiles = new ArrayList<>();
+    private int mDividerIndex;
+    private List<String> mCurrentSpecs;
+    private List<TileInfo> mOtherTiles;
+    private List<TileInfo> mAllTiles;
 
-    public TileAdapter(Context context, Collection<QSTile<?>> currentTiles, QSTileHost host) {
+    private Holder mCurrentDrag;
+
+    public TileAdapter(Context context) {
         mContext = context;
-        addSystemTiles(currentTiles, host);
-        // TODO: Live?
-    }
-
-    private void addSystemTiles(Collection<QSTile<?>> currentTiles, QSTileHost host) {
-        try {
-            ArrayList<String> tileSpecs = new ArrayList<>();
-            for (QSTile<?> tile : currentTiles) {
-                tileSpecs.add(tile.getTileSpec());
-            }
-            mCurrentTiles = tileSpecs;
-            final TileGroup group = new TileGroup("com.android.settings", mContext);
-            boolean hasColorMod = host.getDisplayController().isEnabled();
-            String possible = mContext.getString(R.string.quick_settings_tiles_default)
-                    + ",hotspot,inversion,saver" + (hasColorMod ? ",colors" : "");
-            String[] possibleTiles = possible.split(",");
-            for (int i = 0; i < possibleTiles.length; i++) {
-                final String spec = possibleTiles[i];
-                if (spec.startsWith("q")) {
-                    // Quick tiles can't be customized.
-                    continue;
-                }
-                if (tileSpecs.contains(spec)) {
-                    Log.d(TAG, "Skipping " + spec);
-                    continue;
-                }
-                Log.d(TAG, "Trying " + spec);
-                final QSTile<?> tile = host.createTile(spec);
-                if (tile == null) {
-                    continue;
-                }
-                // Bad, bad, very bad.
-                tile.setListening(true);
-                tile.clearState();
-                tile.refreshState();
-                tile.setListening(false);
-                new Handler(host.getLooper()).post(new Runnable() {
-                    @Override
-                    public void run() {
-                        group.addTile(spec, tile.getState().icon, tile.getState().label, mContext);
-                    }
-                });
-            }
-            // Error: Badness (10000).
-            // Serialize this work after the host's looper's queue is empty.
-            new Handler(host.getLooper()).post(new Runnable() {
-                @Override
-                public void run() {
-                    new Handler(Looper.getMainLooper()).post(new Runnable() {
-                        @Override
-                        public void run() {
-                            if (group.mTiles.size() > 0) {
-                                mGroups.add(group);
-                                notifyDataSetChanged();
-                            }
-                            new QueryTilesTask().execute();
-                        }
-                    });
-                }
-            });
-        } catch (NameNotFoundException e) {
-            Log.e(TAG, "Couldn't load system tiles", e);
-        }
-    }
-
-    public void setListener(TileSelectedListener listener) {
-        mListener = listener;
-    }
-
-    @Override
-    public int getCount() {
-        return mGroups.size();
-    }
-
-    @Override
-    public Object getItem(int position) {
-        return mGroups.get(position);
+        setHasStableIds(true);
     }
 
     @Override
     public long getItemId(int position) {
-        return position;
+        return mTiles.get(position) != null ? mAllTiles.indexOf(mTiles.get(position)) : -1;
+    }
+
+    public Callback getCallback() {
+        return mCallbacks;
+    }
+
+    public ItemDecoration getItemDecoration() {
+        return mDecoration;
+    }
+
+    public void saveSpecs(QSTileHost host) {
+        List<String> newSpecs = new ArrayList<>();
+        for (int i = 0; mTiles.get(i) != null; i++) {
+            newSpecs.add(mTiles.get(i).spec);
+        }
+        host.changeTiles(mCurrentSpecs, newSpecs);
+        setTileSpecs(newSpecs);
+    }
+
+    public void setTileSpecs(List<String> currentSpecs) {
+        mCurrentSpecs = currentSpecs;
+        recalcSpecs();
     }
 
     @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        return mGroups.get(position).getView(mContext, convertView, parent, mListener);
+    public void onTilesChanged(List<TileInfo> tiles) {
+        mAllTiles = tiles;
+        recalcSpecs();
     }
 
-    private static class TileGroup {
-        private final ArrayList<TileInfo> mTiles = new ArrayList<>();
-        private CharSequence mLabel;
-        private Drawable mIcon;
-
-        public TileGroup(String pkg, Context context) throws NameNotFoundException {
-            PackageManager pm = context.getPackageManager();
-            ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
-            mLabel = info.loadLabel(pm);
-            mIcon = info.loadIcon(pm);
-            Log.d(TAG, "Added " + mLabel);
+    private void recalcSpecs() {
+        if (mCurrentSpecs == null || mAllTiles == null) {
+            return;
         }
-
-        private void addTile(String spec, Drawable icon, CharSequence label) {
-            TileInfo info = new TileInfo();
-            info.label = label;
-            info.drawable = icon;
-            info.spec = spec;
-            mTiles.add(info);
+        mOtherTiles = new ArrayList<TileInfo>(mAllTiles);
+        mTiles.clear();
+        for (int i = 0; i < mCurrentSpecs.size(); i++) {
+            mTiles.add(getAndRemoveOther(mCurrentSpecs.get(i)));
         }
+        mTiles.add(null);
+        mTiles.addAll(mOtherTiles);
+        mDividerIndex = mTiles.indexOf(null);
+        notifyDataSetChanged();
+    }
 
-        private void addTile(String spec, Icon icon, CharSequence label, Context context) {
-            addTile(spec, icon.getDrawable(context), label);
-        }
-
-        private View getView(Context context, View convertView, ViewGroup parent,
-                final TileSelectedListener listener) {
-            if (convertView == null) {
-                convertView = LayoutInflater.from(context).inflate(R.layout.tile_listing, parent,
-                        false);
+    private TileInfo getAndRemoveOther(String s) {
+        for (int i = 0; i < mOtherTiles.size(); i++) {
+            if (mOtherTiles.get(i).spec.equals(s)) {
+                return mOtherTiles.remove(i);
             }
-            ((TextView) convertView.findViewById(android.R.id.title)).setText(mLabel);
-            ((ImageView) convertView.findViewById(android.R.id.icon)).setImageDrawable(mIcon);
-            GridLayout grid = (GridLayout) convertView.findViewById(R.id.tile_grid);
-            final int N = mTiles.size();
-            if (grid.getChildCount() != N) {
-                grid.removeAllViews();
+        }
+        return null;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if (mTiles.get(position) == null) {
+            return TYPE_EDIT;
+        }
+        return TYPE_TILE;
+    }
+
+    @Override
+    public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
+        final Context context = parent.getContext();
+        LayoutInflater inflater = LayoutInflater.from(context);
+        if (viewType == 1) {
+            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)));
+        return new Holder(frame);
+    }
+
+    @Override
+    public int getItemCount() {
+        return mTiles.size();
+    }
+
+    @Override
+    public void onBindViewHolder(Holder holder, int position) {
+        if (holder.getItemViewType() == TYPE_EDIT) return;
+
+        TileInfo info = mTiles.get(position);
+        holder.mTileView.onStateChanged(info.state);
+    }
+
+    public SpanSizeLookup getSizeLookup() {
+        return mSizeLookup;
+    }
+
+    public class Holder extends ViewHolder {
+        private QSTileView mTileView;
+
+        public Holder(View itemView) {
+            super(itemView);
+            if (itemView instanceof FrameLayout) {
+                mTileView = (QSTileView) ((FrameLayout) itemView).getChildAt(0);
             }
-            for (int i = 0; i < N; i++) {
-                if (grid.getChildCount() <= i) {
-                    grid.addView(createTile(context));
-                }
-                View view = grid.getChildAt(i);
-                final TileInfo tileInfo = mTiles.get(i);
-                ((ImageView) view.findViewById(R.id.tile_icon)).setImageDrawable(tileInfo.drawable);
-                ((TextView) view.findViewById(R.id.tile_label)).setText(tileInfo.label);
-                view.setClickable(true);
-                view.setOnClickListener(new OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        listener.onTileSelected(tileInfo.spec);
-                    }
-                });
-            }
-            return convertView;
         }
 
-        private View createTile(Context context) {
-            return LayoutInflater.from(context).inflate(R.layout.qs_add_tile_layout, null);
+        public void startDrag() {
+            itemView.animate()
+                    .setDuration(DRAG_LENGTH)
+                    .scaleX(DRAG_SCALE)
+                    .scaleY(DRAG_SCALE);
+            mTileView.findViewById(R.id.tile_label).animate()
+                    .setDuration(DRAG_LENGTH)
+                    .alpha(0);
+        }
+
+        public void stopDrag() {
+            itemView.animate()
+                    .setDuration(DRAG_LENGTH)
+                    .scaleX(1)
+                    .scaleY(1);
+            mTileView.findViewById(R.id.tile_label).animate()
+                    .setDuration(DRAG_LENGTH)
+                    .alpha(1);
         }
     }
 
-    private static class TileInfo {
-        private String spec;
-        private Drawable drawable;
-        private CharSequence label;
-    }
-
-    private class QueryTilesTask extends AsyncTask<Void, Void, Collection<TileGroup>> {
+    private final SpanSizeLookup mSizeLookup = new SpanSizeLookup() {
         @Override
-        protected Collection<TileGroup> doInBackground(Void... params) {
-            HashMap<String, TileGroup> pkgMap = new HashMap<>();
-            PackageManager pm = mContext.getPackageManager();
-            // TODO: Handle userness.
-            List<ResolveInfo> services = pm.queryIntentServices(
-                    new Intent(TileService.ACTION_QS_TILE), 0);
-            for (ResolveInfo info : services) {
-                String packageName = info.serviceInfo.packageName;
-                ComponentName componentName = new ComponentName(packageName, info.serviceInfo.name);
-                String spec = CustomTile.PREFIX + componentName.flattenToShortString() + ")";
-                if (mCurrentTiles.contains(spec)) {
+        public int getSpanSize(int position) {
+            return getItemViewType(position) == TYPE_EDIT ? 3 : 1;
+        }
+    };
+
+    private final ItemDecoration mDecoration = new ItemDecoration() {
+        // TODO: Move this to resource.
+        private final ColorDrawable mDrawable = new ColorDrawable(0xff384248);
+
+        @Override
+        public void onDraw(Canvas c, RecyclerView parent, State state) {
+            super.onDraw(c, parent, state);
+
+            final int childCount = parent.getChildCount();
+            final int width = parent.getWidth();
+            final int bottom = parent.getBottom();
+            for (int i = 0; i < childCount; i++) {
+                final View child = parent.getChildAt(i);
+                final ViewHolder holder = parent.getChildViewHolder(child);
+                if (holder.getAdapterPosition() < mDividerIndex) {
                     continue;
                 }
-                try {
-                    TileGroup group = pkgMap.get(packageName);
-                    if (group == null) {
-                        group = new TileGroup(packageName, mContext);
-                        pkgMap.put(packageName, group);
-                    }
-                    Drawable icon = info.serviceInfo.loadIcon(pm);
-                    CharSequence label = info.serviceInfo.loadLabel(pm);
-                    group.addTile(spec, icon, label != null ? label.toString() : "null");
-                } catch (NameNotFoundException e) {
-                    Log.w(TAG, "Couldn't find resolved package... " + packageName, e);
-                }
+
+                final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+                        .getLayoutParams();
+                final int top = child.getTop() + params.topMargin +
+                        Math.round(ViewCompat.getTranslationY(child));
+                // Draw full width, in case there aren't tiles all the way across.
+                mDrawable.setBounds(0, top, width, bottom);
+                mDrawable.draw(c);
+                break;
             }
-            return pkgMap.values();
+        }
+    };
+
+    private final ItemTouchHelper.Callback mCallbacks = new ItemTouchHelper.Callback() {
+
+        @Override
+        public boolean isLongPressDragEnabled() {
+            return true;
         }
 
         @Override
-        protected void onPostExecute(Collection<TileGroup> result) {
-            mGroups.addAll(result);
-            notifyDataSetChanged();
+        public boolean isItemViewSwipeEnabled() {
+            return false;
         }
-    }
 
-    public interface TileSelectedListener {
-        void onTileSelected(String spec);
-    }
+        @Override
+        public void onSelectedChanged(ViewHolder viewHolder, int actionState) {
+            super.onSelectedChanged(viewHolder, actionState);
+            if (mCurrentDrag != null) {
+                mCurrentDrag.stopDrag();
+            }
+            if (viewHolder != null) {
+                mCurrentDrag = (Holder) viewHolder;
+                mCurrentDrag.startDrag();
+            }
+        }
+
+        @Override
+        public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {
+            if (viewHolder.getItemViewType() == TYPE_EDIT) {
+                return makeMovementFlags(0, 0);
+            }
+            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT
+                    | ItemTouchHelper.LEFT;
+            return makeMovementFlags(dragFlags, 0);
+        }
+
+        @Override
+        public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target) {
+            int from = viewHolder.getAdapterPosition();
+            int to = target.getAdapterPosition();
+            if (to > mDividerIndex) {
+                if (from < mDividerIndex) {
+                    to = mDividerIndex;
+                } else {
+                    return false;
+                }
+            }
+            if (target.getItemViewType() == TYPE_EDIT && from < mDividerIndex) {
+                to++;
+            }
+            move(from, to, mTiles);
+            mDividerIndex = mTiles.indexOf(null);
+            notifyItemMoved(from, to);
+            return true;
+        }
+
+        private <T> void move(int from, int to, List<T> list) {
+            list.add(from > to ? to : to + 1, list.get(from));
+            list.remove(from > to ? from + 1 : from);
+        }
+
+        @Override
+        public void onSwiped(ViewHolder viewHolder, int direction) {
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
new file mode 100644
index 0000000..29f8af2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
+import android.service.quicksettings.TileService;
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSTile.DrawableIcon;
+import com.android.systemui.qs.external.CustomTile;
+import com.android.systemui.statusbar.phone.QSTileHost;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class TileQueryHelper {
+
+    private static final String TAG = "TileQueryHelper";
+
+    private final ArrayList<TileInfo> mTiles = new ArrayList<>();
+    private final ArrayList<String> mSpecs = new ArrayList<>();
+    private final Context mContext;
+    private TileStateListener mListener;
+
+    public TileQueryHelper(Context context, QSTileHost host) {
+        mContext = context;
+        addSystemTiles(host);
+        // TODO: Live?
+    }
+
+    private void addSystemTiles(QSTileHost host) {
+        boolean hasColorMod = host.getDisplayController().isEnabled();
+        String possible = mContext.getString(R.string.quick_settings_tiles_default)
+                + ",hotspot,inversion,saver" + (hasColorMod ? ",colors" : "");
+        String[] possibleTiles = possible.split(",");
+        final Handler qsHandler = new Handler(host.getLooper());
+        final Handler mainHandler = new Handler(Looper.getMainLooper());
+        for (int i = 0; i < possibleTiles.length; i++) {
+            final String spec = possibleTiles[i];
+            final QSTile<?> tile = host.createTile(spec);
+            if (tile == null) {
+                continue;
+            }
+            tile.setListening(true);
+            tile.clearState();
+            tile.refreshState();
+            tile.setListening(false);
+            qsHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    final QSTile.State state = tile.newTileState();
+                    tile.getState().copyTo(state);
+                    mainHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            addTile(spec, state);
+                            mListener.onTilesChanged(mTiles);
+                        }
+                    });
+                }
+            });
+        }
+        qsHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                new QueryTilesTask().execute();
+            }
+        });
+    }
+
+    public void setListener(TileStateListener listener) {
+        mListener = listener;
+    }
+
+    private void addTile(String spec, QSTile.State state) {
+        if (mSpecs.contains(spec)) {
+            return;
+        }
+        TileInfo info = new TileInfo();
+        info.state = state;
+        info.spec = spec;
+        mTiles.add(info);
+        mSpecs.add(spec);
+    }
+
+    private void addTile(String spec, Drawable drawable, CharSequence label, Context context) {
+        QSTile.State state = new QSTile.State();
+        state.label = label;
+        state.contentDescription = label;
+        state.icon = new DrawableIcon(drawable);
+        addTile(spec, state);
+    }
+
+    public static class TileInfo {
+        public String spec;
+        public QSTile.State state;
+    }
+
+    private class QueryTilesTask extends AsyncTask<Void, Void, Collection<TileInfo>> {
+        @Override
+        protected Collection<TileInfo> doInBackground(Void... params) {
+            List<TileInfo> tiles = new ArrayList<>();
+            PackageManager pm = mContext.getPackageManager();
+            List<ResolveInfo> services = pm.queryIntentServicesAsUser(
+                    new Intent(TileService.ACTION_QS_TILE), 0, ActivityManager.getCurrentUser());
+            for (ResolveInfo info : services) {
+                String packageName = info.serviceInfo.packageName;
+                ComponentName componentName = new ComponentName(packageName, info.serviceInfo.name);
+                String spec = CustomTile.toSpec(componentName);
+                Drawable icon = info.serviceInfo.loadIcon(pm);
+                if (icon != null) {
+                    icon.mutate();
+                    icon.setTint(mContext.getColor(android.R.color.white));
+                }
+                CharSequence label = info.serviceInfo.loadLabel(pm);
+                addTile(spec, icon, label != null ? label.toString() : "null", mContext);
+            }
+            return tiles;
+        }
+
+        @Override
+        protected void onPostExecute(Collection<TileInfo> result) {
+            mTiles.addAll(result);
+            mListener.onTilesChanged(mTiles);
+        }
+    }
+
+    public interface TileStateListener {
+        void onTilesChanged(List<TileInfo> tiles);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 886531a..3cd9e67 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -100,6 +100,15 @@
         mIsShowingDialog = true;
     }
 
+    public void onDialogHidden() {
+        mIsShowingDialog = false;
+        try {
+            if (DEBUG) Log.d(TAG, "Removing token");
+            mWindowManager.removeWindowToken(mToken);
+        } catch (RemoteException e) {
+        }
+    }
+
     @Override
     public void setListening(boolean listening) {
         if (mListening == listening) return;
@@ -142,7 +151,7 @@
     }
 
     @Override
-    protected State newTileState() {
+    public State newTileState() {
         return new State();
     }
 
@@ -226,6 +235,10 @@
         return 0;
     }
 
+    public static String toSpec(ComponentName name) {
+        return PREFIX + name.flattenToShortString() + ")";
+    }
+
     public static ComponentName getComponentFromSpec(String spec) {
         final String action = spec.substring(PREFIX.length(), spec.length() - 1);
         if (action.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 2f77a30..5cf1e21 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -52,6 +52,7 @@
     private boolean mJustBound;
     private long mLastUpdate;
     private int mType;
+    private boolean mShowingDialog;
 
     TileServiceManager(TileServices tileServices, Handler handler, ComponentName component) {
         this(tileServices, handler, new TileLifecycleManager(handler,
@@ -86,6 +87,10 @@
         mServices.recalculateBindAllowance();
     }
 
+    public void setShowingDialog(boolean dialog) {
+        mShowingDialog = dialog;
+    }
+
     public IQSTileService getTileService() {
         return mStateManager;
     }
@@ -153,10 +158,13 @@
             // Pending click is the most important thing, need to put this service at the top of
             // the list to be bound.
             mPriority = Integer.MAX_VALUE;
+        } else if (mShowingDialog) {
+            // Hang on to services that are showing dialogs so they don't die.
+            mPriority = Integer.MAX_VALUE - 1;
         } else if (mJustBound) {
             // If we just bound, lets not thrash on binding/unbinding too much, this is second most
             // important.
-            mPriority = Integer.MAX_VALUE - 1;
+            mPriority = Integer.MAX_VALUE - 2;
         } else if (!mBindRequested) {
             // Don't care about binding right now, put us last.
             mPriority = Integer.MIN_VALUE;
@@ -165,8 +173,8 @@
             long timeSinceUpdate = currentTime - mLastUpdate;
             // Fit compare into integer space for simplicity. Make sure to leave MAX_VALUE and
             // MAX_VALUE - 1 for the more important states above.
-            if (timeSinceUpdate > Integer.MAX_VALUE - 2) {
-                mPriority = Integer.MAX_VALUE - 2;
+            if (timeSinceUpdate > Integer.MAX_VALUE - 3) {
+                mPriority = Integer.MAX_VALUE - 3;
             } else {
                 mPriority = (int) timeSinceUpdate;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 04391fb..bfa4a32 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -197,6 +197,18 @@
         if (customTile != null) {
             customTile.onDialogShown();
             mHost.collapsePanels();
+            mServices.get(customTile).setShowingDialog(true);
+        }
+    }
+
+    @Override
+    public void onDialogHidden(Tile tile) {
+        ComponentName componentName = tile.getComponentName();
+        verifyCaller(componentName.getPackageName());
+        CustomTile customTile = getTileForComponent(componentName);
+        if (customTile != null) {
+            mServices.get(customTile).setShowingDialog(false);
+            customTile.onDialogHidden();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index d78d6ff..5222e61 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -51,7 +51,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 64b3a6c..72cdf18 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -54,7 +54,7 @@
     }
 
     @Override
-    protected State newTileState() {
+    public State newTileState() {
         return new QSTile.State();
     }
 
@@ -153,6 +153,7 @@
         private void bindView() {
             mDrawable.onBatteryLevelChanged(100, false, false);
             mDrawable.onPowerSaveChanged(true);
+            mDrawable.disableShowPercent();
             ((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
             Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
             checkbox.setChecked(mPowerSave);
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 874fc3e..1dce053 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -56,7 +56,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 18eb7a1..15e082a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -60,7 +60,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index aacdbc9..c3a2ebe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -54,7 +54,7 @@
     }
 
     @Override
-    protected SignalState newTileState() {
+    public SignalState newTileState() {
         return new SignalState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 6e843e9..e98734c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -54,7 +54,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index 1aeb0fe..c6a98b4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -30,7 +30,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index f99a3e4..58872ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -94,7 +94,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 1d9f15b..f06634e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -47,7 +47,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 2f37943..943b502 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -44,7 +44,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index e1dc9f2..bdf95d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -75,7 +75,7 @@
     }
 
     @Override
-    protected State newTileState() {
+    public State newTileState() {
         return new State();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 8328897..9f41f9a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -45,7 +45,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index f920d48..c94cf5a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -46,7 +46,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index 1565b6f..ba7ea4d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -37,7 +37,7 @@
     }
 
     @Override
-    protected State newTileState() {
+    public State newTileState() {
         return new QSTile.State();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 42296f2..ac4dfd5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -60,7 +60,7 @@
     }
 
     @Override
-    protected SignalState newTileState() {
+    public SignalState newTileState() {
         return new SignalState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 508490f..a94973c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -53,7 +53,7 @@
     }
 
     @Override
-    protected BooleanState newTileState() {
+    public BooleanState newTileState() {
         return new BooleanState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index c3b794d..3f482c8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -45,7 +45,6 @@
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
 import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
-import com.android.systemui.recents.events.activity.EnterRecentsTaskStackAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
 import com.android.systemui.recents.events.activity.ExitRecentsWindowFirstAnimationFrameEvent;
@@ -130,6 +129,7 @@
          */
         public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
             mLaunchIntent = launchIntent;
+            mOpts = opts;
         }
 
         @Override
@@ -437,11 +437,8 @@
     protected void onPause() {
         super.onPause();
 
-        RecentsDebugFlags flags = Recents.getDebugFlags();
-        if (flags.isFastToggleRecentsEnabled()) {
-            // Stop the fast-toggle dozer
-            mIterateTrigger.stopDozing();
-        }
+        // Stop the fast-toggle dozer
+        mIterateTrigger.stopDozing();
     }
 
     @Override
@@ -532,9 +529,9 @@
     }
 
     @Override
-    public void onMultiWindowModeChanged(boolean multiWindowMode) {
-        super.onMultiWindowModeChanged(multiWindowMode);
-        if (!multiWindowMode) {
+    public void onMultiWindowChanged(boolean inMultiWindow) {
+        super.onMultiWindowChanged(inMultiWindow);
+        if (!inMultiWindow) {
             RecentsTaskLoader loader = Recents.getTaskLoader();
             RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
             launchOpts.loadIcons = false;
@@ -648,6 +645,7 @@
     }
 
     public final void onBusEvent(UserInteractionEvent event) {
+        // Stop the fast-toggle dozer
         mIterateTrigger.stopDozing();
     }
 
@@ -694,21 +692,6 @@
         }
     }
 
-    public final void onBusEvent(EnterRecentsTaskStackAnimationCompletedEvent event) {
-        RecentsDebugFlags debugFlags = Recents.getDebugFlags();
-        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
-        if (!launchState.launchedWithAltTab && debugFlags.isFastToggleRecentsEnabled() &&
-                RecentsDebugFlags.Static.EnableFastToggleTimeoutOnEnter) {
-            mIterateTrigger.setDozeDuration(
-                    getResources().getInteger(R.integer.recents_auto_advance_duration));
-            if (!mIterateTrigger.isDozing()) {
-                mIterateTrigger.startDozing();
-            } else {
-                mIterateTrigger.poke();
-            }
-        }
-    }
-
     public final void onBusEvent(EnterRecentsWindowLastAnimationFrameEvent event) {
         EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(true));
         mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index 0afa1f6..177e841 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -52,10 +52,23 @@
      * Returns the task to focus given the current launch state.
      */
     public int getInitialFocusTaskIndex(int numTasks) {
+        RecentsDebugFlags debugFlags = Recents.getDebugFlags();
         if (launchedFromAppWithThumbnail) {
+            if (debugFlags.isFastToggleRecentsEnabled()) {
+                // If fast toggling, focus the front most task so that the next tap will focus the
+                // N-1 task
+                return numTasks - 1;
+            }
+
             // If coming from another app, focus the next task
             return numTasks - 2;
         } else {
+            if (debugFlags.isFastToggleRecentsEnabled()) {
+                // If fast toggling, defer focusing until the next tap (which will automatically
+                // focus the front most task)
+                return -1;
+            }
+
             // If coming from home, focus the first task
             return numTasks - 1;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 0115f91..9e43bb4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -103,12 +103,9 @@
     /**
      * Updates the configuration based on the current state of the system
      */
-    void update(Rect windowRect) {
-        // Recompute some values based on the given state, since we can not rely on the resource
-        // system to get certain values.
-        boolean isLandscape = windowRect.width() > windowRect.height();
-        hasTransposedNavBar = isLandscape && !isXLargeScreen;
-        hasTransposedSearchBar = isLandscape && !isXLargeScreen;
+    void update(Rect systemInsets) {
+        hasTransposedNavBar = systemInsets.right > 0;
+        hasTransposedSearchBar = systemInsets.right > 0;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index 6b8968f..fc14758 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -39,8 +39,6 @@
         public static final boolean EnableAffiliatedTaskGroups = true;
         // Overrides the Tuner flags and enables the fast toggle and timeout
         public static final boolean EnableFastToggleTimeoutOverride = true;
-        // Enables toggling the fast-toggle timeout immediately after entering Recents
-        public static final boolean EnableFastToggleTimeoutOnEnter = true;
 
         // Enables us to create mock recents tasks
         public static final boolean EnableMockTasks = false;
@@ -90,9 +88,6 @@
      * @return whether the initial stack state is paging.
      */
     public boolean isInitialStatePaging() {
-        if (Static.EnableFastToggleTimeoutOnEnter) {
-            return true;
-        }
         return mInitialStatePaging;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 5a60a19..dd7b7c1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -38,6 +38,7 @@
 import android.view.AppTransitionAnimationSpec;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewConfiguration;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Prefs;
@@ -48,6 +49,7 @@
 import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
 import com.android.systemui.recents.events.activity.IterateRecentsEvent;
+import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
@@ -81,8 +83,10 @@
 public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener {
 
     private final static String TAG = "RecentsImpl";
+
     // The minimum amount of time between each recents button press that we will handle
     private final static int MIN_TOGGLE_DELAY_MS = 350;
+
     // The duration within which the user releasing the alt tab (from when they pressed alt tab)
     // that the fast alt-tab animation will run.  If the user's alt-tab takes longer than this
     // duration, then we will toggle recents after this duration.
@@ -337,21 +341,31 @@
         mTriggeredFromAltTab = false;
 
         try {
+            ViewConfiguration viewConfig = ViewConfiguration.get(mContext);
             SystemServicesProxy ssp = Recents.getSystemServices();
             ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
             MutableBoolean isTopTaskHome = new MutableBoolean(true);
+            long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime;
+
             if (topTask != null && ssp.isRecentsTopMost(topTask, isTopTaskHome)) {
                 RecentsConfiguration config = Recents.getConfiguration();
                 RecentsActivityLaunchState launchState = config.getLaunchState();
                 if (!launchState.launchedWithAltTab) {
-                    // Notify recents to move onto the next task
-                    EventBus.getDefault().post(new IterateRecentsEvent());
+                    // If the user taps quickly
+                    if (ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
+                            elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
+                        // Launch the next focused task
+                        EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
+                    } else {
+                        // Notify recents to move onto the next task
+                        EventBus.getDefault().post(new IterateRecentsEvent());
+                    }
                 } else {
                     // If the user has toggled it too quickly, then just eat up the event here (it's
                     // better than showing a janky screenshot).
                     // NOTE: Ideally, the screenshot mechanism would take the window transform into
                     // account
-                    if ((SystemClock.elapsedRealtime() - mLastToggleTime) < MIN_TOGGLE_DELAY_MS) {
+                    if (elapsedTime < MIN_TOGGLE_DELAY_MS) {
                         return;
                     }
 
@@ -364,7 +378,7 @@
                 // better than showing a janky screenshot).
                 // NOTE: Ideally, the screenshot mechanism would take the window transform into
                 // account
-                if ((SystemClock.elapsedRealtime() - mLastToggleTime) < MIN_TOGGLE_DELAY_MS) {
+                if (elapsedTime < MIN_TOGGLE_DELAY_MS) {
                     return;
                 }
 
@@ -551,11 +565,14 @@
     public void dockTopTask(int topTaskId, int dragMode,
             int stackCreateMode, Rect initialBounds) {
         SystemServicesProxy ssp = Recents.getSystemServices();
+
+        // Make sure we inform DividerView before we actually start the activity so we can change
+        // the resize mode already.
+        EventBus.getDefault().send(new DockingTopTaskEvent(dragMode));
         ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds);
         showRecents(false /* triggeredFromAltTab */,
                 dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS, false /* animate */,
                 true /* reloadTasks*/);
-        EventBus.getDefault().send(new DockingTopTaskEvent(dragMode));
     }
 
     /**
@@ -599,10 +616,14 @@
             TaskStack stack) {
         RecentsConfiguration config = Recents.getConfiguration();
         SystemServicesProxy ssp = Recents.getSystemServices();
+        Rect systemInsets = new Rect();
+        ssp.getStableInsets(systemInsets);
         Rect windowRect = ssp.getWindowRect();
+        calculateWindowStableInsets(systemInsets, windowRect);
+        windowRect.offsetTo(0, 0);
 
         // Update the configuration for the current state
-        config.update(windowRect);
+        config.update(systemInsets);
 
         if (RecentsDebugFlags.Static.EnableSearchBar && tryAndBindSearchWidget) {
             // Try and pre-emptively bind the search widget on startup to ensure that we
@@ -612,9 +633,6 @@
                 config.getSearchBarBounds(windowRect, mStatusBarHeight, mSearchBarBounds);
             }
         }
-        Rect systemInsets = new Rect(0, mStatusBarHeight,
-                (config.hasTransposedNavBar ? mNavBarWidth : 0),
-                (config.hasTransposedNavBar ? 0 : mNavBarHeight));
         config.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right,
                 mSearchBarBounds, mTaskStackBounds);
 
@@ -641,6 +659,26 @@
     }
 
     /**
+     * Given the stable insets and the rect for our window, calculates the insets that affect our
+     * window.
+     */
+    private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect) {
+        Rect displayRect = Recents.getSystemServices().getDisplayRect();
+
+        // Display rect without insets - available app space
+        Rect appRect = new Rect(displayRect);
+        appRect.inset(inOutInsets);
+
+        // Our window intersected with available app space
+        Rect windowRectWithInsets = new Rect(windowRect);
+        windowRectWithInsets.intersect(appRect);
+        inOutInsets.left = windowRectWithInsets.left - windowRect.left;
+        inOutInsets.top = windowRectWithInsets.top - windowRect.top;
+        inOutInsets.right = windowRect.right - windowRectWithInsets.right;
+        inOutInsets.bottom = windowRect.bottom - windowRectWithInsets.bottom;
+    }
+
+    /**
      * Preloads the icon of a task.
      */
     private void preloadIcon(ActivityManager.RunningTaskInfo task) {
@@ -721,8 +759,9 @@
             for (int i = tasks.size() - 1; i >= 0; i--) {
                 Task task = tasks.get(i);
                 if (task.isFreeformTask()) {
-                    mTmpTransform = stackView.getStackAlgorithm().getStackTransform(task,
-                            stackView.getScroller().getStackScroll(), mTmpTransform, null);
+                    mTmpTransform = stackView.getStackAlgorithm()
+                            .getStackTransformScreenCoordinates(task,
+                                    stackView.getScroller().getStackScroll(), mTmpTransform, null);
                     Rect toTaskRect = new Rect();
                     mTmpTransform.rect.round(toTaskRect);
                     Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform);
@@ -783,7 +822,7 @@
 
         // Get the transform for the running task
         stackView.getScroller().setStackScrollToInitialState();
-        mTmpTransform = stackView.getStackAlgorithm().getStackTransform(launchTask,
+        mTmpTransform = stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
                 stackView.getScroller().getStackScroll(), mTmpTransform, null);
         return mTmpTransform;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java
new file mode 100644
index 0000000..11604b5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This event is sent to request that the next task is launched after a double-tap on the Recents
+ * button.
+ */
+public class LaunchNextTaskRequestEvent extends EventBus.Event {
+    // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java
new file mode 100644
index 0000000..d5083a8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * Fires when the user invoked the gesture to undock the task in the docked stack.
+ */
+public class UndockingTaskEvent extends EventBus.Event {
+
+    public UndockingTaskEvent() {
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index e288878..5eeda72 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -39,7 +39,7 @@
 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.views.TaskViewAnimation;
+import com.android.systemui.recents.views.AnimationProps;
 
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -67,9 +67,30 @@
     public static class ViewHolder extends RecyclerView.ViewHolder implements Task.TaskCallbacks {
         public final View content;
 
-        public ViewHolder(View v) {
-            super(v);
-            content = v;
+        private Task mTask;
+
+        public ViewHolder(View content) {
+            super(content);
+            this.content = content;
+        }
+
+        /**
+         * Binds this view holder to the given task.
+         */
+        public void bindToTask(Task newTask) {
+            unbindFromTask();
+            mTask = newTask;
+            mTask.addCallback(this);
+        }
+
+        /**
+         * Unbinds this view holder from the
+         */
+        public void unbindFromTask() {
+            if (mTask != null) {
+                mTask.removeCallback(this);
+                mTask = null;
+            }
         }
 
         @Override
@@ -224,7 +245,7 @@
             if (row.getViewType() == TASK_ROW_VIEW_TYPE) {
                 TaskRow taskRow = (TaskRow) row;
                 Task task = taskRow.task;
-                mStack.removeTask(task, TaskViewAnimation.IMMEDIATE);
+                mStack.removeTask(task, AnimationProps.IMMEDIATE);
                 EventBus.getDefault().send(new DeleteTaskDataEvent(task));
                 i = removeTaskRow(i);
             }
@@ -267,12 +288,13 @@
             }
             case TASK_ROW_VIEW_TYPE: {
                 TaskRow taskRow = (TaskRow) row;
-                taskRow.task.addCallback(holder);
                 TextView tv = (TextView) holder.content.findViewById(R.id.description);
                 tv.setText(taskRow.task.title);
                 ImageView iv = (ImageView) holder.content.findViewById(R.id.icon);
                 iv.setAlpha(0f);
                 holder.content.setOnClickListener(taskRow);
+
+                holder.bindToTask(taskRow.task);
                 loader.loadTaskData(taskRow.task, false /* fetchAndInvalidateThumbnails */);
                 break;
             }
@@ -289,7 +311,7 @@
             if (viewType == TASK_ROW_VIEW_TYPE) {
                 TaskRow taskRow = (TaskRow) row;
                 loader.unloadTaskData(taskRow.task);
-                taskRow.task.removeCallback(holder);
+                holder.unbindFromTask();
             }
         }
     }
@@ -304,7 +326,7 @@
     public void onTaskRemoved(Task task, int position) {
         // Since this is removed from the history, we need to update the stack as well to ensure
         // that the model is correct. Since the stack is hidden, we can update it immediately.
-        mStack.removeTask(task, TaskViewAnimation.IMMEDIATE);
+        mStack.removeTask(task, AnimationProps.IMMEDIATE);
         removeTaskRow(position);
         if (mRows.isEmpty()) {
             dismissHistory();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index d22cd53..22ab794 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -47,6 +47,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -977,6 +978,16 @@
         mWm.requestAppKeyboardShortcuts(receiver);
     }
 
+    public void getStableInsets(Rect outStableInsets) {
+        if (mWm == null) return;
+
+        try {
+            WindowManagerGlobal.getWindowManagerService().getStableInsets(outStableInsets);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
     public void focusPinnedStack() {
         try {
             mIam.setFocusedStack(PINNED_STACK_ID);
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 4e08bc2..c51aa7c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -138,18 +138,29 @@
             lastStackActiveTime = 0;
         }
         long newLastStackActiveTime = -1;
+        long prevLastActiveTime = lastStackActiveTime;
         int taskCount = mRawTasks.size();
         for (int i = 0; i < taskCount; i++) {
             ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
 
-            // Affiliated tasks are returned in a specific order from ActivityManager but without a
-            // lastActiveTime since it hasn't yet been started. However, we later sort the task list
-            // by lastActiveTime, which rearranges the tasks. For now, we need to workaround this
-            // by updating the lastActiveTime of this task to the lastActiveTime of the task it is
-            // affiliated with, in the same order that we encounter it in the original list (just
-            // its index in the task group for the task it is affiliated with).
+            /*
+             * Affiliated tasks are returned in a specific order from ActivityManager but without a
+             * lastActiveTime since it hasn't yet been started. However, we later sort the task list
+             * by lastActiveTime, which rearranges the tasks. For now, we need to workaround this
+             * by updating the lastActiveTime of this task to the lastActiveTime of the task it is
+             * affiliated with, in the same order that we encounter it in the original list (just
+             * its index in the task group for the task it is affiliated with).
+             *
+             * If the parent task is not available, then we will use the last active time of the
+             * previous task as a base point (since the task itself may not have an active time)
+             * for the entire affiliated group.
+             */
             if (t.persistentId != t.affiliatedTaskId) {
-                t.lastActiveTime = affiliatedTasks.get(t.affiliatedTaskId).lastActiveTime +
+                Task.TaskKey parentTask = affiliatedTasks.get(t.affiliatedTaskId);
+                long parentTaskLastActiveTime = parentTask != null
+                        ? parentTask.lastActiveTime
+                        : prevLastActiveTime;
+                t.lastActiveTime = parentTaskLastActiveTime +
                         affiliatedTaskCounts.get(t.affiliatedTaskId, 0) + 1;
             }
 
@@ -186,6 +197,8 @@
             allTasks.add(task);
             affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
             affiliatedTasks.put(taskKey.id, taskKey);
+
+            prevLastActiveTime = t.lastActiveTime;
         }
         if (newLastStackActiveTime != -1) {
             Prefs.putLong(mContext, Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME,
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 aa8efa7..1f91dce 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -43,7 +43,7 @@
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.views.DropTarget;
-import com.android.systemui.recents.views.TaskViewAnimation;
+import com.android.systemui.recents.views.AnimationProps;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -228,12 +228,12 @@
          * Notifies when a task has been removed from the stack.
          */
         void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
-            Task newFrontMostTask, TaskViewAnimation animation);
+            Task newFrontMostTask, AnimationProps animation);
 
         /**
          * Notifies when a task has been removed from the history.
          */
-        void onHistoryTaskRemoved(TaskStack stack, Task removedTask, TaskViewAnimation animation);
+        void onHistoryTaskRemoved(TaskStack stack, Task removedTask, AnimationProps animation);
     }
 
     /**
@@ -531,7 +531,7 @@
      * Removes a task from the stack, with an additional {@param animation} hint to the callbacks on
      * how they should update themselves.
      */
-    public void removeTask(Task t, TaskViewAnimation animation) {
+    public void removeTask(Task t, AnimationProps animation) {
         if (mStackTaskList.contains(t)) {
             boolean wasFrontMostTask = (getStackFrontMostTask(false /* includeFreeform */) == t);
             removeTaskImpl(mStackTaskList, t);
@@ -575,7 +575,7 @@
             if (!newTasksMap.containsKey(task.key)) {
                 if (notifyStackChanges) {
                     mCb.onStackTaskRemoved(this, task, i == (taskCount - 1), null,
-                            TaskViewAnimation.IMMEDIATE);
+                            AnimationProps.IMMEDIATE);
                 }
             }
             task.setGroup(null);
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 2d41742..58ec852 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
@@ -28,7 +28,7 @@
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.model.TaskStack.TaskStackCallbacks;
-import com.android.systemui.recents.views.TaskViewAnimation;
+import com.android.systemui.recents.views.AnimationProps;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -137,7 +137,7 @@
 
     @Override
     public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
-            Task newFrontMostTask, TaskViewAnimation animation) {
+            Task newFrontMostTask, AnimationProps animation) {
         getAdapter().notifyItemRemoved(stack.getStackTasks().indexOf(removedTask));
         if (mFocusedTask == removedTask) {
             resetFocusedTask(removedTask);
@@ -152,7 +152,7 @@
     }
 
     @Override
-    public void onHistoryTaskRemoved(TaskStack stack, Task removedTask, TaskViewAnimation animation) {
+    public void onHistoryTaskRemoved(TaskStack stack, Task removedTask, AnimationProps animation) {
         //No history task on tv
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java
new file mode 100644
index 0000000..93878c5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.views;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.annotation.IntDef;
+import android.util.SparseArray;
+import android.util.SparseLongArray;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.systemui.Interpolators;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/**
+ * The generic set of animation properties to animate a {@link View}. The animation can have
+ * different interpolators, start delays and durations for each of the different properties.
+ */
+public class AnimationProps {
+
+    public static final AnimationProps IMMEDIATE = new AnimationProps(0, Interpolators.LINEAR);
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({ALL, TRANSLATION_X, TRANSLATION_Y, TRANSLATION_Z, ALPHA, SCALE, BOUNDS})
+    public @interface PropType {}
+
+    public static final int ALL = 0;
+    public static final int TRANSLATION_X = 1;
+    public static final int TRANSLATION_Y = 2;
+    public static final int TRANSLATION_Z = 3;
+    public static final int ALPHA = 4;
+    public static final int SCALE = 5;
+    public static final int BOUNDS = 6;
+
+    private SparseLongArray mPropStartDelay;
+    private SparseLongArray mPropDuration;
+    private SparseArray<Interpolator> mPropInterpolators;
+    private Animator.AnimatorListener mListener;
+
+    /**
+     * The builder constructor.
+     */
+    public AnimationProps() {}
+
+    /**
+     * Creates an animation with a default {@param duration} and {@param interpolator} for all
+     * properties in this animation.
+     */
+    public AnimationProps(int duration, Interpolator interpolator) {
+        this(0, duration, interpolator, null);
+    }
+
+    /**
+     * Creates an animation with a default {@param duration} and {@param interpolator} for all
+     * properties in this animation.
+     */
+    public AnimationProps(int duration, Interpolator interpolator,
+            Animator.AnimatorListener listener) {
+        this(0, duration, interpolator, listener);
+    }
+
+    /**
+     * Creates an animation with a default {@param startDelay}, {@param duration} and
+     * {@param interpolator} for all properties in this animation.
+     */
+    public AnimationProps(int startDelay, int duration, Interpolator interpolator) {
+        this(startDelay, duration, interpolator, null);
+    }
+
+    /**
+     * Creates an animation with a default {@param startDelay}, {@param duration} and
+     * {@param interpolator} for all properties in this animation.
+     */
+    public AnimationProps(int startDelay, int duration, Interpolator interpolator,
+            Animator.AnimatorListener listener) {
+        setStartDelay(ALL, startDelay);
+        setDuration(ALL, duration);
+        setInterpolator(ALL, interpolator);
+        setListener(listener);
+    }
+
+    /**
+     * Creates a new {@link AnimatorSet} that will animate the given animators.  Callers need to
+     * manually apply the individual animation properties for each of the animators respectively.
+     */
+    public AnimatorSet createAnimator(List<Animator> animators) {
+        AnimatorSet anim = new AnimatorSet();
+        if (mListener != null) {
+            anim.addListener(mListener);
+        }
+        anim.playTogether(animators);
+        return anim;
+    }
+
+    /**
+     * Applies the specific start delay, duration and interpolator to the given {@param animator}
+     * for the specified {@param propertyType}.
+     */
+    public <T extends Animator> T apply(@PropType int propertyType, T animator) {
+        animator.setStartDelay(getStartDelay(propertyType));
+        animator.setDuration(getDuration(propertyType));
+        animator.setInterpolator(getInterpolator(propertyType));
+        return animator;
+    }
+
+    /**
+     * Sets a start delay for a specific property.
+     */
+    public AnimationProps setStartDelay(@PropType int propertyType, int startDelay) {
+        if (mPropStartDelay == null) {
+            mPropStartDelay = new SparseLongArray();
+        }
+        mPropStartDelay.append(propertyType, startDelay);
+        return this;
+    }
+
+    /**
+     * Returns the start delay for a specific property.
+     */
+    public long getStartDelay(@PropType int propertyType) {
+        if (mPropStartDelay != null) {
+            long startDelay = mPropStartDelay.get(propertyType, -1);
+            if (startDelay != -1) {
+                return startDelay;
+            }
+            return mPropStartDelay.get(ALL, 0);
+        }
+        return 0;
+    }
+
+    /**
+     * Sets a duration for a specific property.
+     */
+    public AnimationProps setDuration(@PropType int propertyType, int duration) {
+        if (mPropDuration == null) {
+            mPropDuration = new SparseLongArray();
+        }
+        mPropDuration.append(propertyType, duration);
+        return this;
+    }
+
+    /**
+     * Returns the duration for a specific property.
+     */
+    public long getDuration(@PropType int propertyType) {
+        if (mPropDuration != null) {
+            long duration = mPropDuration.get(propertyType, -1);
+            if (duration != -1) {
+                return duration;
+            }
+            return mPropDuration.get(ALL, 0);
+        }
+        return 0;
+    }
+
+    /**
+     * Sets an interpolator for a specific property.
+     */
+    public AnimationProps setInterpolator(@PropType int propertyType, Interpolator interpolator) {
+        if (mPropInterpolators == null) {
+            mPropInterpolators = new SparseArray<>();
+        }
+        mPropInterpolators.append(propertyType, interpolator);
+        return this;
+    }
+
+    /**
+     * Returns the interpolator for a specific property, falling back to the general interpolator
+     * if there is no specific property interpolator.
+     */
+    public Interpolator getInterpolator(@PropType int propertyType) {
+        if (mPropInterpolators != null) {
+            Interpolator interp = mPropInterpolators.get(propertyType);
+            if (interp != null) {
+                return interp;
+            }
+            return mPropInterpolators.get(ALL, Interpolators.LINEAR);
+        }
+        return Interpolators.LINEAR;
+    }
+
+    /**
+     * Sets an animator listener for this animation.
+     */
+    public AnimationProps setListener(Animator.AnimatorListener listener) {
+        mListener = listener;
+        return this;
+    }
+
+    /**
+     * Returns the animator listener for this animation.
+     */
+    public Animator.AnimatorListener getListener() {
+        return mListener;
+    }
+
+    /**
+     * Returns whether this animation has any duration.
+     */
+    public boolean isImmediate() {
+        int count = mPropDuration.size();
+        for (int i = 0; i < count; i++) {
+            if (mPropDuration.valueAt(i) > 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 3fdd771..6c1ff9b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -270,7 +270,8 @@
             if (taskView == null) {
                 specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
             } else {
-                layoutAlgorithm.getStackTransform(task, stackScroll, mTmpTransform, null);
+                layoutAlgorithm.getStackTransformScreenCoordinates(task, stackScroll, mTmpTransform,
+                        null);
                 specs.add(composeAnimationSpec(taskView, mTmpTransform, true /* addHeaderBitmap */));
             }
             return specs;
@@ -290,7 +291,8 @@
                     //       never happen)
                     specs.add(composeOffscreenAnimationSpec(t, offscreenTaskRect));
                 } else {
-                    layoutAlgorithm.getStackTransform(t, stackScroll, mTmpTransform, null);
+                    layoutAlgorithm.getStackTransformScreenCoordinates(t, stackScroll,
+                            mTmpTransform, null);
                     specs.add(composeAnimationSpec(tv, mTmpTransform, true /* addHeaderBitmap */));
                 }
             }
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 e2ff52c..5e113b9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -497,8 +497,9 @@
     }
 
     @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
+    public void onDrawForeground(Canvas canvas) {
+        super.onDrawForeground(canvas);
+
         ArrayList<TaskStack.DockState> visDockStates = mTouchHandler.getVisibleDockStates();
         for (int i = visDockStates.size() - 1; i >= 0; i--) {
             Drawable d = visDockStates.get(i).viewState.dockAreaOverlay;
@@ -530,8 +531,7 @@
 
     public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
         // Hide the history button
-        int taskViewExitToHomeDuration = getResources().getInteger(
-                R.integer.recents_task_exit_to_home_duration);
+        int taskViewExitToHomeDuration = TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION;
         hideHistoryButton(taskViewExitToHomeDuration, false /* translate */);
         animateBackgroundScrim(0f, taskViewExitToHomeDuration);
     }
@@ -588,7 +588,7 @@
             tmpTransform.scale = 1f;
             tmpTransform.rect.set(taskViewRect);
             mTaskStackView.updateTaskViewToTransform(event.taskView, tmpTransform,
-                    new TaskViewAnimation(125, Interpolators.ALPHA_OUT,
+                    new AnimationProps(125, Interpolators.ALPHA_OUT,
                             new AnimatorListenerAdapter() {
                                 @Override
                                 public void onAnimationEnd(Animator animation) {
@@ -598,7 +598,7 @@
                                             event.task.key.id, dockState.createMode);
 
                                     // Animate the stack accordingly
-                                    TaskViewAnimation stackAnim = new TaskViewAnimation(
+                                    AnimationProps stackAnim = new AnimationProps(
                                             TaskStackView.DEFAULT_SYNC_STACK_DURATION,
                                             Interpolators.FAST_OUT_SLOW_IN);
                                     mTaskStackView.getStack().removeTask(event.task, stackAnim);
@@ -646,9 +646,8 @@
     public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
         if (!launchState.launchedFromAppWithThumbnail && mStack.getTaskCount() > 0) {
-            int taskViewEnterFromHomeDuration = getResources().getInteger(
-                    R.integer.recents_task_enter_from_home_duration);
-            animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, taskViewEnterFromHomeDuration);
+            animateBackgroundScrim(DEFAULT_SCRIM_ALPHA,
+                    TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);
         }
     }
 
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 e8fa398..1cd0850 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -83,13 +83,11 @@
      * going home).
      */
     public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
-        int taskViewExitToAppDuration = mContext.getResources().getInteger(
-                R.integer.recents_task_exit_to_app_duration);
         if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
             mNavBarScrimView.animate()
                     .translationY(mNavBarScrimView.getMeasuredHeight())
                     .setStartDelay(0)
-                    .setDuration(taskViewExitToAppDuration)
+                    .setDuration(TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
                     .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                     .start();
         }
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 682c298..7eaa193 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -20,8 +20,10 @@
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Path;
 import android.graphics.RectF;
 import android.view.View;
+import android.view.animation.PathInterpolator;
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -63,6 +65,22 @@
                 ReferenceCountedTrigger postAnimationTrigger);
     }
 
+    private static final int FRAME_OFFSET_MS = 16;
+
+    public static final int ENTER_FROM_HOME_ALPHA_DURATION = 100;
+    public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 333;
+    private static final PathInterpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR =
+            new PathInterpolator(0, 0, 0, 1f);
+    private static final PathInterpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR =
+            new PathInterpolator(0, 0, 0.2f, 1f);
+
+    public static final int EXIT_TO_HOME_ALPHA_DURATION = 100;
+    public static final int EXIT_TO_HOME_TRANSLATION_DURATION = 150;
+    private static final PathInterpolator EXIT_TO_HOME_TRANSLATION_INTERPOLATOR =
+            new PathInterpolator(0.8f, 0, 0.6f, 1f);
+    private static final PathInterpolator EXIT_TO_HOME_ALPHA_INTERPOLATOR =
+            new PathInterpolator(0.4f, 0, 1f, 1f);
+
     private TaskStackView mStackView;
 
     private TaskViewTransform mTmpTransform = new TaskViewTransform();
@@ -90,7 +108,7 @@
             return;
         }
 
-        int offscreenY = stackLayout.mStackRect.bottom;
+        int offscreenYOffset = stackLayout.mStackRect.height();
         int taskViewAffiliateGroupEnterOffset = res.getDimensionPixelSize(
                 R.dimen.recents_task_view_affiliate_group_enter_offset);
 
@@ -127,7 +145,7 @@
             } else if (launchState.launchedFromHome) {
                 // Move the task view off screen (below) so we can animate it in
                 RectF bounds = new RectF(mTmpTransform.rect);
-                bounds.offsetTo(bounds.left, offscreenY);
+                bounds.offset(0, offscreenYOffset);
                 tv.setLeftTopRightBottom((int) bounds.left, (int) bounds.top, (int) bounds.right,
                         (int) bounds.bottom);
             }
@@ -157,15 +175,12 @@
                 R.integer.recents_task_enter_from_app_duration);
         int taskViewEnterFromAffiliatedAppDuration = res.getInteger(
                 R.integer.recents_task_enter_from_affiliated_app_duration);
-        int taskViewEnterFromHomeDuration = res.getInteger(
-                R.integer.recents_task_enter_from_home_duration);
-        int taskViewEnterFromHomeStaggerDelay = res.getInteger(
-                R.integer.recents_task_enter_from_home_stagger_delay);
 
         // Create enter animations for each of the views from front to back
         List<TaskView> taskViews = mStackView.getTaskViews();
         int taskViewCount = taskViews.size();
         for (int i = taskViewCount - 1; i >= 0; i--) {
+            int taskIndexFromFront = taskViewCount - i - 1;
             final TaskView tv = taskViews.get(i);
             Task task = tv.getTask();
             boolean currentTaskOccludesLaunchTarget = false;
@@ -186,7 +201,7 @@
                 } else {
                     // Animate the task up if it was occluding the launch target
                     if (currentTaskOccludesLaunchTarget) {
-                        TaskViewAnimation taskAnimation = new TaskViewAnimation(
+                        AnimationProps taskAnimation = new AnimationProps(
                                 taskViewEnterFromAffiliatedAppDuration, Interpolators.ALPHA_IN,
                                 new AnimatorListenerAdapter() {
                                     @Override
@@ -202,14 +217,16 @@
 
             } else if (launchState.launchedFromHome) {
                 // Animate the tasks up
-                int frontIndex = (taskViewCount - i - 1);
-                int delay = frontIndex * taskViewEnterFromHomeStaggerDelay;
-                int duration = taskViewEnterFromHomeDuration +
-                        frontIndex * taskViewEnterFromHomeStaggerDelay;
-
-                TaskViewAnimation taskAnimation = new TaskViewAnimation(delay,
-                        duration, Interpolators.DECELERATE_QUINT,
-                        postAnimationTrigger.decrementOnAnimationEnd());
+                AnimationProps taskAnimation = new AnimationProps()
+                        .setStartDelay(AnimationProps.ALPHA, taskIndexFromFront * FRAME_OFFSET_MS)
+                        .setDuration(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_DURATION)
+                        .setDuration(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_DURATION -
+                                (taskIndexFromFront * FRAME_OFFSET_MS))
+                        .setInterpolator(AnimationProps.BOUNDS,
+                                ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR)
+                        .setInterpolator(AnimationProps.ALPHA,
+                                ENTER_FROM_HOME_ALPHA_INTERPOLATOR)
+                        .setListener(postAnimationTrigger.decrementOnAnimationEnd());
                 postAnimationTrigger.increment();
                 mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
             }
@@ -221,7 +238,6 @@
      */
     public void startExitToHomeAnimation(boolean animated,
             ReferenceCountedTrigger postAnimationTrigger) {
-        Resources res = mStackView.getResources();
         TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
         TaskStackViewScroller stackScroller = mStackView.getScroller();
         TaskStack stack = mStackView.getStack();
@@ -231,24 +247,37 @@
             return;
         }
 
-        int offscreenY = stackLayout.mStackRect.bottom;
-        int taskViewExitToHomeDuration = res.getInteger(
-                R.integer.recents_task_exit_to_home_duration);
+        int offscreenYOffset = stackLayout.mStackRect.height();
 
         // Create the animations for each of the tasks
         List<TaskView> taskViews = mStackView.getTaskViews();
         int taskViewCount = taskViews.size();
         for (int i = 0; i < taskViewCount; i++) {
+            int taskIndexFromFront = taskViewCount - i - 1;
             TaskView tv = taskViews.get(i);
             Task task = tv.getTask();
-            TaskViewAnimation taskAnimation = new TaskViewAnimation(
-                    animated ? taskViewExitToHomeDuration : 0, Interpolators.FAST_OUT_LINEAR_IN,
-                    postAnimationTrigger.decrementOnAnimationEnd());
-            postAnimationTrigger.increment();
+
+            // Animate the tasks down
+            AnimationProps taskAnimation;
+            if (animated) {
+                taskAnimation = new AnimationProps()
+                        .setStartDelay(AnimationProps.ALPHA, i * FRAME_OFFSET_MS)
+                        .setDuration(AnimationProps.ALPHA, EXIT_TO_HOME_ALPHA_DURATION)
+                        .setDuration(AnimationProps.BOUNDS, EXIT_TO_HOME_TRANSLATION_DURATION +
+                                (taskIndexFromFront * FRAME_OFFSET_MS))
+                        .setInterpolator(AnimationProps.BOUNDS,
+                                EXIT_TO_HOME_TRANSLATION_INTERPOLATOR)
+                        .setInterpolator(AnimationProps.ALPHA,
+                                EXIT_TO_HOME_ALPHA_INTERPOLATOR)
+                        .setListener(postAnimationTrigger.decrementOnAnimationEnd());
+                postAnimationTrigger.increment();
+            } else {
+                taskAnimation = AnimationProps.IMMEDIATE;
+            }
 
             stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
                     null);
-            mTmpTransform.rect.offsetTo(mTmpTransform.rect.left, offscreenY);
+            mTmpTransform.rect.offset(0, offscreenYOffset);
             mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
         }
     }
@@ -283,7 +312,7 @@
                         screenPinningRequested, postAnimationTrigger);
             } else if (currentTaskOccludesLaunchTarget) {
                 // Animate this task out of view
-                TaskViewAnimation taskAnimation = new TaskViewAnimation(
+                AnimationProps taskAnimation = new AnimationProps(
                         taskViewExitToAppDuration, Interpolators.ALPHA_OUT,
                         postAnimationTrigger.decrementOnAnimationEnd());
                 postAnimationTrigger.increment();
@@ -315,7 +344,7 @@
         deleteTaskView.setClipViewInStack(false);
 
         // Compose the new animation and transform and star the animation
-        TaskViewAnimation taskAnimation = new TaskViewAnimation(taskViewRemoveAnimDuration,
+        AnimationProps taskAnimation = new AnimationProps(taskViewRemoveAnimDuration,
                 Interpolators.ALPHA_OUT, new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
@@ -352,7 +381,7 @@
         for (int i = taskViewCount - 1; i >= 0; i--) {
             TaskView tv = taskViews.get(i);
             Task task = tv.getTask();
-            TaskViewAnimation taskAnimation = new TaskViewAnimation(startDelayIncr * i,
+            AnimationProps taskAnimation = new AnimationProps(startDelayIncr * i,
                     historyTransitionDuration, Interpolators.FAST_OUT_SLOW_IN,
                     postAnimationTrigger.decrementOnAnimationEnd());
             postAnimationTrigger.increment();
@@ -381,7 +410,7 @@
         int taskViewCount = taskViews.size();
         for (int i = taskViewCount - 1; i >= 0; i--) {
             TaskView tv = taskViews.get(i);
-            TaskViewAnimation taskAnimation = new TaskViewAnimation(startDelayIncr * i,
+            AnimationProps taskAnimation = new AnimationProps(startDelayIncr * i,
                     historyTransitionDuration, Interpolators.FAST_OUT_SLOW_IN);
             stackLayout.getStackTransform(tv.getTask(), stackScroller.getStackScroll(),
                     mTmpTransform, null);
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 7c695ce..bd37c3b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -383,6 +383,7 @@
      */
     void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet) {
         SystemServicesProxy ssp = Recents.getSystemServices();
+        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
 
         // Clear the progress map
         mTaskIndexMap.clear();
@@ -449,7 +450,6 @@
             if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
                 mInitialScrollP = mMinScrollP;
             } else if (getDefaultFocusState() > 0f) {
-                RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
                 if (launchState.launchedFromHome) {
                     mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, launchTaskIndex));
                 } else {
@@ -568,7 +568,7 @@
             boolean isFrontMostTaskInGroup = task.group == null || task.group.isFrontMostTask(task);
             if (isFrontMostTaskInGroup) {
                 getStackTransform(taskProgress, mInitialScrollP, tmpTransform, null,
-                        false /* ignoreSingleTaskCase */);
+                        false /* ignoreSingleTaskCase */, false /* forceUpdate */);
                 float screenY = tmpTransform.rect.top;
                 boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
                 if (hasVisibleThumbnail) {
@@ -601,6 +601,12 @@
      */
     public TaskViewTransform getStackTransform(Task task, float stackScroll,
             TaskViewTransform transformOut, TaskViewTransform frontTransform) {
+        return getStackTransform(task, stackScroll, transformOut, frontTransform,
+                false /* forceUpdate */);
+    }
+
+    public TaskViewTransform getStackTransform(Task task, float stackScroll,
+        TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate) {
         if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
             mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
             return transformOut;
@@ -610,12 +616,25 @@
                 transformOut.reset();
                 return transformOut;
             }
-            return getStackTransform(mTaskIndexMap.get(task.key), stackScroll, transformOut,
-                    frontTransform, false /* ignoreSingleTaskCase */);
+            getStackTransform(mTaskIndexMap.get(task.key), stackScroll, transformOut,
+                    frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
+            return transformOut;
         }
     }
 
     /**
+     * Like {@link #getStackTransform}, but in screen coordinates
+     */
+    public TaskViewTransform getStackTransformScreenCoordinates(Task task, float stackScroll,
+            TaskViewTransform transformOut, TaskViewTransform frontTransform) {
+        Rect windowRect = Recents.getSystemServices().getWindowRect();
+        TaskViewTransform transform = getStackTransform(task, stackScroll, transformOut,
+                frontTransform);
+        transform.rect.offset(windowRect.left, windowRect.top);
+        return transform;
+    }
+
+    /**
      * Update/get the transform.
      *
      * @param ignoreSingleTaskCase When set, will ensure that the transform computed does not take
@@ -623,9 +642,9 @@
      *                             internally to ensure that we can calculate the transform for any
      *                             position in the stack.
      */
-    public TaskViewTransform getStackTransform(float taskProgress, float stackScroll,
+    public void getStackTransform(float taskProgress, float stackScroll,
             TaskViewTransform transformOut, TaskViewTransform frontTransform,
-            boolean ignoreSingleTaskCase) {
+            boolean ignoreSingleTaskCase, boolean forceUpdate) {
         SystemServicesProxy ssp = Recents.getSystemServices();
 
         // Compute the focused and unfocused offset
@@ -646,9 +665,9 @@
         }
 
         // Skip if the task is not visible
-        if (!unfocusedVisible && !focusedVisible) {
+        if (!forceUpdate && !unfocusedVisible && !focusedVisible) {
             transformOut.reset();
-            return transformOut;
+            return;
         }
 
         int x = (mStackRect.width() - mTaskRect.width()) / 2;
@@ -688,7 +707,6 @@
         transformOut.visible = (transformOut.rect.top < mStackRect.bottom) &&
                 (frontTransform == null || transformOut.rect.top != frontTransform.rect.top);
         transformOut.p = relP;
-        return transformOut;
     }
 
     /**
@@ -785,8 +803,10 @@
                 mFocusState * (mFocusedRange.relativeMin - mUnfocusedRange.relativeMin);
         float max = mUnfocusedRange.relativeMax +
                 mFocusState * (mFocusedRange.relativeMax - mUnfocusedRange.relativeMax);
-        getStackTransform(min, 0f, mBackOfStackTransform, null, true /* ignoreSingleTaskCase */);
-        getStackTransform(max, 0f, mFrontOfStackTransform, null, true /* ignoreSingleTaskCase */);
+        getStackTransform(min, 0f, mBackOfStackTransform, null, true /* ignoreSingleTaskCase */,
+                true /* forceUpdate */);
+        getStackTransform(max, 0f, mFrontOfStackTransform, null, true /* ignoreSingleTaskCase */,
+                true /* forceUpdate */);
         mBackOfStackTransform.visible = true;
         mFrontOfStackTransform.visible = true;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 232b416..bb74de4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -16,6 +16,10 @@
 
 package com.android.systemui.recents.views;
 
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.ComponentName;
@@ -34,9 +38,9 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 
 import com.android.systemui.Interpolators;
@@ -54,6 +58,7 @@
 import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
 import com.android.systemui.recents.events.activity.HideHistoryEvent;
 import com.android.systemui.recents.events.activity.IterateRecentsEvent;
+import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
 import com.android.systemui.recents.events.activity.PackagesChangedEvent;
@@ -85,10 +90,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-
 
 /* The visual representation of a task stack view */
 public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
@@ -124,7 +125,7 @@
     ArrayList<TaskView> mTaskViews = new ArrayList<>();
     ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
     ArraySet<Task.TaskKey> mIgnoreTasks = new ArraySet<>();
-    TaskViewAnimation mDeferredTaskViewLayoutAnimation = null;
+    AnimationProps mDeferredTaskViewLayoutAnimation = null;
 
     DozeTrigger mUIDozeTrigger;
     Task mFocusedTask;
@@ -135,6 +136,7 @@
 
     boolean mTaskViewsClipDirty = true;
     boolean mAwaitingFirstLayout = true;
+    boolean mInMeasureLayout = false;
     boolean mEnterAnimationComplete = false;
     boolean mTouchExplorationEnabled;
     boolean mScreenPinningEnabled;
@@ -537,17 +539,17 @@
             if (tv == null) {
                 tv = mViewPool.pickUpViewFromPool(task, task);
                 if (task.isFreeformTask()) {
-                    tv.updateViewPropertiesToTaskTransform(transform, TaskViewAnimation.IMMEDIATE,
+                    tv.updateViewPropertiesToTaskTransform(transform, AnimationProps.IMMEDIATE,
                             mRequestUpdateClippingListener);
                 } else {
                     if (Float.compare(transform.p, 0f) <= 0) {
                         tv.updateViewPropertiesToTaskTransform(
                                 mLayoutAlgorithm.getBackOfStackTransform(),
-                                TaskViewAnimation.IMMEDIATE, mRequestUpdateClippingListener);
+                                AnimationProps.IMMEDIATE, mRequestUpdateClippingListener);
                     } else {
                         tv.updateViewPropertiesToTaskTransform(
                                 mLayoutAlgorithm.getFrontOfStackTransform(),
-                                TaskViewAnimation.IMMEDIATE, mRequestUpdateClippingListener);
+                                AnimationProps.IMMEDIATE, mRequestUpdateClippingListener);
                     }
                 }
             } else {
@@ -580,9 +582,9 @@
      * animations that are current running on those task views, and will ensure that the children
      * {@link TaskView}s will match the set of visible tasks in the stack.
      *
-     * @see #relayoutTaskViews(TaskViewAnimation, ArraySet<Task.TaskKey>)
+     * @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>)
      */
-    void relayoutTaskViews(TaskViewAnimation animation) {
+    void relayoutTaskViews(AnimationProps animation) {
         relayoutTaskViews(animation, mIgnoreTasks);
     }
 
@@ -594,7 +596,7 @@
      *
      * @param ignoreTasksSet the set of tasks to ignore in the relayout
      */
-    void relayoutTaskViews(TaskViewAnimation animation, ArraySet<Task.TaskKey> ignoreTasksSet) {
+    void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet) {
         // If we had a deferred animation, cancel that
         mDeferredTaskViewLayoutAnimation = null;
 
@@ -623,17 +625,17 @@
     /**
      * Posts an update to synchronize the {@link TaskView}s with the stack on the next frame.
      */
-    void relayoutTaskViewsOnNextFrame(TaskViewAnimation animation) {
+    void relayoutTaskViewsOnNextFrame(AnimationProps animation) {
         mDeferredTaskViewLayoutAnimation = animation;
         invalidate();
     }
 
     /**
      * Called to update a specific {@link TaskView} to a given {@link TaskViewTransform} with a
-     * given set of {@link TaskViewAnimation} properties.
+     * given set of {@link AnimationProps} properties.
      */
     public void updateTaskViewToTransform(TaskView taskView, TaskViewTransform transform,
-            TaskViewAnimation animation) {
+            AnimationProps animation) {
         taskView.updateViewPropertiesToTaskTransform(transform, animation,
                 mRequestUpdateClippingListener);
     }
@@ -653,7 +655,7 @@
                 transform.fillIn(tv);
             } else {
                 mLayoutAlgorithm.getStackTransform(task, mStackScroller.getStackScroll(),
-                        transform, null);
+                        transform, null, true /* forceUpdate */);
             }
             transform.visible = true;
         }
@@ -1137,6 +1139,7 @@
      */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        mInMeasureLayout = true;
         int width = MeasureSpec.getSize(widthMeasureSpec);
         int height = MeasureSpec.getSize(heightMeasureSpec);
 
@@ -1159,22 +1162,29 @@
         mTmpTaskViews.addAll(mViewPool.getViews());
         int taskViewCount = mTmpTaskViews.size();
         for (int i = 0; i < taskViewCount; i++) {
-            TaskView tv = mTmpTaskViews.get(i);
-            if (tv.getBackground() != null) {
-                tv.getBackground().getPadding(mTmpRect);
-            } else {
-                mTmpRect.setEmpty();
-            }
-            tv.measure(
-                    MeasureSpec.makeMeasureSpec(
-                            mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right,
-                            MeasureSpec.EXACTLY),
-                    MeasureSpec.makeMeasureSpec(
-                            mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom,
-                            MeasureSpec.EXACTLY));
+            measureTaskView(mTmpTaskViews.get(i));
         }
 
         setMeasuredDimension(width, height);
+        mInMeasureLayout = false;
+    }
+
+    /**
+     * Measures a TaskView.
+     */
+    private void measureTaskView(TaskView tv) {
+        if (tv.getBackground() != null) {
+            tv.getBackground().getPadding(mTmpRect);
+        } else {
+            mTmpRect.setEmpty();
+        }
+        tv.measure(
+                MeasureSpec.makeMeasureSpec(
+                        mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right,
+                        MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(
+                        mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom,
+                        MeasureSpec.EXACTLY));
     }
 
     /**
@@ -1190,15 +1200,7 @@
         mTmpTaskViews.addAll(mViewPool.getViews());
         int taskViewCount = mTmpTaskViews.size();
         for (int i = 0; i < taskViewCount; i++) {
-            TaskView tv = mTmpTaskViews.get(i);
-            if (tv.getBackground() != null) {
-                tv.getBackground().getPadding(mTmpRect);
-            } else {
-                mTmpRect.setEmpty();
-            }
-            Rect taskRect = mLayoutAlgorithm.mTaskRect;
-            tv.layout(taskRect.left - mTmpRect.left, taskRect.top - mTmpRect.top,
-                    taskRect.right + mTmpRect.right, taskRect.bottom + mTmpRect.bottom);
+            layoutTaskView(mTmpTaskViews.get(i));
         }
 
         if (changed) {
@@ -1207,29 +1209,41 @@
             }
         }
         // Relayout all of the task views including the ignored ones
-        relayoutTaskViews(TaskViewAnimation.IMMEDIATE, EMPTY_TASK_SET);
+        relayoutTaskViews(AnimationProps.IMMEDIATE, EMPTY_TASK_SET);
         clipTaskViews();
 
         if (mAwaitingFirstLayout || !mEnterAnimationComplete) {
             mAwaitingFirstLayout = false;
             onFirstLayout();
-            return;
         }
     }
 
+    /**
+     * Lays out a TaskView.
+     */
+    private void layoutTaskView(TaskView tv) {
+        if (tv.getBackground() != null) {
+            tv.getBackground().getPadding(mTmpRect);
+        } else {
+            mTmpRect.setEmpty();
+        }
+        Rect taskRect = mLayoutAlgorithm.mTaskRect;
+        tv.layout(taskRect.left - mTmpRect.left, taskRect.top - mTmpRect.top,
+                taskRect.right + mTmpRect.right, taskRect.bottom + mTmpRect.bottom);
+    }
+
     /** Handler for the first layout. */
     void onFirstLayout() {
         // Setup the view for the enter animation
         mAnimationHelper.prepareForEnterAnimation();
 
         // Animate in the freeform workspace
-        animateFreeformWorkspaceBackgroundAlpha(
-                mLayoutAlgorithm.getStackState().freeformBackgroundAlpha, 150,
-                Interpolators.FAST_OUT_SLOW_IN);
+        int ffBgAlpha = mLayoutAlgorithm.getStackState().freeformBackgroundAlpha;
+        animateFreeformWorkspaceBackgroundAlpha(ffBgAlpha, new AnimationProps(150,
+                Interpolators.FAST_OUT_SLOW_IN));
 
         // Set the task focused state without requesting view focus, and leave the focus animations
         // until after the enter-animation
-        Task launchTask = mStack.getLaunchTarget();
         RecentsConfiguration config = Recents.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
         int focusedTaskIndex = launchState.getInitialFocusTaskIndex(mStack.getTaskCount());
@@ -1274,7 +1288,9 @@
     }
 
     @Override
-    protected void dispatchDraw(Canvas canvas) {
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
         // Draw the freeform workspace background
         SystemServicesProxy ssp = Recents.getSystemServices();
         if (ssp.hasFreeformWorkspaceSupport()) {
@@ -1282,8 +1298,6 @@
                 mFreeformWorkspaceBackground.draw(canvas);
             }
         }
-
-        super.dispatchDraw(canvas);
     }
 
     @Override
@@ -1318,7 +1332,7 @@
         updateLayoutAlgorithm(true /* boundScroll */);
 
         // Animate all the tasks into place
-        relayoutTaskViews(new TaskViewAnimation(DEFAULT_SYNC_STACK_DURATION,
+        relayoutTaskViews(new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
                 Interpolators.FAST_OUT_SLOW_IN));
     }
 
@@ -1327,7 +1341,7 @@
      */
     @Override
     public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
-            Task newFrontMostTask, TaskViewAnimation animation) {
+            Task newFrontMostTask, AnimationProps animation) {
         if (mFocusedTask == removedTask) {
             resetFocusedTask(removedTask);
         }
@@ -1364,7 +1378,7 @@
 
     @Override
     public void onHistoryTaskRemoved(TaskStack stack, Task removedTask,
-            TaskViewAnimation animation) {
+            AnimationProps animation) {
         // To be implemented
     }
 
@@ -1404,7 +1418,21 @@
 
         // Add/attach the view to the hierarchy
         if (isNewView) {
-            addView(tv, insertIndex);
+            if (mInMeasureLayout) {
+                // If we are measuring the layout, then just add the view normally as it will be
+                // laid out during the layout pass
+                addView(tv, insertIndex);
+            } else {
+                // Otherwise, this is from a bindVisibleTaskViews() call outside the measure/layout
+                // pass, and we should layout the new child ourselves
+                ViewGroup.LayoutParams params = tv.getLayoutParams();
+                if (params == null) {
+                    params = generateDefaultLayoutParams();
+                }
+                addViewInLayout(tv, insertIndex, params, true /* preventRequestLayout */);
+                measureTaskView(tv);
+                layoutTaskView(tv);
+            }
         } else {
             attachViewToParent(tv, insertIndex, tv.getLayoutParams());
         }
@@ -1463,14 +1491,14 @@
     public void onFocusStateChanged(float prevFocusState, float curFocusState) {
         if (mDeferredTaskViewLayoutAnimation == null) {
             mUIDozeTrigger.poke();
-            relayoutTaskViewsOnNextFrame(TaskViewAnimation.IMMEDIATE);
+            relayoutTaskViewsOnNextFrame(AnimationProps.IMMEDIATE);
         }
     }
 
     /**** TaskStackViewScroller.TaskStackViewScrollerCallbacks ****/
 
     @Override
-    public void onScrollChanged(float prevScroll, float curScroll, TaskViewAnimation animation) {
+    public void onScrollChanged(float prevScroll, float curScroll, AnimationProps animation) {
         mUIDozeTrigger.poke();
         if (animation != null) {
             relayoutTaskViewsOnNextFrame(animation);
@@ -1506,7 +1534,7 @@
                     tv.dismissTask();
                 } else {
                     // Otherwise, remove the task from the stack immediately
-                    mStack.removeTask(t, TaskViewAnimation.IMMEDIATE);
+                    mStack.removeTask(t, AnimationProps.IMMEDIATE);
                 }
             }
         }
@@ -1517,6 +1545,24 @@
         mUIDozeTrigger.stopDozing();
     }
 
+    public final void onBusEvent(LaunchNextTaskRequestEvent event) {
+        int launchTaskIndex = mStack.indexOfStackTask(mStack.getLaunchTarget());
+        if (launchTaskIndex != -1) {
+            launchTaskIndex = Math.max(0, launchTaskIndex - 1);
+        } else {
+            launchTaskIndex = mStack.getTaskCount() - 1;
+        }
+        if (launchTaskIndex != -1) {
+            // Stop all animations
+            mUIDozeTrigger.stopDozing();
+            cancelAllTaskViewAnimations();
+
+            Task launchTask = mStack.getStackTasks().get(launchTaskIndex);
+            EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask),
+                    launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+        }
+    }
+
     public final void onBusEvent(LaunchTaskStartedEvent event) {
         mAnimationHelper.startLaunchTaskAnimation(event.taskView, event.screenPinningRequested,
                 event.getAnimationTrigger());
@@ -1531,10 +1577,9 @@
         mAnimationHelper.startExitToHomeAnimation(event.animated, event.getAnimationTrigger());
 
         // Dismiss the freeform workspace background
-        int taskViewExitToHomeDuration = getResources().getInteger(
-                R.integer.recents_task_exit_to_home_duration);
-        animateFreeformWorkspaceBackgroundAlpha(0, taskViewExitToHomeDuration,
-                Interpolators.FAST_OUT_SLOW_IN);
+        int taskViewExitToHomeDuration = TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION;
+        animateFreeformWorkspaceBackgroundAlpha(0, new AnimationProps(taskViewExitToHomeDuration,
+                Interpolators.FAST_OUT_SLOW_IN));
     }
 
     public final void onBusEvent(DismissFocusedTaskViewEvent event) {
@@ -1587,6 +1632,9 @@
     }
 
     public final void onBusEvent(DragStartEvent event) {
+        // Ensure that the drag task is not animated
+        addIgnoreTask(event.task);
+
         if (event.task.isFreeformTask()) {
             // Animate to the front of the stack
             mStackScroller.animateScroll(mLayoutAlgorithm.mInitialScrollP, null);
@@ -1599,7 +1647,7 @@
         mTmpTransform.scale = finalScale;
         mTmpTransform.translationZ = mLayoutAlgorithm.mMaxTranslationZ + 1;
         updateTaskViewToTransform(event.taskView, mTmpTransform,
-                new TaskViewAnimation(DRAG_SCALE_DURATION, Interpolators.FAST_OUT_SLOW_IN));
+                new AnimationProps(DRAG_SCALE_DURATION, Interpolators.FAST_OUT_SLOW_IN));
     }
 
     public final void onBusEvent(DragStartInitializeDropTargetsEvent event) {
@@ -1611,7 +1659,7 @@
     }
 
     public final void onBusEvent(DragDropTargetChangedEvent event) {
-        TaskViewAnimation animation = new TaskViewAnimation(250, Interpolators.FAST_OUT_SLOW_IN);
+        AnimationProps animation = new AnimationProps(250, Interpolators.FAST_OUT_SLOW_IN);
         if (event.dropTarget instanceof TaskStack.DockState) {
             // Calculate the new task stack bounds that matches the window size that Recents will
             // have after the drop
@@ -1683,10 +1731,10 @@
         mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
                 mTmpTransform, null);
         event.getAnimationTrigger().increment();
-        relayoutTaskViews(new TaskViewAnimation(DEFAULT_SYNC_STACK_DURATION,
+        relayoutTaskViews(new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
                 Interpolators.FAST_OUT_SLOW_IN));
         updateTaskViewToTransform(event.taskView, mTmpTransform,
-                new TaskViewAnimation(DEFAULT_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN,
+                new AnimationProps(DEFAULT_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN,
                         event.getAnimationTrigger().decrementOnAnimationEnd()));
         removeIgnoreTask(event.task);
     }
@@ -1733,21 +1781,6 @@
         }
     }
 
-    public final void onBusEvent(EnterRecentsTaskStackAnimationCompletedEvent event) {
-        RecentsDebugFlags debugFlags = Recents.getDebugFlags();
-        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
-        if (!launchState.launchedWithAltTab && debugFlags.isFastToggleRecentsEnabled() &&
-                RecentsDebugFlags.Static.EnableFastToggleTimeoutOnEnter) {
-            if (mFocusedTask != null) {
-                int timerIndicatorDuration = getResources().getInteger(
-                        R.integer.recents_auto_advance_duration);
-                int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask);
-                setFocusedTask(focusedTaskIndex, false /* scrollToTask */,
-                        false /* requestViewFocus */, timerIndicatorDuration);
-            }
-        }
-    }
-
     public final void onBusEvent(UpdateFreeformTaskViewVisibilityEvent event) {
         List<TaskView> taskViews = getTaskViews();
         int taskViewCount = taskViews.size();
@@ -1797,15 +1830,15 @@
                 R.string.accessibility_recents_item_dismissed, task.title));
 
         // Remove the task from the stack
-        mStack.removeTask(task, new TaskViewAnimation(DEFAULT_SYNC_STACK_DURATION,
+        mStack.removeTask(task, new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
                 Interpolators.FAST_OUT_SLOW_IN));
     }
 
     /**
      * Starts an alpha animation on the freeform workspace background.
      */
-    private void animateFreeformWorkspaceBackgroundAlpha(int targetAlpha, int duration,
-            Interpolator interpolator) {
+    private void animateFreeformWorkspaceBackgroundAlpha(int targetAlpha,
+            AnimationProps animation) {
         if (mFreeformWorkspaceBackground.getAlpha() == targetAlpha) {
             return;
         }
@@ -1813,8 +1846,12 @@
         Utilities.cancelAnimationWithoutCallbacks(mFreeformWorkspaceBackgroundAnimator);
         mFreeformWorkspaceBackgroundAnimator = ObjectAnimator.ofInt(mFreeformWorkspaceBackground,
                 Utilities.DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha);
-        mFreeformWorkspaceBackgroundAnimator.setDuration(duration);
-        mFreeformWorkspaceBackgroundAnimator.setInterpolator(interpolator);
+        mFreeformWorkspaceBackgroundAnimator.setStartDelay(
+                animation.getDuration(AnimationProps.ALPHA));
+        mFreeformWorkspaceBackgroundAnimator.setDuration(
+                animation.getDuration(AnimationProps.ALPHA));
+        mFreeformWorkspaceBackgroundAnimator.setInterpolator(
+                animation.getInterpolator(AnimationProps.ALPHA));
         mFreeformWorkspaceBackgroundAnimator.start();
     }
 
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 ced5d4b..c641d75 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -38,7 +38,7 @@
     private static final boolean DEBUG = false;
 
     public interface TaskStackViewScrollerCallbacks {
-        void onScrollChanged(float prevScroll, float curScroll, TaskViewAnimation animation);
+        void onScrollChanged(float prevScroll, float curScroll, AnimationProps animation);
     }
 
     /**
@@ -93,14 +93,14 @@
      * Sets the current stack scroll immediately.
      */
     public void setStackScroll(float s) {
-        setStackScroll(s, TaskViewAnimation.IMMEDIATE);
+        setStackScroll(s, AnimationProps.IMMEDIATE);
     }
 
     /**
      * Sets the current stack scroll, but indicates to the callback the preferred animation to
      * update to this new scroll.
      */
-    public void setStackScroll(float s, TaskViewAnimation animation) {
+    public void setStackScroll(float s, AnimationProps animation) {
         float prevStackScroll = mStackScrollP;
         mStackScrollP = s;
         if (mCb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index da99956..d6680fd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -29,6 +29,7 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewParent;
+import android.view.animation.Animation;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
 
@@ -497,6 +498,7 @@
         // onBeginDrag().
         mSv.removeIgnoreTask(tv.getTask());
         mSv.updateLayoutAlgorithm(false /* boundScroll */);
+        mSv.relayoutTaskViews(AnimationProps.IMMEDIATE);
         mSwipeHelperAnimations.remove(v);
     }
 
@@ -546,7 +548,7 @@
             mTmpTransform.translationZ = fromTransform.translationZ +
                     (toTransform.translationZ - fromTransform.translationZ) * dismissFraction;
 
-            mSv.updateTaskViewToTransform(tv, mTmpTransform, TaskViewAnimation.IMMEDIATE);
+            mSv.updateTaskViewToTransform(tv, mTmpTransform, AnimationProps.IMMEDIATE);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 853f868..439d96f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -29,7 +29,6 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
-import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.IntProperty;
@@ -243,9 +242,9 @@
     }
 
     void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform,
-            TaskViewAnimation toAnimation, ValueAnimator.AnimatorUpdateListener updateCallback) {
+            AnimationProps toAnimation, ValueAnimator.AnimatorUpdateListener updateCallback) {
         RecentsConfiguration config = Recents.getConfiguration();
-        Utilities.cancelAnimationWithoutCallbacks(mTransformAnimation);
+        cancelTransformAnimation();
 
         // Compose the animations for the transform
         mTmpAnimators.clear();
@@ -255,21 +254,23 @@
                 setTaskProgress(toTransform.p);
             }
             // Manually call back to the animator listener and update callback
-            if (toAnimation.listener != null) {
-                toAnimation.listener.onAnimationEnd(null);
+            if (toAnimation.getListener() != null) {
+                toAnimation.getListener().onAnimationEnd(null);
             }
             if (updateCallback != null) {
                 updateCallback.onAnimationUpdate(null);
             }
         } else {
+            // Both the progress and the update are a function of the bounds movement of the task
             if (Float.compare(getTaskProgress(), toTransform.p) != 0) {
-                mTmpAnimators.add(ObjectAnimator.ofFloat(this, TASK_PROGRESS, getTaskProgress(),
-                        toTransform.p));
+                ObjectAnimator anim = ObjectAnimator.ofFloat(this, TASK_PROGRESS, getTaskProgress(),
+                        toTransform.p);
+                mTmpAnimators.add(toAnimation.apply(AnimationProps.BOUNDS, anim));
             }
             if (updateCallback != null) {
                 ValueAnimator updateCallbackAnim = ValueAnimator.ofInt(0, 1);
                 updateCallbackAnim.addUpdateListener(updateCallback);
-                mTmpAnimators.add(updateCallbackAnim);
+                mTmpAnimators.add(toAnimation.apply(AnimationProps.BOUNDS, updateCallbackAnim));
             }
 
             // Create the animator
@@ -280,7 +281,7 @@
 
     /** Resets this view's properties */
     void resetViewProperties() {
-        Utilities.cancelAnimationWithoutCallbacks(mTransformAnimation);
+        cancelTransformAnimation();
         setDim(0);
         setVisibility(View.VISIBLE);
         getViewBounds().reset();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
deleted file mode 100644
index 5455042..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.view.animation.Interpolator;
-
-import com.android.systemui.Interpolators;
-
-import java.util.List;
-
-/**
- * The animation properties to animate a {@link TaskView} to a given {@link TaskViewTransform}.
- */
-public class TaskViewAnimation {
-
-    public static final TaskViewAnimation IMMEDIATE = new TaskViewAnimation(0,
-            Interpolators.LINEAR);
-
-    public final int startDelay;
-    public final int duration;
-    public final Interpolator interpolator;
-    public final Animator.AnimatorListener listener;
-
-    public TaskViewAnimation(int duration, Interpolator interpolator) {
-        this(0 /* startDelay */, duration, interpolator, null);
-    }
-
-    public TaskViewAnimation(int duration, Interpolator interpolator,
-            Animator.AnimatorListener listener) {
-        this(0 /* startDelay */, duration, interpolator, listener);
-    }
-
-    public TaskViewAnimation(int startDelay, int duration, Interpolator interpolator) {
-        this(startDelay, duration, interpolator, null);
-    }
-
-    public TaskViewAnimation(int startDelay, int duration, Interpolator interpolator,
-            Animator.AnimatorListener listener) {
-        this.startDelay = startDelay;
-        this.duration = duration;
-        this.interpolator = interpolator;
-        this.listener = listener;
-    }
-
-    /**
-     * Creates a new {@link AnimatorSet} that will animate the given animators with the current
-     * animation properties.
-     */
-    public AnimatorSet createAnimator(List<Animator> animators) {
-        AnimatorSet anim = new AnimatorSet();
-        anim.setStartDelay(startDelay);
-        anim.setDuration(duration);
-        anim.setInterpolator(interpolator);
-        if (listener != null) {
-            anim.addListener(listener);
-        }
-        anim.playTogether(animators);
-        return anim;
-    }
-
-    /**
-     * Returns whether this animation has any duration.
-     */
-    public boolean isImmediate() {
-        return duration <= 0;
-    }
-}
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 7cde463..c91a833 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -274,8 +274,8 @@
     }
 
     @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
+    public void onDrawForeground(Canvas canvas) {
+        super.onDrawForeground(canvas);
 
         // Draw the dim layer with the rounded corners
         canvas.drawRoundRect(0, 0, mTaskViewRect.width(), getHeight() + mCornerRadius,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index 85b7c82..32878b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -154,13 +154,13 @@
      * Applies this transform to a view.
      */
     public void applyToTaskView(TaskView v, ArrayList<Animator> animators,
-            TaskViewAnimation taskAnimation, boolean allowShadows) {
+            AnimationProps animation, boolean allowShadows) {
         // Return early if not visible
         if (!visible) {
             return;
         }
 
-        if (taskAnimation.isImmediate()) {
+        if (animation.isImmediate()) {
             if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) {
                 v.setTranslationZ(translationZ);
             }
@@ -177,23 +177,27 @@
             }
         } else {
             if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) {
-                animators.add(ObjectAnimator.ofFloat(v, View.TRANSLATION_Z, v.getTranslationZ(),
-                        translationZ));
+                ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.TRANSLATION_Z,
+                        v.getTranslationZ(), translationZ);
+                animators.add(animation.apply(AnimationProps.TRANSLATION_Z, anim));
             }
             if (hasScaleChangedFrom(v.getScaleX())) {
-                animators.add(ObjectAnimator.ofPropertyValuesHolder(v,
+                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v,
                         PropertyValuesHolder.ofFloat(View.SCALE_X, v.getScaleX(), scale),
-                        PropertyValuesHolder.ofFloat(View.SCALE_Y, v.getScaleX(), scale)));
+                        PropertyValuesHolder.ofFloat(View.SCALE_Y, v.getScaleX(), scale));
+                animators.add(animation.apply(AnimationProps.SCALE, anim));
             }
             if (hasAlphaChangedFrom(v.getAlpha())) {
-                animators.add(ObjectAnimator.ofFloat(v, View.ALPHA, v.getAlpha(), alpha));
+                ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.ALPHA, v.getAlpha(), alpha);
+                animators.add(animation.apply(AnimationProps.ALPHA, anim));
             }
             if (hasRectChangedFrom(v)) {
-                animators.add(ObjectAnimator.ofPropertyValuesHolder(v,
+                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v,
                         PropertyValuesHolder.ofInt(LEFT, v.getLeft(), (int) rect.left),
                         PropertyValuesHolder.ofInt(TOP, v.getTop(), (int) rect.top),
                         PropertyValuesHolder.ofInt(RIGHT, v.getRight(), (int) rect.right),
-                        PropertyValuesHolder.ofInt(BOTTOM, v.getBottom(), (int) rect.bottom)));
+                        PropertyValuesHolder.ofInt(BOTTOM, v.getBottom(), (int) rect.bottom));
+                animators.add(animation.apply(AnimationProps.BOUNDS, anim));
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
index 5ef56f3..12e2713 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
@@ -26,10 +26,9 @@
 import android.graphics.Paint;
 import android.util.AttributeSet;
 import android.util.Property;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
 import android.widget.ImageButton;
 
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 
 /**
@@ -71,7 +70,6 @@
     private final int mWidth;
     private final int mHeight;
     private final int mCircleDiameter;
-    private final Interpolator mFastOutSlowInInterpolator;
     private int mCurrentWidth;
     private int mCurrentHeight;
     private AnimatorSet mAnimator;
@@ -85,8 +83,6 @@
         mCurrentWidth = mWidth;
         mCurrentHeight = mHeight;
         mCircleDiameter = (mWidth + mHeight) / 3;
-        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
-                android.R.interpolator.fast_out_slow_in);
     }
 
     public void setTouching(boolean touching, boolean animate) {
@@ -120,8 +116,8 @@
                 ? DividerView.TOUCH_ANIMATION_DURATION
                 : DividerView.TOUCH_RELEASE_ANIMATION_DURATION);
         mAnimator.setInterpolator(touching
-                ? DividerView.TOUCH_RESPONSE_INTERPOLATOR
-                : mFastOutSlowInInterpolator);
+                ? Interpolators.TOUCH_RESPONSE
+                : Interpolators.FAST_OUT_SLOW_IN);
         mAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 0b20f7a..83c22b1 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -48,10 +48,12 @@
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.internal.policy.DockedDividerUtils;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.DockingTopTaskEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
+import com.android.systemui.recents.events.activity.UndockingTaskEvent;
 import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
@@ -67,8 +69,6 @@
 
     static final long TOUCH_ANIMATION_DURATION = 150;
     static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
-    static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
-            new PathInterpolator(0.3f, 0f, 0.1f, 1f);
 
     private static final String TAG = "DividerView";
 
@@ -116,7 +116,6 @@
     private final Rect mOtherInsetRect = new Rect();
     private final Rect mLastResizeRect = new Rect();
     private final WindowManagerProxy mWindowManagerProxy = WindowManagerProxy.getInstance();
-    private Interpolator mFastOutSlowInInterpolator;
     private DividerWindowManager mWindowManager;
     private VelocityTracker mVelocityTracker;
     private FlingAnimationUtils mFlingAnimationUtils;
@@ -158,8 +157,6 @@
         mTouchElevation = getResources().getDimensionPixelSize(
                 R.dimen.docked_stack_divider_lift_elevation);
         mGrowRecents = getResources().getBoolean(R.bool.recents_grow_in_multiwindow);
-        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
-                android.R.interpolator.fast_out_slow_in);
         mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
         mFlingAnimationUtils = new FlingAnimationUtils(getContext(), 0.3f);
         updateDisplayInfo();
@@ -184,8 +181,17 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
-                insets.getStableInsetRight(), insets.getStableInsetBottom());
+        if (mStableInsets.left != insets.getStableInsetLeft()
+                || mStableInsets.top != insets.getStableInsetTop()
+                || mStableInsets.right != insets.getStableInsetRight()
+                || mStableInsets.bottom != insets.getStableInsetBottom()) {
+            mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+                    insets.getStableInsetRight(), insets.getStableInsetBottom());
+            if (mSnapAlgorithm != null) {
+                mSnapAlgorithm = null;
+                initializeSnapAlgorithm();
+            }
+        }
         return super.onApplyWindowInsets(insets);
     }
 
@@ -202,17 +208,13 @@
             mHandle.setTouching(true, animate);
         }
         mDockSide = mWindowManagerProxy.getDockSide();
-        getSnapAlgorithm();
-        if (mDockSide != WindowManager.DOCKED_INVALID) {
-            mWindowManagerProxy.setResizing(true);
-            mWindowManager.setSlippery(false);
-            if (touching) {
-                liftBackground();
-            }
-            return true;
-        } else {
-            return false;
+        initializeSnapAlgorithm();
+        mWindowManagerProxy.setResizing(true);
+        mWindowManager.setSlippery(false);
+        if (touching) {
+            liftBackground();
         }
+        return mDockSide != WindowManager.DOCKED_INVALID;
     }
 
     public void stopDragging(int position, float velocity, boolean avoidDismissStart) {
@@ -224,17 +226,36 @@
 
     public void stopDragging(int position, SnapTarget target, long duration,
             Interpolator interpolator) {
+        stopDragging(position, target, duration, 0 /* startDelay*/, interpolator);
+    }
+
+    public void stopDragging(int position, SnapTarget target, long duration, long startDelay,
+            Interpolator interpolator) {
         mHandle.setTouching(false, true /* animate */);
-        flingTo(position, target, duration, interpolator);
+        flingTo(position, target, duration, startDelay, interpolator);
         mWindowManager.setSlippery(true);
         releaseBackground();
     }
 
-    public DividerSnapAlgorithm getSnapAlgorithm() {
+    private void stopDragging() {
+        mHandle.setTouching(false, true /* animate */);
+        mWindowManager.setSlippery(true);
+        releaseBackground();
+    }
+
+    private void updateDockSide() {
+        mDockSide = mWindowManagerProxy.getDockSide();
+    }
+
+    private void initializeSnapAlgorithm() {
         if (mSnapAlgorithm == null) {
             mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth,
                     mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets);
         }
+    }
+
+    public DividerSnapAlgorithm getSnapAlgorithm() {
+        initializeSnapAlgorithm();
         return mSnapAlgorithm;
     }
 
@@ -258,6 +279,11 @@
                 mStartX = (int) event.getX();
                 mStartY = (int) event.getY();
                 boolean result = startDragging(true /* animate */, true /* touching */);
+                if (!result) {
+
+                    // Weren't able to start dragging successfully, so cancel it again.
+                    stopDragging();
+                }
                 mStartPosition = getCurrentPosition();
                 mMoving = false;
                 return result;
@@ -311,10 +337,11 @@
         anim.start();
     }
 
-    private void flingTo(int position, SnapTarget target, long duration,
+    private void flingTo(int position, SnapTarget target, long duration, long startDelay,
             Interpolator interpolator) {
         ValueAnimator anim = getFlingAnimator(position, target);
         anim.setDuration(duration);
+        anim.setStartDelay(startDelay);
         anim.setInterpolator(interpolator);
         anim.start();
     }
@@ -368,7 +395,7 @@
             mBackground.animate().scaleX(1.4f);
         }
         mBackground.animate()
-                .setInterpolator(TOUCH_RESPONSE_INTERPOLATOR)
+                .setInterpolator(Interpolators.TOUCH_RESPONSE)
                 .setDuration(TOUCH_ANIMATION_DURATION)
                 .translationZ(mTouchElevation)
                 .start();
@@ -376,7 +403,7 @@
         // Lift handle as well so it doesn't get behind the background, even though it doesn't
         // cast shadow.
         mHandle.animate()
-                .setInterpolator(TOUCH_RESPONSE_INTERPOLATOR)
+                .setInterpolator(Interpolators.TOUCH_RESPONSE)
                 .setDuration(TOUCH_ANIMATION_DURATION)
                 .translationZ(mTouchElevation)
                 .start();
@@ -384,14 +411,14 @@
 
     private void releaseBackground() {
         mBackground.animate()
-                .setInterpolator(mFastOutSlowInInterpolator)
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                 .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
                 .translationZ(0)
                 .scaleX(1f)
                 .scaleY(1f)
                 .start();
         mHandle.animate()
-                .setInterpolator(mFastOutSlowInInterpolator)
+                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                 .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
                 .translationZ(0)
                 .start();
@@ -412,6 +439,7 @@
         mDisplayWidth = info.logicalWidth;
         mDisplayHeight = info.logicalHeight;
         mSnapAlgorithm = null;
+        initializeSnapAlgorithm();
     }
 
     private int calculatePosition(int touchX, int touchY) {
@@ -496,12 +524,42 @@
         } else {
             mWindowManagerProxy.resizeDockedStack(mDockedRect, null, null, null, null);
         }
+        SnapTarget closestDismissTarget = mSnapAlgorithm.getClosestDismissTarget(position);
+        float dimFraction = getDimFraction(position, closestDismissTarget);
+        mWindowManagerProxy.setResizeDimLayer(dimFraction != 0f,
+                getStackIdForDismissTarget(closestDismissTarget),
+                dimFraction);
+    }
+
+    private float getDimFraction(int position, SnapTarget dismissTarget) {
         float fraction = mSnapAlgorithm.calculateDismissingFraction(position);
         fraction = Math.max(0, Math.min(fraction, 1f));
         fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
-        mWindowManagerProxy.setResizeDimLayer(fraction != 0f,
-                getStackIdForDismissTarget(mSnapAlgorithm.getClosestDismissTarget(position)),
-                fraction);
+        if (hasInsetsAtDismissTarget(dismissTarget)) {
+
+            // Less darkening with system insets.
+            fraction *= 0.8f;
+        }
+        return fraction;
+    }
+
+    /**
+     * @return true if and only if there are system insets at the location of the dismiss target
+     */
+    private boolean hasInsetsAtDismissTarget(SnapTarget dismissTarget) {
+        if (isHorizontalDivision()) {
+            if (dismissTarget == mSnapAlgorithm.getDismissStartTarget()) {
+                return mStableInsets.top != 0;
+            } else {
+                return mStableInsets.bottom != 0;
+            }
+        } else {
+            if (dismissTarget == mSnapAlgorithm.getDismissStartTarget()) {
+                return mStableInsets.left != 0;
+            } else {
+                return mStableInsets.right != 0;
+            }
+        }
     }
 
     /**
@@ -587,7 +645,7 @@
         }
         if (dismissTarget != null && fraction > 0f
                 && isDismissing(splitTarget, position, dockSide)) {
-            fraction = calculateParallaxDismissingFraction(fraction);
+            fraction = calculateParallaxDismissingFraction(fraction, dockSide);
             int offsetPosition = (int) (taskPosition +
                     fraction * (dismissTarget.position - splitTarget.position));
             int width = taskRect.width();
@@ -617,8 +675,14 @@
      * @return for a specified {@code fraction}, this returns an adjusted value that simulates a
      *         slowing down parallax effect
      */
-    private static float calculateParallaxDismissingFraction(float fraction) {
-        return SLOWDOWN_INTERPOLATOR.getInterpolation(fraction) / 3.5f;
+    private static float calculateParallaxDismissingFraction(float fraction, int dockSide) {
+        float result = SLOWDOWN_INTERPOLATOR.getInterpolation(fraction) / 3.5f;
+
+        // Less parallax at the top, just because.
+        if (dockSide == WindowManager.DOCKED_TOP) {
+            result /= 2f;
+        }
+        return result;
     }
 
     private static boolean isDismissing(SnapTarget snapTarget, int position, int dockSide) {
@@ -680,13 +744,29 @@
     public final void onBusEvent(RecentsDrawnEvent drawnEvent) {
         if (mAnimateAfterRecentsDrawn) {
             mAnimateAfterRecentsDrawn = false;
+            updateDockSide();
             stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 250,
-                    TOUCH_RESPONSE_INTERPOLATOR);
+                    Interpolators.TOUCH_RESPONSE);
         }
         if (mGrowAfterRecentsDrawn) {
             mGrowAfterRecentsDrawn = false;
+            updateDockSide();
             stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 250,
-                    TOUCH_RESPONSE_INTERPOLATOR);
+                    Interpolators.TOUCH_RESPONSE);
+        }
+    }
+
+    public final void onBusEvent(UndockingTaskEvent undockingTaskEvent) {
+        int dockSide = mWindowManagerProxy.getDockSide();
+        if (dockSide != WindowManager.DOCKED_INVALID) {
+            startDragging(false /* animate */, false /* touching */);
+            SnapTarget target = dockSideTopLeft(dockSide)
+                    ? mSnapAlgorithm.getDismissEndTarget()
+                    : mSnapAlgorithm.getDismissStartTarget();
+
+            // Don't start immediately - give a little bit time to settle the drag resize change.
+            stopDragging(getCurrentPosition(), target, 336 /* duration */, 100 /* startDelay */,
+                    Interpolators.TOUCH_RESPONSE);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 24ab506..15bcaf8 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -97,7 +97,7 @@
         @Override
         public void run() {
             try {
-                ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID, null, true, false,
+                ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID, null, true, true,
                         false);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed to resize stack: " + e);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index de6e7fe..71347c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import android.content.ComponentName;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -66,6 +67,9 @@
     private static final int MSG_CAMERA_LAUNCH_GESTURE         = 24 << MSG_SHIFT;
     private static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS     = 25 << MSG_SHIFT;
     private static final int MSG_REQUEST_TV_PICTURE_IN_PICTURE = 26 << MSG_SHIFT;
+    private static final int MSG_ADD_QS_TILE                   = 27 << MSG_SHIFT;
+    private static final int MSG_REMOVE_QS_TILE                = 28 << MSG_SHIFT;
+    private static final int MSG_CLICK_QS_TILE                 = 29 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -112,6 +116,10 @@
         public void startAssist(Bundle args);
         public void onCameraLaunchGestureDetected(int source);
         public void requestTvPictureInPicture();
+
+        void addQsTile(ComponentName tile);
+        void remQsTile(ComponentName tile);
+        void clickTile(ComponentName tile);
     }
 
     public CommandQueue(Callbacks callbacks) {
@@ -318,6 +326,27 @@
         }
     }
 
+    @Override
+    public void addQsTile(ComponentName tile) {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_ADD_QS_TILE, tile).sendToTarget();
+        }
+    }
+
+    @Override
+    public void remQsTile(ComponentName tile) {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_REMOVE_QS_TILE, tile).sendToTarget();
+        }
+    }
+
+    @Override
+    public void clickQsTile(ComponentName tile) {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_CLICK_QS_TILE, tile).sendToTarget();
+        }
+    }
+
     private final class H extends Handler {
         public void handleMessage(Message msg) {
             final int what = msg.what & MSG_MASK;
@@ -412,6 +441,15 @@
                 case MSG_REQUEST_TV_PICTURE_IN_PICTURE:
                     mCallbacks.requestTvPictureInPicture();
                     break;
+                case MSG_ADD_QS_TILE:
+                    mCallbacks.addQsTile((ComponentName) msg.obj);
+                    break;
+                case MSG_REMOVE_QS_TILE:
+                    mCallbacks.remQsTile((ComponentName) msg.obj);
+                    break;
+                case MSG_CLICK_QS_TILE:
+                    mCallbacks.clickTile((ComponentName) msg.obj);
+                    break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
index d9276bf..3067714 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
@@ -17,14 +17,12 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
-import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
 
 import com.android.systemui.R;
 
 public class DismissView extends StackScrollerDecorView {
-    private boolean mDismissAllInProgress;
     private DismissViewButton mDismissButton;
 
     public DismissView(Context context, AttributeSet attrs) {
@@ -53,27 +51,7 @@
                 || touchY > mContent.getY() + mContent.getHeight();
     }
 
-    public void showClearButton() {
-        mDismissButton.showButton();
-    }
-
-    public void setDismissAllInProgress(boolean dismissAllInProgress) {
-        if (dismissAllInProgress) {
-            setClipBounds(null);
-        }
-        mDismissAllInProgress = dismissAllInProgress;
-    }
-
-    @Override
-    public void setClipBounds(Rect clipBounds) {
-        if (mDismissAllInProgress) {
-            // we don't want any clipping to happen!
-            return;
-        }
-        super.setClipBounds(clipBounds);
-    }
-
     public boolean isButtonVisible() {
-        return mDismissButton.isButtonStatic();
+        return mDismissButton.getAlpha() != 0.0f;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewButton.java
index 46060f1..b608d67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewButton.java
@@ -17,22 +17,13 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
-import android.graphics.Canvas;
 import android.graphics.Rect;
-import android.graphics.drawable.AnimatedVectorDrawable;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.view.View;
 import android.view.ViewGroup;
-import android.widget.Button;
 
-import com.android.systemui.R;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
-public class DismissViewButton extends Button {
-    private AnimatedVectorDrawable mAnimatedDismissDrawable;
-    private final Drawable mStaticDismissDrawable;
-    private Drawable mActiveDrawable;
+public class DismissViewButton extends AlphaOptimizedButton {
 
     public DismissViewButton(Context context) {
         this(context, null);
@@ -49,55 +40,6 @@
     public DismissViewButton(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        mAnimatedDismissDrawable = (AnimatedVectorDrawable) getContext().getDrawable(
-                R.drawable.dismiss_all_shape_animation).mutate();
-        mAnimatedDismissDrawable.setCallback(this);
-        mAnimatedDismissDrawable.setBounds(0,
-                0,
-                mAnimatedDismissDrawable.getIntrinsicWidth(),
-                mAnimatedDismissDrawable.getIntrinsicHeight());
-        mStaticDismissDrawable = getContext().getDrawable(R.drawable.dismiss_all_shape);
-        mStaticDismissDrawable.setBounds(0,
-                0,
-                mStaticDismissDrawable.getIntrinsicWidth(),
-                mStaticDismissDrawable.getIntrinsicHeight());
-        mStaticDismissDrawable.setCallback(this);
-        mActiveDrawable = mStaticDismissDrawable;
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        canvas.save();
-        int drawableHeight = mActiveDrawable.getBounds().height();
-        boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
-        int dx = isRtl ? getWidth() / 2 + drawableHeight / 2 : getWidth() / 2 - drawableHeight / 2;
-        canvas.translate(dx, getHeight() / 2.0f + drawableHeight /
-                2.0f);
-        canvas.scale(isRtl ? -1.0f : 1.0f, -1.0f);
-        mActiveDrawable.draw(canvas);
-        canvas.restore();
-    }
-
-    @Override
-    public boolean performClick() {
-        if (!mAnimatedDismissDrawable.isRunning()) {
-            mActiveDrawable = mAnimatedDismissDrawable;
-            mAnimatedDismissDrawable.start();
-        }
-        return super.performClick();
-    }
-
-    @Override
-    protected boolean verifyDrawable(Drawable who) {
-        return super.verifyDrawable(who)
-                || who == mAnimatedDismissDrawable
-                || who == mStaticDismissDrawable;
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
     }
 
     /**
@@ -118,16 +60,4 @@
         outRect.top += translationY;
         outRect.bottom += translationY;
     }
-
-    public void showButton() {
-        mActiveDrawable = mStaticDismissDrawable;
-        invalidate();
-    }
-
-    /**
-     * @return Whether the button is currently static and not being animated.
-     */
-    public boolean isButtonStatic() {
-        return mActiveDrawable == mStaticDismissDrawable;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 963920c..0b7bfa8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -23,17 +23,15 @@
 import android.content.DialogInterface.OnClickListener;
 import android.os.Handler;
 import android.os.Looper;
-import android.util.DisplayMetrics;
+import android.view.ContextThemeWrapper;
 import android.view.KeyEvent;
 import android.view.KeyboardShortcutGroup;
 import android.view.KeyboardShortcutInfo;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup.LayoutParams;
 import android.view.Window;
 import android.view.WindowManager.KeyboardShortcutsReceiver;
 import android.widget.LinearLayout;
-import android.widget.ScrollView;
 import android.widget.TextView;
 
 import com.android.systemui.R;
@@ -65,7 +63,7 @@
     private Dialog mKeyboardShortcutsDialog;
 
     public KeyboardShortcuts(Context context) {
-        this.mContext = context;
+        this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
     }
 
     public void toggleKeyboardShortcuts() {
@@ -108,40 +106,28 @@
         mHandler.post(new Runnable() {
             @Override
             public void run() {
-                // TODO: break all this code out into a handleShowKeyboard...
-                // Might add more things posted; should consider adding a custom handler so
-                // you can send the keyboardShortcutsGroups as part of the message.
-                AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
-                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
-                        LAYOUT_INFLATER_SERVICE);
-                final View keyboardShortcutsView = inflater.inflate(
-                        R.layout.keyboard_shortcuts_view, null);
-                DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
-                ScrollView scrollView = (ScrollView) keyboardShortcutsView.findViewById(
-                        R.id.keyboard_shortcuts_scroll_view);
-                // TODO: find a better way to set the height.
-                scrollView.setLayoutParams(new LinearLayout.LayoutParams(
-                        LayoutParams.WRAP_CONTENT,
-                        (int) (dm.heightPixels * dm.density)));
-
-                populateKeyboardShortcuts((LinearLayout) keyboardShortcutsView.findViewById(
-                        R.id.keyboard_shortcuts_container), keyboardShortcutGroups);
-                dialogBuilder.setView(keyboardShortcutsView);
-                dialogBuilder.setPositiveButton(R.string.quick_settings_done, dialogCloseListener);
-                mKeyboardShortcutsDialog = dialogBuilder.create();
-                mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
-
-                // Setup window.
-                Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
-                keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
-                keyboardShortcutsWindow.setBackgroundDrawable(
-                        mContext.getDrawable(R.color.ksh_dialog_background_color));
-                keyboardShortcutsWindow.setGravity(TOP);
-                mKeyboardShortcutsDialog.show();
+                handleShowKeyboardShortcuts(keyboardShortcutGroups);
             }
         });
     }
 
+    private void handleShowKeyboardShortcuts(List<KeyboardShortcutGroup> keyboardShortcutGroups) {
+        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                LAYOUT_INFLATER_SERVICE);
+        final View keyboardShortcutsView = inflater.inflate(
+                R.layout.keyboard_shortcuts_view, null);
+        populateKeyboardShortcuts((LinearLayout) keyboardShortcutsView.findViewById(
+                R.id.keyboard_shortcuts_container), keyboardShortcutGroups);
+        dialogBuilder.setView(keyboardShortcutsView);
+        dialogBuilder.setPositiveButton(R.string.quick_settings_done, dialogCloseListener);
+        mKeyboardShortcutsDialog = dialogBuilder.create();
+        mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
+        Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
+        keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
+        mKeyboardShortcutsDialog.show();
+    }
+
     private void populateKeyboardShortcuts(LinearLayout keyboardShortcutsLayout,
             List<KeyboardShortcutGroup> keyboardShortcutGroups) {
         LayoutInflater inflater = LayoutInflater.from(mContext);
@@ -156,36 +142,37 @@
                     : mContext.getColor(R.color.ksh_application_group_color));
             keyboardShortcutsLayout.addView(categoryTitle);
 
-            LinearLayout shortcutWrapper = (LinearLayout) inflater.inflate(
-                    R.layout.keyboard_shortcuts_wrapper, null);
+            LinearLayout shortcutContainer = (LinearLayout) inflater.inflate(
+                    R.layout.keyboard_shortcuts_container, keyboardShortcutsLayout, false);
             final int itemsSize = group.getItems().size();
             for (int j = 0; j < itemsSize; j++) {
                 KeyboardShortcutInfo info = group.getItems().get(j);
-                View shortcutView = inflater.inflate(R.layout.keyboard_shortcut_app_item, null);
+                View shortcutView = inflater.inflate(R.layout.keyboard_shortcut_app_item,
+                        shortcutContainer, false);
                 TextView textView = (TextView) shortcutView
                         .findViewById(R.id.keyboard_shortcuts_keyword);
                 textView.setText(info.getLabel());
 
+                LinearLayout shortcutItemsContainer = (LinearLayout) shortcutView
+                        .findViewById(R.id.keyboard_shortcuts_item_container);
                 List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
                 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, null);
+                            R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer, false);
                     shortcutKeyView.setText(shortcutKey);
-                    LinearLayout shortcutItemsContainer = (LinearLayout) shortcutView
-                            .findViewById(R.id.keyboard_shortcuts_item_container);
                     shortcutItemsContainer.addView(shortcutKeyView);
                 }
-                shortcutWrapper.addView(shortcutView);
+                shortcutContainer.addView(shortcutView);
             }
-
-            // TODO: merge container and wrapper into one xml file - wrapper is always a child of
-            // container.
-            LinearLayout shortcutsContainer = (LinearLayout) inflater.inflate(
-                    R.layout.keyboard_shortcuts_container, null);
-            shortcutsContainer.addView(shortcutWrapper);
-            keyboardShortcutsLayout.addView(shortcutsContainer);
+            keyboardShortcutsLayout.addView(shortcutContainer);
+            if (i < keyboardShortcutGroupsSize - 1) {
+                View separator = inflater.inflate(
+                        R.layout.keyboard_shortcuts_category_separator, keyboardShortcutsLayout,
+                        false);
+                keyboardShortcutsLayout.addView(separator);
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 00b9888..76e522e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -197,9 +197,13 @@
                 if (expandedSize != collapsedSize) {
                     int paddingEnd = contractedHeader.getMeasuredWidth() - expandedSize;
                     contractedHeader.setPadding(
-                            isLayoutRtl() ? paddingEnd : contractedHeader.getPaddingLeft(),
+                            contractedHeader.isLayoutRtl()
+                                    ? paddingEnd
+                                    : contractedHeader.getPaddingLeft(),
                             contractedHeader.getPaddingTop(),
-                            isLayoutRtl() ? contractedHeader.getPaddingLeft() : paddingEnd,
+                            contractedHeader.isLayoutRtl()
+                                    ? contractedHeader.getPaddingLeft()
+                                    : paddingEnd,
                             contractedHeader.getPaddingBottom());
                     contractedHeader.setShowWorkBadgeAtEnd(true);
                     return true;
@@ -208,9 +212,13 @@
                 int paddingEnd = mNotificationContentMarginEnd;
                 if (contractedHeader.getPaddingEnd() != paddingEnd) {
                     contractedHeader.setPadding(
-                            isLayoutRtl() ? paddingEnd : contractedHeader.getPaddingLeft(),
+                            contractedHeader.isLayoutRtl()
+                                    ? paddingEnd
+                                    : contractedHeader.getPaddingLeft(),
                             contractedHeader.getPaddingTop(),
-                            isLayoutRtl() ? contractedHeader.getPaddingLeft() : paddingEnd,
+                            contractedHeader.isLayoutRtl()
+                                    ? contractedHeader.getPaddingLeft()
+                                    : paddingEnd,
                             contractedHeader.getPaddingBottom());
                     contractedHeader.setShowWorkBadgeAtEnd(false);
                     return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 98a37f9..c70aad2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -74,8 +74,7 @@
         }
 
         private void applyToChild(View view, boolean shouldApply, int originalColor) {
-            if (view.getVisibility() == View.VISIBLE
-                    && originalColor != NotificationHeaderView.NO_COLOR) {
+            if (originalColor != NotificationHeaderView.NO_COLOR) {
                 ImageView imageView = (ImageView) view;
                 imageView.getDrawable().mutate();
                 if (shouldApply) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
new file mode 100644
index 0000000..f9afc7c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
@@ -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.
+ */
+
+package com.android.systemui.statusbar;
+
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import android.content.Context;
+import android.content.DialogInterface;
+
+import com.android.systemui.R;
+
+public class UserUtil {
+    public static void deleteUserWithPrompt(Context context, int userId,
+                                            UserSwitcherController userSwitcherController) {
+        new RemoveUserDialog(context, userId, userSwitcherController).show();
+    }
+
+    private final static class RemoveUserDialog extends SystemUIDialog implements
+            DialogInterface.OnClickListener {
+
+        private final int mUserId;
+        private final UserSwitcherController mUserSwitcherController;
+
+        public RemoveUserDialog(Context context, int userId,
+                                UserSwitcherController userSwitcherController) {
+            super(context);
+            setTitle(R.string.user_remove_user_title);
+            setMessage(context.getString(R.string.user_remove_user_message));
+            setButton(DialogInterface.BUTTON_NEGATIVE,
+                    context.getString(android.R.string.cancel), this);
+            setButton(DialogInterface.BUTTON_POSITIVE,
+                    context.getString(R.string.user_remove_user_remove), this);
+            setCanceledOnTouchOutside(false);
+            mUserId = userId;
+            mUserSwitcherController = userSwitcherController;
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            if (which == BUTTON_NEGATIVE) {
+                cancel();
+            } else {
+                dismiss();
+                mUserSwitcherController.removeUserId(mUserId);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
index 28f4e05..2294931 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.car;
 
 import android.content.Context;
-import android.content.DialogInterface;
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -29,8 +28,8 @@
 import android.widget.TextView;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.UserUtil;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 public class UserGridView extends GridView {
@@ -88,7 +87,8 @@
                     return true;
                 }
 
-                new RemoveUserDialog(getContext(), record.info.id).show();
+                UserUtil.deleteUserWithPrompt(getContext(), record.info.id,
+                        mUserSwitcherController);
                 return true;
             }
         });
@@ -159,32 +159,4 @@
             return convertView;
         }
     }
-
-    private final class RemoveUserDialog extends SystemUIDialog implements
-            DialogInterface.OnClickListener {
-
-        private final int mUserId;
-
-        public RemoveUserDialog(Context context, int userId) {
-            super(context);
-            setTitle(R.string.user_remove_user_title);
-            setMessage(context.getString(R.string.user_remove_user_message));
-            setButton(DialogInterface.BUTTON_NEGATIVE,
-                    context.getString(android.R.string.cancel), this);
-            setButton(DialogInterface.BUTTON_POSITIVE,
-                    context.getString(R.string.user_remove_user_remove), this);
-            setCanceledOnTouchOutside(false);
-            mUserId = userId;
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            if (which == BUTTON_NEGATIVE) {
-                cancel();
-            } else {
-                dismiss();
-                mUserSwitcherController.removeUserId(mUserId);
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
index ec73935..81144d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
@@ -107,12 +107,13 @@
 
     public void bind(CharSequence title, CharSequence text) {
         mTitleView.setText(title);
-        if (TextUtils.isEmpty(title)) {
-            mTitleView.setVisibility(GONE);
-        }
-        mTextView.setText(text);
+        mTitleView.setVisibility(TextUtils.isEmpty(title) ? GONE : VISIBLE);
         if (TextUtils.isEmpty(text)) {
             mTextView.setVisibility(GONE);
+            mTextView.setText(null);
+        } else {
+            mTextView.setVisibility(VISIBLE);
+            mTextView.setText(text.toString());
         }
         requestLayout();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java
index 285d53f..28bb66f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java
@@ -18,8 +18,13 @@
 
 import android.app.Notification;
 import android.content.Context;
+import android.text.BidiFormatter;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
+import android.text.style.TextAppearanceSpan;
 import android.view.LayoutInflater;
+import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.systemui.R;
@@ -34,12 +39,12 @@
 
     private final Context mContext;
     private ViewGroup mParent;
-    private String mConcadenationString;
+    private String mDivider;
 
     public HybridNotificationViewManager(Context ctx, ViewGroup parent) {
         mContext = ctx;
         mParent = parent;
-        mConcadenationString = mContext.getString(R.string.group_summary_concadenation);
+        mDivider = " • ";
     }
 
     private HybridNotificationView inflateHybridView() {
@@ -83,7 +88,7 @@
         if (reusableView == null) {
             reusableView = inflateHybridView();
         }
-        CharSequence summary = null;
+        SpannableStringBuilder summary = new SpannableStringBuilder();
         int childCount = group.size();
         for (int i = startIndex; i < childCount; i++) {
             ExpandableNotificationRow child = group.get(i);
@@ -92,15 +97,18 @@
             if (titleText == null) {
                 continue;
             }
-            if (TextUtils.isEmpty(summary)) {
-                summary = titleText;
-            } else if (reusableView.isLayoutRtl()) {
-                summary = titleText + mConcadenationString + summary;
-            } else {
-                summary = summary + mConcadenationString + titleText;
+            if (!TextUtils.isEmpty(summary)) {
+                summary.append(mDivider,
+                        new TextAppearanceSpan(mContext, R.style.
+                                TextAppearance_Material_Notification_HybridNotificationDivider),
+                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
             }
+            summary.append(BidiFormatter.getInstance().unicodeWrap(titleText));
         }
-        reusableView.bind(summary);
+        // We want to force the same orientation as the layout RTL mode
+        BidiFormatter formater = BidiFormatter.getInstance(
+                reusableView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
+        reusableView.bind(formater.unicodeWrap(summary));
         return reusableView;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
new file mode 100644
index 0000000..487a7a0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.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.statusbar.notification;
+
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.view.View;
+
+import com.android.internal.widget.ImageFloatingTextView;
+import com.android.systemui.statusbar.TransformableView;
+
+/**
+ * Wraps a notification containing a big text template
+ */
+public class NotificationBigTextTemplateViewWrapper extends NotificationTemplateViewWrapper {
+
+    private ImageFloatingTextView mBigtext;
+
+    protected NotificationBigTextTemplateViewWrapper(Context ctx, View view) {
+        super(ctx, view);
+    }
+
+    private void resolveViews(StatusBarNotification notification) {
+        mBigtext = (ImageFloatingTextView) mView.findViewById(com.android.internal.R.id.big_text);
+    }
+
+    @Override
+    public void notifyContentUpdated(StatusBarNotification notification) {
+        // Reinspect the notification. Before the super call, because the super call also updates
+        // the transformation types and we need to have our values set by then.
+        resolveViews(notification);
+        super.notifyContentUpdated(notification);
+    }
+
+    @Override
+    protected void updateTransformedTypes() {
+        // This also clears the existing types
+        super.updateTransformedTypes();
+        if (mBigtext != null) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
+                    mBigtext);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index b060245..0c21f0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -55,11 +55,12 @@
                         }
                         TransformState otherState = notification.getCurrentState(
                                 TRANSFORMING_VIEW_TITLE);
-                        CrossFadeHelper.fadeOut(mText, endRunnable);
+                        final View text = ownState.getTransformedView();
+                        CrossFadeHelper.fadeOut(text, endRunnable);
                         if (otherState != null) {
                             int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
                             int[] ownPosition = ownState.getLaidOutLocationOnScreen();
-                            mText.animate()
+                            text.animate()
                                     .translationY((otherStablePosition[1]
                                             + otherState.getTransformedView().getHeight()
                                             - ownPosition[1]) * 0.33f)
@@ -72,11 +73,11 @@
                                             if (endRunnable != null) {
                                                 endRunnable.run();
                                             }
-                                            TransformState.setClippingDeactivated(mText,
+                                            TransformState.setClippingDeactivated(text,
                                                     false);
                                         }
                                     });
-                            TransformState.setClippingDeactivated(mText, true);
+                            TransformState.setClippingDeactivated(text, true);
                             otherState.recycle();
                         }
                         return true;
@@ -90,17 +91,18 @@
                         }
                         TransformState otherState = notification.getCurrentState(
                                 TRANSFORMING_VIEW_TITLE);
-                        boolean isVisible = mText.getVisibility() == View.VISIBLE;
-                        CrossFadeHelper.fadeIn(mText);
+                        final View text = ownState.getTransformedView();
+                        boolean isVisible = text.getVisibility() == View.VISIBLE;
+                        CrossFadeHelper.fadeIn(text);
                         if (otherState != null) {
                             int[] otherStablePosition = otherState.getLaidOutLocationOnScreen();
                             int[] ownStablePosition = ownState.getLaidOutLocationOnScreen();
                             if (!isVisible) {
-                                mText.setTranslationY((otherStablePosition[1]
+                                text.setTranslationY((otherStablePosition[1]
                                         + otherState.getTransformedView().getHeight()
                                         - ownStablePosition[1]) * 0.33f);
                             }
-                            mText.animate()
+                            text.animate()
                                     .translationY(0)
                                     .setDuration(
                                             StackStateAnimator.ANIMATION_DURATION_STANDARD)
@@ -108,11 +110,11 @@
                                     .withEndAction(new Runnable() {
                                         @Override
                                         public void run() {
-                                            TransformState.setClippingDeactivated(mText,
+                                            TransformState.setClippingDeactivated(text,
                                                     false);
                                         }
                                     });
-                            TransformState.setClippingDeactivated(mText, true);
+                            TransformState.setClippingDeactivated(text, true);
                             otherState.recycle();
                         }
                         return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index f50b976..a2b4c5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -37,6 +37,8 @@
         if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
             if ("bigPicture".equals(v.getTag())) {
                 return new NotificationBigPictureTemplateViewWrapper(ctx, v);
+            } else if ("bigText".equals(v.getTag())) {
+                return new NotificationBigTextTemplateViewWrapper(ctx, v);
             }
             return new NotificationTemplateViewWrapper(ctx, v);
         } else if (v instanceof NotificationHeaderView) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
index 9a94d34..eade2a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BaseStatusBarHeader.java
@@ -35,6 +35,7 @@
 
     public abstract int getCollapsedHeight();
     public abstract int getExpandedHeight();
+
     public abstract void setExpanded(boolean b);
     public abstract void setExpansion(float headerExpansionFraction);
     public abstract void setListening(boolean listening);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index a2586f1..bb03454 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -304,8 +304,7 @@
     public void onTuningChanged(String key, String newValue) {
         switch (key) {
             case KEY_DOCK_WINDOW_GESTURE:
-                mDockWindowEnabled = (newValue == null) ||
-                        (Integer.parseInt(newValue) != 0);
+                mDockWindowEnabled = newValue != null && (Integer.parseInt(newValue) != 0);
                 break;
         }
     }
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 9359301..d625fc2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -27,7 +27,6 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.Space;
-
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.KeyButtonView;
 import com.android.systemui.tuner.TunerService;
@@ -58,8 +57,9 @@
     public static final String KEY_IMAGE_DELIM = ":";
     public static final String KEY_CODE_END = ")";
 
-    protected final LayoutInflater mLayoutInflater;
-    protected final LayoutInflater mLandscapeInflater;
+    protected LayoutInflater mLayoutInflater;
+    protected LayoutInflater mLandscapeInflater;
+    private int mDensity;
 
     protected FrameLayout mRot0;
     protected FrameLayout mRot90;
@@ -69,11 +69,27 @@
 
     public NavigationBarInflaterView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mLayoutInflater = LayoutInflater.from(context);
+        mDensity = context.getResources().getConfiguration().densityDpi;
+        createInflaters();
+    }
+
+    private void createInflaters() {
+        mLayoutInflater = LayoutInflater.from(mContext);
         Configuration landscape = new Configuration();
-        landscape.setTo(context.getResources().getConfiguration());
+        landscape.setTo(mContext.getResources().getConfiguration());
         landscape.orientation = Configuration.ORIENTATION_LANDSCAPE;
-        mLandscapeInflater = LayoutInflater.from(context.createConfigurationContext(landscape));
+        mLandscapeInflater = LayoutInflater.from(mContext.createConfigurationContext(landscape));
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (mDensity != newConfig.densityDpi) {
+            mDensity = newConfig.densityDpi;
+            createInflaters();
+            clearViews();
+            inflateLayout(mCurrentLayout);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 3130eb9..d3681b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -154,10 +154,14 @@
         }
         mBarState = newState;
         if (mBarState == StatusBarState.KEYGUARD) {
-            for (NotificationGroup group : mGroupMap.values()) {
-                if (group.expanded) {
-                    setGroupExpanded(group, false);
-                }
+            collapseAllGroups();
+        }
+    }
+
+    public void collapseAllGroups() {
+        for (NotificationGroup group : mGroupMap.values()) {
+            if (group.expanded) {
+                setGroupExpanded(group, false);
             }
         }
     }
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 277668f..f822bd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -39,8 +39,6 @@
 import android.view.ViewTreeObserver;
 import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
@@ -93,7 +91,7 @@
     public static final long DOZE_ANIMATION_DURATION = 700;
 
     private KeyguardAffordanceHelper mAfforanceHelper;
-    private BaseStatusBarHeader mHeader;
+    protected BaseStatusBarHeader mHeader;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
     private KeyguardStatusBarView mKeyguardStatusBar;
     private QSContainer mQsContainer;
@@ -212,10 +210,6 @@
         }
     };
 
-    /** Interpolator to be used for animations that respond directly to a touch */
-    private final Interpolator mTouchResponseInterpolator =
-            new PathInterpolator(0.3f, 0f, 0.1f, 1f);
-
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setWillNotDraw(!DEBUG);
@@ -1447,7 +1441,7 @@
         mScrollView.setBlockFlinging(true);
         ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
         if (isClick) {
-            animator.setInterpolator(mTouchResponseInterpolator);
+            animator.setInterpolator(Interpolators.TOUCH_RESPONSE);
             animator.setDuration(368);
         } else {
             mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
@@ -2404,7 +2398,7 @@
         setVerticalPanelTranslation(0f);
     }
 
-    private void setVerticalPanelTranslation(float translation) {
+    protected void setVerticalPanelTranslation(float translation) {
         mNotificationStackScroller.setTranslationX(translation);
         mScrollView.setTranslationX(translation);
         mHeader.setTranslationX(translation);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index cbb71c5..fd28b09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.util.AttributeSet;
 import android.view.View;
@@ -55,6 +56,20 @@
     }
 
     @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        reloadWidth(mScrollView);
+        reloadWidth(mStackScroller);
+    }
+
+    private void reloadWidth(View view) {
+        LayoutParams params = (LayoutParams) view.getLayoutParams();
+        params.width = getContext().getResources().getDimensionPixelSize(
+                R.dimen.notification_panel_width);
+        view.setLayoutParams(params);
+    }
+
+    @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
         return insets;
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 7e7a948..4dee51d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -29,6 +29,7 @@
 import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -117,7 +118,10 @@
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.UndockingTaskEvent;
 import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.WindowManagerProxy;
 import com.android.systemui.statusbar.ActivatableNotificationView;
 import com.android.systemui.statusbar.BackDropView;
 import com.android.systemui.statusbar.BaseStatusBar;
@@ -794,7 +798,7 @@
                 mKeyguardBottomArea.getLockIcon());
         mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
 
-        // set the inital view visibility
+        // set the initial view visibility
         setAreThereNotifications();
 
         mIconController = new StatusBarIconController(
@@ -1111,26 +1115,25 @@
         @Override
         public boolean onLongClick(View v) {
             if (mRecents != null) {
-                Point realSize = new Point();
-                mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
-                        .getRealSize(realSize);
-                Rect initialBounds;
-
-                // Hack level over 9000: Make it one pixel smaller so activity manager doesn't
-                // dismiss it immediately again. Remove once b/26777526 is fixed.
-                if (mContext.getResources().getConfiguration().orientation
-                        == Configuration.ORIENTATION_LANDSCAPE) {
-                    initialBounds = new Rect(0, 0, realSize.x - 1, realSize.y);
+                int dockSide = WindowManagerProxy.getInstance().getDockSide();
+                if (dockSide == WindowManager.DOCKED_INVALID) {
+                    Point realSize = new Point();
+                    mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
+                            .getRealSize(realSize);
+                    Rect initialBounds= new Rect(0, 0, realSize.x, realSize.y);
+                    boolean docked = mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
+                            ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
+                            initialBounds);
+                    if (docked) {
+                        MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS);
+                        return true;
+                    }
                 } else {
-                    initialBounds = new Rect(0, 0, realSize.x, realSize.y - 1);
-                }
-                boolean docked = mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
-                        ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
-                        initialBounds);
-                if (docked) {
-                    MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS);
+                    EventBus.getDefault().send(new UndockingTaskEvent());
+                    MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
                     return true;
                 }
+
             }
             return false;
         }
@@ -1525,6 +1528,21 @@
         }
     }
 
+    @Override
+    public void addQsTile(ComponentName tile) {
+        mQSPanel.getHost().addTile(tile);
+    }
+
+    @Override
+    public void remQsTile(ComponentName tile) {
+        mQSPanel.getHost().removeTile(tile);
+    }
+
+    @Override
+    public void clickTile(ComponentName tile) {
+        mQSPanel.clickTile(tile);
+    }
+
     private boolean packageHasVisibilityOverride(String key) {
         return mNotificationData.getVisibilityOverride(key)
                 != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
@@ -2323,8 +2341,6 @@
 
     }
 
-    Animator mScrollViewAnim, mClearButtonAnim;
-
     @Override
     public void animateExpandNotificationsPanel() {
         if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 8e2d828..4393e75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -18,13 +18,17 @@
 
 import android.app.ActivityManager;
 import android.app.PendingIntent;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Process;
+import android.os.UserHandle;
 import android.provider.Settings;
+import android.provider.Settings.Secure;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
@@ -32,6 +36,7 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.external.CustomTile;
+import com.android.systemui.qs.external.TileLifecycleManager;
 import com.android.systemui.qs.external.TileServices;
 import com.android.systemui.qs.tiles.AirplaneModeTile;
 import com.android.systemui.qs.tiles.BatteryTile;
@@ -336,6 +341,51 @@
                 TextUtils.join(",", specs), ActivityManager.getCurrentUser());
     }
 
+    public void addTile(ComponentName tile) {
+        List<String> newSpecs = new ArrayList<>(mTileSpecs);
+        newSpecs.add(0, CustomTile.toSpec(tile));
+        changeTiles(mTileSpecs, newSpecs);
+    }
+
+    public void removeTile(ComponentName tile) {
+        List<String> newSpecs = new ArrayList<>(mTileSpecs);
+        newSpecs.remove(CustomTile.toSpec(tile));
+        changeTiles(mTileSpecs, newSpecs);
+    }
+
+    public void changeTiles(List<String> previousTiles, List<String> newTiles) {
+        final int NP = previousTiles.size();
+        final int NA = newTiles.size();
+        for (int i = 0; i < NP; i++) {
+            String tileSpec = previousTiles.get(i);
+            if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
+            if (!newTiles.contains(tileSpec)) {
+                Intent intent = new Intent().setComponent(
+                        CustomTile.getComponentFromSpec(tileSpec));
+                TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
+                        mContext, intent, new UserHandle(ActivityManager.getCurrentUser()));
+                lifecycleManager.onStopListening();
+                lifecycleManager.onTileRemoved();
+                lifecycleManager.flushMessagesAndUnbind();
+            }
+        }
+        for (int i = 0; i < NA; i++) {
+            String tileSpec = newTiles.get(i);
+            if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
+            if (!previousTiles.contains(tileSpec)) {
+                Intent intent = new Intent().setComponent(
+                        CustomTile.getComponentFromSpec(tileSpec));
+                TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
+                        mContext, intent, new UserHandle(ActivityManager.getCurrentUser()));
+                lifecycleManager.onTileAdded();
+                lifecycleManager.flushMessagesAndUnbind();
+            }
+        }
+        if (DEBUG) Log.d(TAG, "saveCurrentTiles " + newTiles);
+        Secure.putStringForUser(getContext().getContentResolver(), QSTileHost.TILES_SETTING,
+                TextUtils.join(",", newTiles), ActivityManager.getCurrentUser());
+    }
+
     public QSTile<?> createTile(String tileSpec) {
         if (tileSpec.equals("wifi")) return WifiTile.isSupported(this)
                 ? new WifiTile(this) : null;
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 9aeb1f8..fe46385 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -31,7 +31,6 @@
 import android.widget.Switch;
 import android.widget.TextView;
 import android.widget.Toast;
-
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSPanel;
@@ -74,6 +73,9 @@
     private float mDateTimeTranslation;
     private MultiUserSwitch mMultiUserSwitch;
     private ImageView mMultiUserAvatar;
+    private View mQsDetailHeaderBack;
+
+    private final int[] mTmpInt2 = new int[2];
 
     public QuickStatusBarHeader(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -87,6 +89,7 @@
         mDateTimeTranslation = mContext.getResources().getDimension(
                 R.dimen.qs_date_anim_translation);
         mDateTimeGroup = (ViewGroup) findViewById(R.id.date_time_group);
+        mDateTimeGroup.findViewById(R.id.empty_time_view).setVisibility(View.GONE);
         mExpandedGroup = (ViewGroup) findViewById(R.id.expanded_group);
 
         mHeaderQsPanel = (QuickQSPanel) findViewById(R.id.quick_qs_panel);
@@ -100,6 +103,7 @@
 
         mQsDetailHeader = findViewById(R.id.qs_detail_header);
         mQsDetailHeader.setAlpha(0);
+        mQsDetailHeaderBack = mQsDetailHeader.findViewById(com.android.internal.R.id.up);
         mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
         mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
         mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
@@ -367,6 +371,15 @@
                         }
                     });
                 }
+                mQsDetailHeaderBack.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        v.getLocationInWindow(mTmpInt2);
+                        mTmpInt2[0] += v.getWidth() / 2;
+                        mTmpInt2[1] += v.getHeight() / 2;
+                        mQsPanel.showDetailAdapter(false, null, mTmpInt2);
+                    }
+                });
             } else {
                 mQsDetailHeader.setClickable(false);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 9996b75..45aae2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -30,12 +30,12 @@
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.TypedValue;
+import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
-
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.FontSizeUtils;
@@ -226,12 +226,25 @@
 
     public void setExternalIcon(String slot) {
         int viewIndex = getViewIndex(getSlotIndex(slot));
+        int height = mContext.getResources().getDimensionPixelSize(
+                R.dimen.status_bar_icon_drawing_size);
         ImageView imageView = (ImageView) mStatusIcons.getChildAt(viewIndex);
         imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
         imageView.setAdjustViewBounds(true);
+        setHeightAndCenter(imageView, height);
         imageView = (ImageView) mStatusIconsKeyguard.getChildAt(viewIndex);
         imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
         imageView.setAdjustViewBounds(true);
+        setHeightAndCenter(imageView, height);
+    }
+
+    private void setHeightAndCenter(ImageView imageView, int height) {
+        ViewGroup.LayoutParams params = imageView.getLayoutParams();
+        params.height = height;
+        if (params instanceof LinearLayout.LayoutParams) {
+            ((LinearLayout.LayoutParams) params).gravity = Gravity.CENTER_VERTICAL;
+        }
+        imageView.setLayoutParams(params);
     }
 
     public void setIcon(String slot, StatusBarIcon icon) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
index b036936..500d603 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
@@ -20,7 +20,6 @@
     void addCallback(Callback callback);
     void removeCallback(Callback callback);
     boolean isHotspotEnabled();
-    boolean isHotspotSupported();
     void setHotspotEnabled(boolean enabled);
     boolean isTetheringAllowed();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 61d26c7..07b7409 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -27,8 +27,6 @@
 import android.os.UserManager;
 import android.util.Log;
 
-import com.android.settingslib.TetherUtil;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -98,11 +96,6 @@
     }
 
     @Override
-    public boolean isHotspotSupported() {
-        return TetherUtil.isTetheringSupported(mContext);
-    }
-
-    @Override
     public boolean isTetheringAllowed() {
         return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING,
                 UserHandle.of(mCurrentUser));
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 409dac1..5cfcd89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.stack;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -58,6 +59,7 @@
     private HybridNotificationView mGroupOverflowContainer;
     private ViewState mGroupOverFlowState;
     private int mRealHeight;
+    private int mLayoutDirection = LAYOUT_DIRECTION_UNDEFINED;
 
     public NotificationChildrenContainer(Context context) {
         this(context, null);
@@ -209,6 +211,16 @@
         }
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        int layoutDirection = getLayoutDirection();
+        if (layoutDirection != mLayoutDirection) {
+            updateGroupOverflow();
+            mLayoutDirection = layoutDirection;
+        }
+    }
+
     private View inflateDivider() {
         return LayoutInflater.from(mContext).inflate(
                 R.layout.notification_children_divider, this, false);
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 d6276b8..cc0e67d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1648,6 +1648,9 @@
                 bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight());
                 bottom = Math.min(bottom, getHeight());
             }
+        } else if (mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+            top = mTopPadding;
+            bottom = top;
         }
         mBackgroundBounds.top = Math.max(0, top);
         mBackgroundBounds.bottom = Math.min(getHeight(), bottom);
@@ -2093,12 +2096,6 @@
         generateAddAnimation(child, false /* fromMoreCard */);
         updateAnimationState(child);
         updateChronometerForChild(child);
-        if (canChildBeDismissed(child)) {
-            // Make sure the dismissButton is visible and not in the animated state.
-            // We need to do this to avoid a race where a clearable notification is added after the
-            // dismiss animation is finished
-            mDismissView.showClearButton();
-        }
     }
 
     private void updateHideSensitiveForChild(View child) {
@@ -2608,6 +2605,9 @@
         mIsExpanded = isExpanded;
         mStackScrollAlgorithm.setIsExpanded(isExpanded);
         if (changed) {
+            if (!mIsExpanded) {
+                mGroupManager.collapseAllGroups();
+            }
             updateNotificationAnimationStates();
             updateChronometers();
         }
@@ -2977,7 +2977,6 @@
                     mDismissView.performVisibilityAnimation(false, dimissHideFinishRunnable);
                 } else {
                     dimissHideFinishRunnable.run();
-                    mDismissView.showClearButton();
                 }
             }
         }
@@ -2985,7 +2984,6 @@
 
     public void setDismissAllInProgress(boolean dismissAllInProgress) {
         mDismissAllInProgress = dismissAllInProgress;
-        mDismissView.setDismissAllInProgress(dismissAllInProgress);
         mAmbientState.setDismissAllInProgress(dismissAllInProgress);
         if (dismissAllInProgress) {
             disableClipOptimization();
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 f322348..784f610 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.tv;
 
+import android.content.ComponentName;
 import android.os.IBinder;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
@@ -79,10 +80,6 @@
             boolean showImeSwitcher) {
     }
 
-    @Override
-    public void toggleRecentApps() {
-    }
-
     @Override // CommandQueue
     public void setWindowState(int window, int state) {
     }
@@ -187,4 +184,16 @@
     protected boolean isSnoozedPackage(StatusBarNotification sbn) {
         return false;
     }
+
+    @Override
+    public void addQsTile(ComponentName tile) {
+    }
+
+    @Override
+    public void remQsTile(ComponentName tile) {
+    }
+
+    @Override
+    public void clickTile(ComponentName tile) {
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
index 7b06393..d8cf2e2 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
@@ -56,7 +56,7 @@
     }
 
     @Override
-    protected State newTileState() {
+    public State newTileState() {
         return new State();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index f298e16..e0a1547 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -25,12 +25,15 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
@@ -40,6 +43,7 @@
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 import java.util.HashMap;
@@ -50,6 +54,10 @@
 
     public static final String ACTION_CLEAR = "com.android.systemui.action.CLEAR_TUNER";
 
+    private static final String TUNER_VERSION = "sysui_tuner_version";
+
+    private static final int CURRENT_TUNER_VERSION = 1;
+
     private final Observer mObserver = new Observer();
     // Map of Uris we listen on to their settings keys.
     private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
@@ -63,6 +71,13 @@
     @Override
     public void start() {
         mContentResolver = mContext.getContentResolver();
+
+        for (UserInfo user : UserManager.get(mContext).getUsers()) {
+            mCurrentUser = user.getUserHandle().getIdentifier();
+            if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) {
+                upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION);
+            }
+        }
         putComponent(TunerService.class, this);
 
         mCurrentUser = ActivityManager.getCurrentUser();
@@ -77,6 +92,24 @@
         mUserTracker.startTracking();
     }
 
+    private void upgradeTuner(int oldVersion, int newVersion) {
+        if (oldVersion < 1) {
+            String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
+            if (blacklistStr != null) {
+                ArraySet<String> iconBlacklist =
+                        StatusBarIconController.getIconBlacklist(blacklistStr);
+
+                iconBlacklist.add("rotate");
+                iconBlacklist.add("headset");
+
+                Settings.Secure.putStringForUser(mContentResolver,
+                        StatusBarIconController.ICON_BLACKLIST,
+                        TextUtils.join(",", iconBlacklist), mCurrentUser);
+            }
+        }
+        setValue(TUNER_VERSION, newVersion);
+    }
+
     public String getValue(String setting) {
         return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
     }
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 6febe5f..3e47d85 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -32,11 +32,14 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.systemui.Prefs;
+
 import java.util.ArrayList;
 import java.util.List;
 
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static com.android.systemui.Prefs.Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN;
 
 /**
  * Manages the picture-in-picture (PIP) UI and states.
@@ -44,6 +47,7 @@
 public class PipManager {
     private static final String TAG = "PipManager";
     private static final boolean DEBUG = false;
+    private static final boolean DEBUG_FORCE_ONBOARDING = false;
 
     private static PipManager sPipManager;
 
@@ -65,6 +69,7 @@
     private Rect mMenuModePipBound;
     private boolean mInitialized;
     private int mPipTaskId = TASK_ID_NO_PIP;
+    private boolean mOnboardingShown;
 
     private final Runnable mOnActivityPinnedRunnable = new Runnable() {
         @Override
@@ -83,6 +88,7 @@
             if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
             mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
             showPipOverlay(false);
+            launchPipOnboardingActivityIfNeeded();
         }
     };
     private final Runnable mOnTaskStackChanged = new Runnable() {
@@ -145,6 +151,8 @@
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
         mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+        mOnboardingShown = Prefs.getBoolean(
+                mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, false);
     }
 
     /**
@@ -169,7 +177,7 @@
     }
 
     /**
-     * Closes PIP (PIPped activity and PIP system UI).
+     * Closes PIP (PIPed activity and PIP system UI).
      */
     public void closePip() {
         mState = STATE_NO_PIP;
@@ -194,7 +202,7 @@
     }
 
     /**
-     * Moves the PIPped activity to the fullscreen and closes PIP system UI.
+     * Moves the PIPed activity to the fullscreen and closes PIP system UI.
      */
     public void movePipToFullscreen() {
         mState = STATE_NO_PIP;
@@ -260,6 +268,17 @@
         mListeners.remove(listener);
     }
 
+    private void launchPipOnboardingActivityIfNeeded() {
+        if (DEBUG_FORCE_ONBOARDING || !mOnboardingShown) {
+            mOnboardingShown = true;
+            Prefs.putBoolean(mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, true);
+
+            Intent intent = new Intent(mContext, PipOnboardingActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mContext.startActivity(intent);
+        }
+    }
+
     private boolean hasPipTasks() {
         try {
             StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
@@ -334,7 +353,7 @@
      */
     public interface Listener {
         /**
-         * Invoked when a PIPped activity is closed.
+         * Invoked when a PIPed activity is closed.
          */
         void onPipActivityClosed();
         /**
@@ -342,7 +361,7 @@
          */
         void onShowPipMenu();
         /**
-         * Invoked when the PIPped activity is returned back to the fullscreen.
+         * Invoked when the PIPed activity is returned back to the fullscreen.
          */
         void onMoveToFullscreen();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
new file mode 100644
index 0000000..a0b913a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+
+import com.android.systemui.R;
+
+/**
+ * Activity to show an overlay on top of PIP activity to show how to pop up PIP menu.
+ */
+public class PipOnboardingActivity extends Activity implements PipManager.Listener {
+    private final PipManager mPipManager = PipManager.getInstance();
+
+    @Override
+    protected void onCreate(Bundle bundle) {
+        super.onCreate(bundle);
+        setContentView(R.layout.tv_pip_onboarding);
+        mPipManager.addListener(this);
+        findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                finish();
+            }
+        });
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mPipManager.removeListener(this);
+    }
+
+    @Override
+    public void onPipActivityClosed() {
+        finish();
+    }
+
+    @Override
+    public void onShowPipMenu() {
+        finish();
+    }
+
+    @Override
+    public void onMoveToFullscreen() {
+        finish();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java
index 4586c28..efdb50d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java
@@ -91,7 +91,7 @@
         mTileServiceManager.calculateBindPriority(0);
         // Priority shouldn't disappear after the request goes away if we just bound, instead
         // it sticks around to avoid thrashing a bunch of processes.
-        assertEquals(Integer.MAX_VALUE - 1, mTileServiceManager.getBindPriority());
+        assertEquals(Integer.MAX_VALUE - 2, mTileServiceManager.getBindPriority());
 
         mTileServiceManager.setBindAllowed(false);
         captor = ArgumentCaptor.forClass(Boolean.class);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 697777c..e1dd87f 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -342,5 +342,15 @@
 
     // QS Tile for Data Saver.
     QS_DATA_SAVER = 284;
+
+    // OPEN: Settings > Security > User credentials
+    // CATEGORY: Settings
+    // OS: 6.1
+    // GMS: 7.8.99
+    USER_CREDENTIALS = 285;
+
+    // Logged when the user undocks a previously docked window by long pressing recents while in
+    // docked mode.
+    ACTION_WINDOW_UNDOCK_LONGPRESS = 286;
   }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
index e310801..b79a7ba 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
@@ -25,8 +25,11 @@
 import android.gesture.GestureStroke;
 import android.gesture.Prediction;
 import android.util.Slog;
+import android.util.TypedValue;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.ViewConfiguration;
 
 import com.android.internal.R;
 
@@ -46,7 +49,9 @@
     public interface Listener {
         public void onDoubleTapAndHold(MotionEvent event, int policyFlags);
         public boolean onDoubleTap(MotionEvent event, int policyFlags);
-        public boolean onGesture(int gestureId);
+        public boolean onGestureCompleted(int gestureId);
+        public void onGestureStarted();
+        public void onGestureCancelled(MotionEvent event, int policyFlags);
     }
 
     private final Listener mListener;
@@ -64,6 +69,10 @@
     // Indicates that motion events are being collected to match a gesture.
     private boolean mRecognizingGesture;
 
+    // Indicates that we've collected enough data to be sure it could be a
+    // gesture.
+    private boolean mGestureStarted;
+
     // Indicates that motion events from the second pointer are being checked
     // for a double tap.
     private boolean mSecondFingerDoubleTap;
@@ -75,11 +84,22 @@
     // Policy flags of the previous event.
     private int mPolicyFlags;
 
-    // The X of the previous event.
-    private float mPreviousX;
+    // These values track the previous point that was saved to use for gesture
+    // detection.  They are only updated when the user moves more than the
+    // recognition threshold.
+    private float mPreviousGestureX;
+    private float mPreviousGestureY;
 
-    // The Y of the previous event.
-    private float mPreviousY;
+    // These values track the previous point that was used to determine if there
+    // was a transition into or out of gesture detection.  They are updated when
+    // the user moves more than the detection threshold.
+    private float mBaseX;
+    private float mBaseY;
+    private long mBaseTime;
+
+    // This is the calculated movement threshold used track if the user is still
+    // moving their finger.
+    private final float mGestureDetectionThreshold;
 
     // Buffer for storing points for gesture detection.
     private final ArrayList<GesturePoint> mStrokeBuffer = new ArrayList<GesturePoint>(100);
@@ -90,6 +110,10 @@
     // The minimal score for accepting a predicted gesture.
     private static final float MIN_PREDICTION_SCORE = 2.0f;
 
+    private static final int GESTURE_CONFIRM_MM = 10;
+    private static final long CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS = 1000;
+    private static final long CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS = 500;
+
     AccessibilityGestureDetector(Context context, Listener listener) {
         mListener = listener;
 
@@ -100,11 +124,15 @@
         mGestureLibrary.setOrientationStyle(8 /* GestureStore.ORIENTATION_SENSITIVE_8 */);
         mGestureLibrary.setSequenceType(GestureStore.SEQUENCE_SENSITIVE);
         mGestureLibrary.load();
+
+        mGestureDetectionThreshold = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1,
+                context.getResources().getDisplayMetrics()) * GESTURE_CONFIRM_MM;
     }
 
     public boolean onMotionEvent(MotionEvent event, int policyFlags) {
         final float x = event.getX();
         final float y = event.getY();
+        final long time = event.getEventTime();
 
         mPolicyFlags = policyFlags;
         switch (event.getActionMasked()) {
@@ -112,20 +140,56 @@
                 mDoubleTapDetected = false;
                 mSecondFingerDoubleTap = false;
                 mRecognizingGesture = true;
-                mPreviousX = x;
-                mPreviousY = y;
+                mGestureStarted = false;
+                mPreviousGestureX = x;
+                mPreviousGestureY = y;
                 mStrokeBuffer.clear();
-                mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
+                mStrokeBuffer.add(new GesturePoint(x, y, time));
+
+                mBaseX = x;
+                mBaseY = y;
+                mBaseTime = time;
                 break;
 
             case MotionEvent.ACTION_MOVE:
                 if (mRecognizingGesture) {
-                    final float dX = Math.abs(x - mPreviousX);
-                    final float dY = Math.abs(y - mPreviousY);
+                    final float deltaX = mBaseX - x;
+                    final float deltaY = mBaseY - y;
+                    final double moveDelta = Math.hypot(deltaX, deltaY);
+                    if (moveDelta > mGestureDetectionThreshold) {
+                        // If the pointer has moved more than the threshold,
+                        // update the stored values.
+                        mBaseX = x;
+                        mBaseY = y;
+                        mBaseTime = time;
+
+                        // If this hasn't been confirmed as a gesture yet, send
+                        // the event.
+                        if (!mGestureStarted) {
+                            mGestureStarted = true;
+                            mListener.onGestureStarted();
+                        }
+                    } else {
+                        final long timeDelta = time - mBaseTime;
+                        final long threshold = mGestureStarted ?
+                            CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS :
+                            CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS;
+
+                        // If the pointer hasn't moved for longer than the
+                        // timeout, cancel gesture detection.
+                        if (timeDelta > threshold) {
+                            cancelGesture();
+                            mListener.onGestureCancelled(event, policyFlags);
+                            return false;
+                        }
+                    }
+
+                    final float dX = Math.abs(x - mPreviousGestureX);
+                    final float dY = Math.abs(y - mPreviousGestureY);
                     if (dX >= TOUCH_TOLERANCE || dY >= TOUCH_TOLERANCE) {
-                        mPreviousX = x;
-                        mPreviousY = y;
-                        mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
+                        mPreviousGestureX = x;
+                        mPreviousGestureY = y;
+                        mStrokeBuffer.add(new GesturePoint(x, y, time));
                     }
                 }
                 break;
@@ -134,12 +198,13 @@
                 if (maybeFinishDoubleTap(event, policyFlags)) {
                     return true;
                 }
-                if (mRecognizingGesture) {
-                    mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
+                if (mGestureStarted) {
+                    mStrokeBuffer.add(new GesturePoint(x, y, time));
 
-                    if (recognizeGesture()) {
-                        return true;
+                    if (!recognizeGesture()) {
+                        mListener.onGestureCancelled(event, policyFlags);
                     }
+                    return true;
                 }
                 break;
 
@@ -152,7 +217,7 @@
                     // If this was the second finger, attempt to recognize double
                     // taps on it.
                     mSecondFingerDoubleTap = true;
-                    mSecondPointerDownTime = event.getEventTime();
+                    mSecondPointerDownTime = time;
                 } else {
                     // If there are more than two fingers down, stop watching
                     // for a double tap.
@@ -167,6 +232,10 @@
                     return true;
                 }
                 break;
+
+            case MotionEvent.ACTION_CANCEL:
+                clear();
+                break;
         }
 
         // If we're detecting taps on the second finger, map events from the
@@ -193,19 +262,14 @@
         mFirstTapDetected = false;
         mDoubleTapDetected = false;
         mSecondFingerDoubleTap = false;
+        mGestureStarted = false;
         cancelGesture();
-        mStrokeBuffer.clear();
     }
 
     public boolean firstTapDetected() {
         return mFirstTapDetected;
     }
 
-    public void cancelGesture() {
-        mRecognizingGesture = false;
-        mStrokeBuffer.clear();
-    }
-
     @Override
     public void onLongPress(MotionEvent e) {
         maybeSendLongPress(e, mPolicyFlags);
@@ -251,6 +315,12 @@
         return mListener.onDoubleTap(event, policyFlags);
     }
 
+    private void cancelGesture() {
+        mRecognizingGesture = false;
+        mGestureStarted = false;
+        mStrokeBuffer.clear();
+    }
+
     private boolean recognizeGesture() {
         Gesture gesture = new Gesture();
         gesture.addStroke(new GestureStroke(mStrokeBuffer));
@@ -265,7 +335,7 @@
                 }
                 try {
                     final int gestureId = Integer.parseInt(bestPrediction.name);
-                    if (mListener.onGesture(gestureId)) {
+                    if (mListener.onGestureCompleted(gestureId)) {
                         return true;
                     }
                 } catch (NumberFormatException nfe) {
diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
index 1a7de25..e1f3cd8 100644
--- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
+++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
@@ -110,17 +110,27 @@
         String matrix = Settings.Secure.getStringForUser(cr,
                 Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, userId);
         if (matrix != null) {
-            colorMatrix = multiply(colorMatrix, getMatrix(matrix));
+            final float[] userMatrix = get4x4Matrix(matrix);
+            if (userMatrix != null) {
+                colorMatrix = multiply(colorMatrix, userMatrix);
+            }
         }
 
         setColorTransform(colorMatrix);
     }
 
-    private static float[] getMatrix(String matrix) {
+    private static float[] get4x4Matrix(String matrix) {
         String[] strValues = matrix.split(",");
+        if (strValues.length != 16) {
+            return null;
+        }
         float[] values = new float[strValues.length];
-        for (int i = 0; i < values.length; i++) {
-            values[i] = Float.parseFloat(strValues[i]);
+        try {
+            for (int i = 0; i < values.length; i++) {
+                values[i] = Float.parseFloat(strValues[i]);
+            }
+        } catch (java.lang.NumberFormatException ex) {
+            return null;
         }
         return values;
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index ca30349..9e6cd00 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -25,7 +25,6 @@
 import android.view.MotionEvent;
 import android.view.MotionEvent.PointerCoords;
 import android.view.MotionEvent.PointerProperties;
-import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
 import android.view.WindowManagerPolicy;
 import android.view.accessibility.AccessibilityEvent;
@@ -87,9 +86,6 @@
     // Invalid pointer ID.
     private static final int INVALID_POINTER_ID = -1;
 
-    // The velocity above which we detect gestures.
-    private static final int GESTURE_DETECTION_VELOCITY_DIP = 1000;
-
     // The minimal distance before we take the middle of the distance between
     // the two dragging pointers as opposed to use the location of the primary one.
     private static final int MIN_POINTER_DISTANCE_TO_USE_MIDDLE_LOCATION_DIP = 200;
@@ -134,15 +130,9 @@
     // the two dragging pointers as opposed to use the location of the primary one.
     private final int mScaledMinPointerDistanceToUseMiddleLocation;
 
-    // The scaled velocity above which we detect gestures.
-    private final int mScaledGestureDetectionVelocity;
-
     // The handler to which to delegate events.
     private EventStreamTransformation mNext;
 
-    // Helper to track gesture velocity.
-    private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
-
     // Helper class to track received pointers.
     private final ReceivedPointerTracker mReceivedPointerTracker;
 
@@ -200,7 +190,6 @@
         final float density = context.getResources().getDisplayMetrics().density;
         mScaledMinPointerDistanceToUseMiddleLocation =
             (int) (MIN_POINTER_DISTANCE_TO_USE_MIDDLE_LOCATION_DIP * density);
-        mScaledGestureDetectionVelocity = (int) (GESTURE_DETECTION_VELOCITY_DIP * density);
     }
 
     @Override
@@ -289,11 +278,19 @@
 
         mReceivedPointerTracker.onMotionEvent(rawEvent);
 
-        if (mGestureDetector.onMotionEvent(event, policyFlags)) {
+        // The motion detector is interested in the movements in physical space,
+        // so it uses the rawEvent to ignore magnification and other
+        // transformations.
+        if (mGestureDetector.onMotionEvent(rawEvent, policyFlags)) {
             // Event was handled by the gesture detector.
             return;
         }
 
+        if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
+            clear(event, policyFlags);
+            return;
+        }
+
         switch(mCurrentState) {
             case STATE_TOUCH_EXPLORING: {
                 handleMotionEventStateTouchExploring(event, rawEvent, policyFlags);
@@ -305,7 +302,7 @@
                 handleMotionEventStateDelegating(event, policyFlags);
             } break;
             case STATE_GESTURE_DETECTING: {
-                handleMotionEventGestureDetecting(rawEvent, policyFlags);
+                // Already handled.
             } break;
             default:
                 throw new IllegalStateException("Illegal state: " + mCurrentState);
@@ -440,26 +437,50 @@
     }
 
     @Override
-    public boolean onGesture(int gestureId) {
+    public boolean onGestureCompleted(int gestureId) {
         if (mCurrentState != STATE_GESTURE_DETECTING) {
             return false;
         }
 
-        mAms.onTouchInteractionEnd();
-
-        // Announce the end of the gesture recognition.
-        sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
-        // Announce the end of a the touch interaction.
-        sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+        endGestureDetection();
 
         mAms.onGesture(gestureId);
 
-        mExitGestureDetectionModeDelayed.cancel();
-        mCurrentState = STATE_TOUCH_EXPLORING;
-
         return true;
     }
 
+    @Override
+    public void onGestureStarted() {
+      // We have to perform gesture detection, so
+      // clear the current state and try to detect.
+      mCurrentState = STATE_GESTURE_DETECTING;
+      mSendHoverEnterAndMoveDelayed.cancel();
+      mSendHoverExitDelayed.cancel();
+      mExitGestureDetectionModeDelayed.post();
+      // Send accessibility event to announce the start
+      // of gesture recognition.
+      sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_START);
+    }
+
+    @Override
+    public void onGestureCancelled(MotionEvent event, int policyFlags) {
+      if (mCurrentState == STATE_GESTURE_DETECTING) {
+          endGestureDetection();
+      } else if (mCurrentState == STATE_TOUCH_EXPLORING) {
+          final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
+          final int pointerIdBits = (1 << pointerId);
+
+          // Cache the event until we discern exploration from gesturing.
+          mSendHoverEnterAndMoveDelayed.addEvent(event);
+
+          // We have just decided that the user is touch,
+          // exploring so start sending events.
+          mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
+          mSendHoverExitDelayed.cancel();
+          sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
+      }
+    }
+
     /**
      * Handles a motion event in touch exploring state.
      *
@@ -471,8 +492,6 @@
             int policyFlags) {
         ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
 
-        mVelocityTracker.addMovement(rawEvent);
-
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN: {
                 mAms.onTouchInteractionStart();
@@ -525,46 +544,6 @@
                         if (mSendHoverEnterAndMoveDelayed.isPending()) {
                             // Cache the event until we discern exploration from gesturing.
                             mSendHoverEnterAndMoveDelayed.addEvent(event);
-
-                            // It is *important* to use the distance traveled by the pointers
-                            // on the screen which may or may not be magnified.
-                            final float deltaX = receivedTracker.getReceivedPointerDownX(pointerId)
-                                - rawEvent.getX(pointerIndex);
-                            final float deltaY = receivedTracker.getReceivedPointerDownY(pointerId)
-                                - rawEvent.getY(pointerIndex);
-                            final double moveDelta = Math.hypot(deltaX, deltaY);
-                            // The user has moved enough for us to decide.
-                            if (moveDelta > mDoubleTapSlop) {
-                                // Check whether the user is performing a gesture. We
-                                // detect gestures if the pointer is moving above a
-                                // given velocity.
-                                mVelocityTracker.computeCurrentVelocity(1000);
-                                final float maxAbsVelocity = Math.max(
-                                        Math.abs(mVelocityTracker.getXVelocity(pointerId)),
-                                        Math.abs(mVelocityTracker.getYVelocity(pointerId)));
-                                if (maxAbsVelocity > mScaledGestureDetectionVelocity) {
-                                    // We have to perform gesture detection, so
-                                    // clear the current state and try to detect.
-                                    mCurrentState = STATE_GESTURE_DETECTING;
-                                    mVelocityTracker.clear();
-                                    mSendHoverEnterAndMoveDelayed.cancel();
-                                    mSendHoverExitDelayed.cancel();
-                                    mExitGestureDetectionModeDelayed.post();
-                                    // Send accessibility event to announce the start
-                                    // of gesture recognition.
-                                    sendAccessibilityEvent(
-                                            AccessibilityEvent.TYPE_GESTURE_DETECTION_START);
-                                } else {
-                                    // We have just decided that the user is touch,
-                                    // exploring so start sending events.
-                                    mGestureDetector.cancelGesture();
-                                    mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
-                                    mSendHoverExitDelayed.cancel();
-                                    sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE,
-                                            pointerIdBits, policyFlags);
-                                }
-                                break;
-                            }
                         } else {
                             if (mTouchExplorationInProgress) {
                                 sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags);
@@ -602,11 +581,6 @@
                             }
                         }
 
-                        // We know that a new state transition is to happen and the
-                        // new state will not be gesture recognition, so cancel
-                        // the gesture.
-                        mGestureDetector.cancelGesture();
-
                         if (isDraggingGesture(event)) {
                             // Two pointers moving in the same direction within
                             // a given distance perform a drag.
@@ -620,7 +594,6 @@
                             mCurrentState = STATE_DELEGATING;
                             sendDownForAllNotInjectedPointers(event, policyFlags);
                         }
-                        mVelocityTracker.clear();
                     } break;
                     default: {
                         // More than one pointer so the user is not touch exploring
@@ -639,7 +612,6 @@
                         // More than two pointers are delegated to the view hierarchy.
                         mCurrentState = STATE_DELEGATING;
                         sendDownForAllNotInjectedPointers(event, policyFlags);
-                        mVelocityTracker.clear();
                     }
                 }
             } break;
@@ -648,8 +620,6 @@
                 final int pointerId = event.getPointerId(event.getActionIndex());
                 final int pointerIdBits = (1 << pointerId);
 
-                mVelocityTracker.clear();
-
                 if (mSendHoverEnterAndMoveDelayed.isPending()) {
                     // If we have not delivered the enter schedule an exit.
                     mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags);
@@ -663,9 +633,6 @@
                 }
 
             } break;
-            case MotionEvent.ACTION_CANCEL: {
-                clear(event, policyFlags);
-            } break;
         }
     }
 
@@ -756,9 +723,6 @@
                 }
                 mCurrentState = STATE_TOUCH_EXPLORING;
             } break;
-            case MotionEvent.ACTION_CANCEL: {
-                clear(event, policyFlags);
-            } break;
         }
     }
 
@@ -795,9 +759,6 @@
 
                 mCurrentState = STATE_TOUCH_EXPLORING;
             } break;
-            case MotionEvent.ACTION_CANCEL: {
-                clear(event, policyFlags);
-            } break;
             default: {
                 // Deliver the event.
                 sendMotionEvent(event, event.getAction(), ALL_POINTER_ID_BITS, policyFlags);
@@ -805,22 +766,16 @@
         }
     }
 
-    private void handleMotionEventGestureDetecting(MotionEvent event, int policyFlags) {
-        switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_UP: {
-                mAms.onTouchInteractionEnd();
-                // Announce the end of the gesture recognition.
-                sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
-                // Announce the end of a the touch interaction.
-                sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+    private void endGestureDetection() {
+        mAms.onTouchInteractionEnd();
 
-                mExitGestureDetectionModeDelayed.cancel();
-                mCurrentState = STATE_TOUCH_EXPLORING;
-            } break;
-            case MotionEvent.ACTION_CANCEL: {
-                clear(event, policyFlags);
-            } break;
-        }
+        // Announce the end of the gesture recognition.
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
+        // Announce the end of a the touch interaction.
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+
+        mExitGestureDetectionModeDelayed.cancel();
+        mCurrentState = STATE_TOUCH_EXPLORING;
     }
 
     /**
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index db901aa..29801b3 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -46,7 +46,6 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.Point;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -86,6 +85,7 @@
 import com.android.internal.widget.IRemoteViewsFactory;
 import com.android.server.LocalServices;
 import com.android.server.WidgetBackupProvider;
+import com.android.server.policy.IconUtilities;
 
 import libcore.io.IoUtils;
 
@@ -104,6 +104,7 @@
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -155,9 +156,17 @@
             } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
                 onUserStopped(userId);
             } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                refreshProfileWidgetsMaskedState(userId);
+                reloadWidgetsMaskedStateForUser(userId);
             } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
-                refreshWidgetMaskedState(userId);
+                synchronized (mLock) {
+                    reloadWidgetQuietModeMaskedStateLocked(userId);
+                }
+            } else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
+                String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                updateWidgetPackageSuspensionMaskedState(packages, true, getSendingUserId());
+            } else if (Intent.ACTION_PACKAGES_UNSUSPENDED.equals(action)) {
+                String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                updateWidgetPackageSuspensionMaskedState(packages, false, getSendingUserId());
             } else {
                 onPackageBroadcastReceived(intent, userId);
             }
@@ -206,6 +215,8 @@
     private boolean mSafeMode;
     private int mMaxWidgetBitmapMemory;
 
+    private final IconUtilities mIconUtilities;
+
     AppWidgetServiceImpl(Context context) {
         mContext = context;
         mPackageManager = AppGlobals.getPackageManager();
@@ -216,6 +227,7 @@
         mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
         mBackupRestoreController = new BackupRestoreController();
         mSecurityPolicy = new SecurityPolicy();
+        mIconUtilities = new IconUtilities(context);
 
         computeMaximumWidgetBitmapMemory();
         registerBroadcastReceiver();
@@ -268,6 +280,12 @@
         offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
                 offModeFilter, null, null);
+
+        IntentFilter suspendPackageFilter = new IntentFilter();
+        suspendPackageFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+        suspendPackageFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
+        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+                suspendPackageFilter, null, null);
     }
 
     private void registerOnCrossProfileProvidersChangedListener() {
@@ -413,15 +431,20 @@
     }
 
     /**
-     * Refresh the masked state for all profiles under the given user.
+     * Reload all widgets' masked state for the given user and its associated profiles, including
+     * due to quiet mode and package suspension.
      */
-    private void refreshProfileWidgetsMaskedState(int userId) {
+    private void reloadWidgetsMaskedStateForUser(int userId) {
         if (!mUserManager.isUserUnlocked(userId)) return;
-        List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
-        if (profiles != null) {
-            for (int i = 0; i < profiles.size(); i++) {
-                UserInfo user  = profiles.get(i);
-                refreshWidgetMaskedState(user.id);
+        synchronized (mLock) {
+            reloadWidgetPackageSuspensionMaskedStateLocked(userId);
+            List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
+            if (profiles != null) {
+                for (int i = 0; i < profiles.size(); i++) {
+                    UserInfo user  = profiles.get(i);
+                    reloadWidgetQuietModeMaskedStateLocked(user.id);
+                    reloadWidgetPackageSuspensionMaskedStateLocked(user.id);
+                }
             }
         }
     }
@@ -429,7 +452,7 @@
     /**
      * Mask/unmask widgets in the given profile, depending on the quiet state of the profile.
      */
-    private void refreshWidgetMaskedState(int profileId) {
+    private void reloadWidgetQuietModeMaskedStateLocked(int profileId) {
         if (!mUserManager.isUserUnlocked(profileId)) return;
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -438,25 +461,18 @@
                 return;
             }
             boolean shouldMask = user.isQuietModeEnabled();
-            final int iconSize = (int) mContext.getResources().getDimension(
-                    android.R.dimen.app_icon_size);
-            synchronized (mLock) {
-                final int N = mProviders.size();
-                for (int i = 0; i < N; i++) {
-                    Provider provider = mProviders.get(i);
-                    int providerUserId = provider.getUserId();
-                    if (providerUserId == profileId) {
-                        final int widgetCount = provider.widgets.size();
-                        for (int j = 0; j < widgetCount; j++) {
-                            Widget widget = provider.widgets.get(j);
-                            if (shouldMask) {
-                                widget.replaceWithMaskedViewsLocked(mContext, iconSize);
-                            } else {
-                                widget.clearMaskedViewsLocked();
-                            }
-                            scheduleNotifyUpdateAppWidgetLocked(widget,
-                                    widget.getEffectiveViewsLocked());
-                        }
+            final int N = mProviders.size();
+            for (int i = 0; i < N; i++) {
+                Provider provider = mProviders.get(i);
+                int providerUserId = provider.getUserId();
+                if (providerUserId != profileId) {
+                    continue;
+                }
+                if (provider.setMaskedByQuietProfileLocked(shouldMask)) {
+                    if (provider.isMaskedLocked()) {
+                        maskWidgetsViewsLocked(provider);
+                    } else {
+                        unmaskWidgetsViewsLocked(provider);
                     }
                 }
             }
@@ -465,6 +481,103 @@
         }
     }
 
+    /**
+     * Reload widget's masked state due to package suspension state.
+     */
+    private void reloadWidgetPackageSuspensionMaskedStateLocked(int profileId) {
+        final int N = mProviders.size();
+        for (int i = 0; i < N; i++) {
+            Provider provider = mProviders.get(i);
+            int providerUserId = provider.getUserId();
+            if (providerUserId != profileId) {
+                continue;
+            }
+            try {
+                ApplicationInfo ai = mPackageManager.getApplicationInfo(
+                        provider.info.provider.getPackageName(), 0, provider.getUserId());
+                boolean suspended = (ai.flags & ApplicationInfo.FLAG_SUSPENDED) != 0;
+                if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
+                    if (provider.isMaskedLocked()) {
+                        maskWidgetsViewsLocked(provider);
+                    } else {
+                        unmaskWidgetsViewsLocked(provider);
+                    }
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to query application info", e);
+            }
+        }
+    }
+
+    /**
+     * Incrementally update the masked state due to package suspension state.
+     */
+    private void updateWidgetPackageSuspensionMaskedState(String[] packagesArray, boolean suspended,
+            int profileId) {
+        if (packagesArray == null) {
+            return;
+        }
+        Set<String> packages = new ArraySet<String>(Arrays.asList(packagesArray));
+        synchronized (mLock) {
+            final int N = mProviders.size();
+            for (int i = 0; i < N; i++) {
+                Provider provider = mProviders.get(i);
+                int providerUserId = provider.getUserId();
+                if (providerUserId != profileId
+                        || !packages.contains(provider.info.provider.getPackageName())) {
+                    continue;
+                }
+                if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
+                    if (provider.isMaskedLocked()) {
+                        maskWidgetsViewsLocked(provider);
+                    } else {
+                        unmaskWidgetsViewsLocked(provider);
+                    }
+                }
+            }
+        }
+    }
+
+    private void maskWidgetsViewsLocked(Provider provider) {
+        Bitmap iconBitmap = null;
+        try {
+            // Load the unbadged application icon and pass it to the widget to appear on
+            // the masked view.
+            final String providerPackage = provider.info.provider.getPackageName();
+            Context userContext = mContext.createPackageContextAsUser(providerPackage, 0,
+                    UserHandle.of(provider.getUserId()));
+            PackageManager pm = userContext.getPackageManager();
+            Drawable icon = pm.getApplicationInfo(providerPackage, 0).loadUnbadgedIcon(pm);
+            // Create a bitmap of the icon which is what the widget's remoteview requires.
+            iconBitmap = mIconUtilities.createIconBitmap(icon);
+        } catch (NameNotFoundException e) {
+            Slog.e(TAG, "Fail to get application icon", e);
+            // Provider package removed, no need to mask its views as its state will be
+            // purged very soon.
+            return;
+        }
+
+        final int widgetCount = provider.widgets.size();
+        for (int j = 0; j < widgetCount; j++) {
+            Widget widget = provider.widgets.get(j);
+            if (widget.replaceWithMaskedViewsLocked(mContext, iconBitmap)) {
+                scheduleNotifyUpdateAppWidgetLocked(widget,
+                        widget.getEffectiveViewsLocked());
+            }
+        }
+    }
+
+    private void unmaskWidgetsViewsLocked(Provider provider) {
+        final int widgetCount = provider.widgets.size();
+        for (int j = 0; j < widgetCount; j++) {
+            Widget widget = provider.widgets.get(j);
+            if (widget.clearMaskedViewsLocked()) {
+                scheduleNotifyUpdateAppWidgetLocked(widget,
+                        widget.getEffectiveViewsLocked());
+            }
+        }
+    }
+
     private void resolveHostUidLocked(String pkg, int uid) {
         final int N = mHosts.size();
         for (int i = 0; i < N; i++) {
@@ -3442,6 +3555,9 @@
         PendingIntent broadcast;
         boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
 
+        boolean maskedByQuietProfile;
+        boolean maskedBySuspendedPackage;
+
         int tag = TAG_UNDEFINED; // for use while saving state (the index)
 
         public int getUserId() {
@@ -3470,6 +3586,24 @@
         public String toString() {
             return "Provider{" + id + (zombie ? " Z" : "") + '}';
         }
+
+        // returns true if the provider's masked state is changed as a result
+        public boolean setMaskedByQuietProfileLocked(boolean masked) {
+            boolean oldMaskedState = isMaskedLocked();
+            maskedByQuietProfile = masked;
+            return isMaskedLocked() != oldMaskedState;
+        }
+
+        // returns true if the provider's masked state is changed as a result
+        public boolean setMaskedBySuspendedPackageLocked(boolean masked) {
+            boolean oldMaskedState = isMaskedLocked();
+            maskedBySuspendedPackage = masked;
+            return isMaskedLocked() != oldMaskedState;
+        }
+
+        public boolean isMaskedLocked() {
+            return maskedByQuietProfile || maskedBySuspendedPackage;
+        }
     }
 
     private static final class ProviderId {
@@ -3625,28 +3759,24 @@
             return "AppWidgetId{" + appWidgetId + ':' + host + ':' + provider + '}';
         }
 
-        public void replaceWithMaskedViewsLocked(Context context, int iconSize) {
+        private boolean replaceWithMaskedViewsLocked(Context context, Bitmap icon) {
             if (maskedViews != null) {
-                return;
+                return false;
             }
             maskedViews = new RemoteViews(context.getPackageName(), R.layout.work_widget_mask_view);
-            try {
-                Drawable icon = context.getPackageManager().getApplicationIcon(
-                        provider.info.provider.getPackageName());
-                final int width = iconSize;
-                final int height = iconSize;
-                Bitmap iconBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-                Canvas canvas = new Canvas(iconBitmap);
-                icon.setBounds(0, 0, width, height);
-                icon.draw(canvas);
-                maskedViews.setImageViewBitmap(R.id.work_widget_app_icon, iconBitmap);
-            } catch (NameNotFoundException e) {
-                Slog.e(TAG, "Fail to get application icon", e);
+            if (icon != null) {
+                maskedViews.setImageViewBitmap(R.id.work_widget_app_icon, icon);
             }
+            return true;
         }
 
-        public void clearMaskedViewsLocked() {
-            maskedViews = null;
+        private boolean clearMaskedViewsLocked() {
+            if (maskedViews != null) {
+                maskedViews = null;
+                return true;
+            } else {
+                return false;
+            }
         }
 
         public RemoteViews getEffectiveViewsLocked() {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index c535ebd..5e948b1 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2166,7 +2166,8 @@
             try {
                 ApplicationInfo app = pkg.applicationInfo;
                 if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
-                        || app.backupAgentName == null) {
+                        || app.backupAgentName == null
+                        || (app.flags&ApplicationInfo.FLAG_FULL_BACKUP_ONLY) != 0) {
                     packages.remove(a);
                 }
                 else {
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 5f57a76..4667172 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -111,8 +111,9 @@
     
     static final boolean WAKEUP_STATS = false;
 
-    private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT = new Intent(
-            AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
+    private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT =
+            new Intent(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)
+                    .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
 
     final LocalLog mLog = new LocalLog(TAG);
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3fd8b40..4300920 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2670,18 +2670,21 @@
     // if ro.tether.denied = true we default to no tethering
     // gservices could set the secure setting to 1 though to enable it on a build where it
     // had previously been turned off.
+    @Override
     public boolean isTetheringSupported() {
         enforceTetherAccessPermission();
         int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
         boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.TETHER_SUPPORTED, defaultVal) != 0)
                 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
-        return tetherEnabledInSettings && ((mTethering.getTetherableUsbRegexs().length != 0 ||
+        return tetherEnabledInSettings && mUserManager.isAdminUser() &&
+                ((mTethering.getTetherableUsbRegexs().length != 0 ||
                 mTethering.getTetherableWifiRegexs().length != 0 ||
                 mTethering.getTetherableBluetoothRegexs().length != 0) &&
                 mTethering.getUpstreamIfaceTypes().length != 0);
     }
 
+    @Override
     public void startTethering(int type, ResultReceiver receiver,
             boolean showProvisioningUi) {
         ConnectivityManager.enforceTetherChangePermission(mContext);
@@ -2692,6 +2695,7 @@
         mTethering.startTethering(type, receiver, showProvisioningUi);
     }
 
+    @Override
     public void stopTethering(int type) {
         ConnectivityManager.enforceTetherChangePermission(mContext);
         mTethering.stopTethering(type);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 9bd79c9..423ef84 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1649,6 +1649,7 @@
             // Whoops, there is an upcoming alarm.  We don't actually want to go idle.
             if (mState != STATE_ACTIVE) {
                 becomeActiveLocked("alarm", Process.myUid());
+                becomeInactiveIfAppropriateLocked();
             }
             return;
         }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index c55c5b6..14ddc36 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -24,12 +24,12 @@
 import com.android.server.location.ActivityRecognitionProxy;
 import com.android.server.location.FlpHardwareProvider;
 import com.android.server.location.FusedProxy;
-import com.android.server.location.GnssLocationProvider;
 import com.android.server.location.GeocoderProxy;
 import com.android.server.location.GeofenceManager;
 import com.android.server.location.GeofenceProxy;
-import com.android.server.location.GpsMeasurementsProvider;
-import com.android.server.location.GpsNavigationMessageProvider;
+import com.android.server.location.GnssLocationProvider;
+import com.android.server.location.GnssMeasurementsProvider;
+import com.android.server.location.GnssNavigationMessageProvider;
 import com.android.server.location.LocationBlacklist;
 import com.android.server.location.LocationFudger;
 import com.android.server.location.LocationProviderInterface;
@@ -61,11 +61,11 @@
 import android.location.Criteria;
 import android.location.GeocoderParams;
 import android.location.Geofence;
+import android.location.IGnssMeasurementsListener;
 import android.location.IGnssStatusListener;
 import android.location.IGnssStatusProvider;
 import android.location.IGpsGeofenceHardware;
-import android.location.IGpsMeasurementsListener;
-import android.location.IGpsNavigationMessageListener;
+import android.location.IGnssNavigationMessageListener;
 import android.location.ILocationListener;
 import android.location.ILocationManager;
 import android.location.INetInitiatedListener;
@@ -162,8 +162,8 @@
     private LocationWorkerHandler mLocationHandler;
     private PassiveProvider mPassiveProvider;  // track passive provider for special cases
     private LocationBlacklist mBlacklist;
-    private GpsMeasurementsProvider mGpsMeasurementsProvider;
-    private GpsNavigationMessageProvider mGpsNavigationMessageProvider;
+    private GnssMeasurementsProvider mGnssMeasurementsProvider;
+    private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
     private IGpsGeofenceHardware mGpsGeofenceProxy;
 
     // --- fields below are protected by mLock ---
@@ -467,8 +467,8 @@
             mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
             addProviderLocked(gnssProvider);
             mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
-            mGpsMeasurementsProvider = gnssProvider.getGpsMeasurementsProvider();
-            mGpsNavigationMessageProvider = gnssProvider.getGpsNavigationMessageProvider();
+            mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
+            mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
             mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
         }
 
@@ -994,7 +994,7 @@
      */
     @Override
     public int getGpsYearOfHardware() {
-        if (mGpsNavigationMessageProvider != null) {
+        if (mGnssNavigationMessageProvider != null) {
             return mGpsSystemInfoProvider.getGpsYearOfHardware();
         } else {
             return 0;
@@ -1923,8 +1923,8 @@
     }
 
     @Override
-    public boolean addGpsMeasurementsListener(
-            IGpsMeasurementsListener listener,
+    public boolean addGnssMeasurementsListener(
+            IGnssMeasurementsListener listener,
             String packageName) {
         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
         checkResolutionLevelIsSufficientForProviderUse(
@@ -1941,22 +1941,22 @@
             Binder.restoreCallingIdentity(identity);
         }
 
-        if (!hasLocationAccess || mGpsMeasurementsProvider == null) {
+        if (!hasLocationAccess || mGnssMeasurementsProvider == null) {
             return false;
         }
-        return mGpsMeasurementsProvider.addListener(listener);
+        return mGnssMeasurementsProvider.addListener(listener);
     }
 
     @Override
-    public void removeGpsMeasurementsListener(IGpsMeasurementsListener listener) {
-        if (mGpsMeasurementsProvider != null) {
-            mGpsMeasurementsProvider.removeListener(listener);
+    public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
+        if (mGnssMeasurementsProvider != null) {
+            mGnssMeasurementsProvider.removeListener(listener);
         }
     }
 
     @Override
-    public boolean addGpsNavigationMessageListener(
-            IGpsNavigationMessageListener listener,
+    public boolean addGnssNavigationMessageListener(
+            IGnssNavigationMessageListener listener,
             String packageName) {
         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
         checkResolutionLevelIsSufficientForProviderUse(
@@ -1973,16 +1973,16 @@
             Binder.restoreCallingIdentity(identity);
         }
 
-        if (!hasLocationAccess || mGpsNavigationMessageProvider == null) {
+        if (!hasLocationAccess || mGnssNavigationMessageProvider == null) {
             return false;
         }
-        return mGpsNavigationMessageProvider.addListener(listener);
+        return mGnssNavigationMessageProvider.addListener(listener);
     }
 
     @Override
-    public void removeGpsNavigationMessageListener(IGpsNavigationMessageListener listener) {
-        if (mGpsNavigationMessageProvider != null) {
-            mGpsNavigationMessageProvider.removeListener(listener);
+    public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
+        if (mGnssNavigationMessageProvider != null) {
+            mGnssNavigationMessageProvider.removeListener(listener);
         }
     }
 
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index d0cd536..ecba0a4 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -200,7 +200,7 @@
                 PendingIntent.FLAG_UPDATE_CURRENT);
 
         Notification notification = new Notification.Builder(mContext)
-                .setSmallIcon(com.android.internal.R.drawable.ic_secure)
+                .setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
                 .setWhen(0)
                 .setOngoing(true)
                 .setTicker(title)
@@ -762,39 +762,24 @@
         }
 
         VerifyCredentialResponse response;
-        boolean shouldReEnroll = false;;
-        if (hasChallenge) {
-            byte[] token = null;
-            GateKeeperResponse gateKeeperResponse = getGateKeeperService()
-                    .verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
-            int responseCode = gateKeeperResponse.getResponseCode();
-            if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
-                 response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
-            } else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
-                token = gateKeeperResponse.getPayload();
-                if (token == null) {
-                    // something's wrong if there's no payload with a challenge
-                    Slog.e(TAG, "verifyChallenge response had no associated payload");
-                    response = VerifyCredentialResponse.ERROR;
-                } else {
-                    shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
-                    response = new VerifyCredentialResponse(token);
-                }
-            } else {
+        boolean shouldReEnroll = false;
+        GateKeeperResponse gateKeeperResponse = getGateKeeperService()
+                .verifyChallenge(userId, challenge, storedHash.hash, credential.getBytes());
+        int responseCode = gateKeeperResponse.getResponseCode();
+        if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
+             response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
+        } else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
+            byte[] token = gateKeeperResponse.getPayload();
+            if (token == null) {
+                // something's wrong if there's no payload with a challenge
+                Slog.e(TAG, "verifyChallenge response had no associated payload");
                 response = VerifyCredentialResponse.ERROR;
+            } else {
+                shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
+                response = new VerifyCredentialResponse(token);
             }
         } else {
-            GateKeeperResponse gateKeeperResponse = getGateKeeperService().verify(
-                    userId, storedHash.hash, credential.getBytes());
-            int responseCode = gateKeeperResponse.getResponseCode();
-            if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
-                response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
-            } else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
-                shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
-                response = VerifyCredentialResponse.OK;
-            } else {
-                response = VerifyCredentialResponse.ERROR;
-            }
+            response = VerifyCredentialResponse.ERROR;
         }
 
         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 4a186a6..5120e1b 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2800,14 +2800,13 @@
     }
 
     @Override
-    public void prepareUserStorage(
-            String volumeUuid, int userId, int serialNumber, boolean ephemeral) {
+    public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
         waitForReady();
 
         try {
             mCryptConnector.execute("cryptfs", "prepare_user_storage", escapeNull(volumeUuid),
-                    userId, serialNumber, ephemeral ? 1 : 0);
+                    userId, serialNumber, flags);
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }
@@ -2817,8 +2816,9 @@
     public ParcelFileDescriptor mountAppFuse(final String name) throws RemoteException {
         try {
             final int uid = Binder.getCallingUid();
+            final int pid = Binder.getCallingPid();
             final NativeDaemonEvent event =
-                    mConnector.execute("appfuse", "mount", uid, name);
+                    mConnector.execute("appfuse", "mount", uid, pid, name);
             if (event.getFileDescriptors() == null) {
                 throw new RemoteException("AppFuse FD from vold is null.");
             }
@@ -2830,7 +2830,7 @@
                         public void onClose(IOException e) {
                             try {
                                 final NativeDaemonEvent event = mConnector.execute(
-                                        "appfuse", "unmount", uid, name);
+                                        "appfuse", "unmount", uid, pid, name);
                             } catch (NativeDaemonConnectorException unmountException) {
                                 Log.e(TAG, "Failed to unmount appfuse.");
                             }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 143015f..2683be6 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -4266,6 +4266,21 @@
         }
     }
 
+    private boolean isPermitted(String opPackageName, int callingUid, String... permissions) {
+        for (String perm : permissions) {
+            if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "  caller uid " + callingUid + " has " + perm);
+                }
+                final int opCode = AppOpsManager.permissionToOpCode(perm);
+                if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOp(
+                        opCode, callingUid, opPackageName) == AppOpsManager.MODE_ALLOWED) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 
     private int handleIncomingUser(int userId) {
         try {
@@ -4340,53 +4355,12 @@
 
     private List<String> getTypesVisibleToCaller(int callingUid, int userId,
             String opPackageName) {
-        List<String> permissionsToCheck = new ArrayList<String>(2);
-        permissionsToCheck.add(Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
-        long id = Binder.clearCallingIdentity();
-        try {
-            ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
-                    opPackageName, 0 /* flags */);
-            /*
-             * At or before SDK 23, clients discover all the accounts in their
-             * user profile (via AccountManager.getAccounts(...)) by declaring
-             * the GET_ACCOUNTS permission.
-             *
-             * After SDK 23 the GET_ACCOUNTS permission is deprecated.  Instead
-             * apps will be able to retrieve those accounts managed by
-             * authenticators sharing a package signature without any special
-             * permissions. The only clients able to discover all the accounts
-             * on the device will be those with the GET_ACCOUNTS_PRVILEGED
-             * system permission.
-             */
-            if (23 >= appInfo.targetSdkVersion) {
-                permissionsToCheck.add(Manifest.permission.GET_ACCOUNTS);
-            }
-        } catch (NameNotFoundException e) {
-            // No application associated with the specified package.
-            Log.w(TAG, "No application associated with package: " + opPackageName);
-        } finally {
-            Binder.restoreCallingIdentity(id);
-        }
-        boolean isPermitted = isPermitted(opPackageName, callingUid, permissionsToCheck);
+        boolean isPermitted =
+                isPermitted(opPackageName, callingUid, Manifest.permission.GET_ACCOUNTS,
+                        Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
         return getTypesForCaller(callingUid, userId, isPermitted);
     }
 
-    private boolean isPermitted(String opPackageName, int callingUid, List<String> permissions) {
-        for (String perm : permissions) {
-            if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "  caller uid " + callingUid + " has " + perm);
-                }
-                final int opCode = AppOpsManager.permissionToOpCode(perm);
-                if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOp(
-                        opCode, callingUid, opPackageName) == AppOpsManager.MODE_ALLOWED) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     private List<String> getTypesManagedByCaller(int callingUid, int userId) {
         return getTypesForCaller(callingUid, userId, false);
     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 4f0d4d9..bef6f0a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -62,7 +62,7 @@
     static final boolean DEBUG_LRU = DEBUG_ALL || false;
     static final boolean DEBUG_MU = DEBUG_ALL || false;
     static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false;
-    static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
+    static final boolean DEBUG_PAUSE = DEBUG_ALL || true;
     static final boolean DEBUG_POWER = DEBUG_ALL || false;
     static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
     static final boolean DEBUG_PROCESS_OBSERVERS = DEBUG_ALL || false;
@@ -77,7 +77,7 @@
     static final boolean DEBUG_SERVICE = DEBUG_ALL || false;
     static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false;
     static final boolean DEBUG_STACK = DEBUG_ALL || false;
-    static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || false;
+    static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || true;
     static final boolean DEBUG_SWITCH = DEBUG_ALL || false;
     static final boolean DEBUG_TASKS = DEBUG_ALL || false;
     static final boolean DEBUG_THUMBNAILS = DEBUG_ALL || false;
@@ -85,7 +85,7 @@
     static final boolean DEBUG_UID_OBSERVERS = DEBUG_ALL || false;
     static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false;
     static final boolean DEBUG_USER_LEAVING = DEBUG_ALL || false;
-    static final boolean DEBUG_VISIBILITY = DEBUG_ALL || false;
+    static final boolean DEBUG_VISIBILITY = DEBUG_ALL || true;
     static final boolean DEBUG_VISIBLE_BEHIND = DEBUG_ALL_ACTIVITIES || false;
     static final boolean DEBUG_USAGE_STATS = DEBUG_ALL || false;
     static final boolean DEBUG_PERMISSIONS_REVIEW = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c55e713..7aac9d7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -249,12 +249,15 @@
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FIRST_STATIC_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
@@ -599,6 +602,8 @@
 
     final AppErrors mAppErrors;
 
+    boolean mDoingSetFocusedActivity;
+
     public boolean canShowErrorDialogs() {
         return mShowDialogs && !mSleeping && !mShuttingDown;
     }
@@ -2730,6 +2735,12 @@
         }
 
         if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r);
+
+        final boolean wasDoingSetFocusedActivity = mDoingSetFocusedActivity;
+        if (wasDoingSetFocusedActivity) Slog.w(TAG,
+                "setFocusedActivityLocked: called recursively, r=" + r + ", reason=" + reason);
+        mDoingSetFocusedActivity = true;
+
         final ActivityRecord last = mFocusedActivity;
         mFocusedActivity = r;
         if (r.task.isApplicationTask()) {
@@ -2781,6 +2792,12 @@
             mLastFocusedUserId = mFocusedActivity.userId;
         }
 
+        // Log a warning if the focused app is changed during the process. This could
+        // indicate a problem of the focus setting logic!
+        if (mFocusedActivity != r) Slog.w(TAG,
+                "setFocusedActivityLocked: r=" + r + " but focused to " + mFocusedActivity);
+        mDoingSetFocusedActivity = wasDoingSetFocusedActivity;
+
         EventLogTags.writeAmFocusedActivity(
                 mFocusedActivity == null ? -1 : mFocusedActivity.userId,
                 mFocusedActivity == null ? "NULL" : mFocusedActivity.shortComponentName,
@@ -5310,28 +5327,42 @@
 
     @Override
     public void killAllBackgroundProcesses() {
+        killAllBackgroundProcesses(-1);
+    }
+
+    /**
+     * Kills all background processes with targetSdkVersion below the specified
+     * target SDK version.
+     *
+     * @param targetSdkVersion the target SDK version below which to kill
+     *                         processes, or {@code -1} to kill all processes
+     */
+    private void killAllBackgroundProcesses(int targetSdkVersion) {
         if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
                 != PackageManager.PERMISSION_GRANTED) {
-            String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid()
+            final String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
                     + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
 
-        long callingId = Binder.clearCallingIdentity();
+        final long callingId = Binder.clearCallingIdentity();
         try {
-            synchronized(this) {
-                ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
+            synchronized (this) {
+                final ArrayList<ProcessRecord> procs = new ArrayList<>();
                 final int NP = mProcessNames.getMap().size();
-                for (int ip=0; ip<NP; ip++) {
-                    SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+                for (int ip = 0; ip < NP; ip++) {
+                    final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
                     final int NA = apps.size();
-                    for (int ia=0; ia<NA; ia++) {
-                        ProcessRecord app = apps.valueAt(ia);
+                    for (int ia = 0; ia < NA; ia++) {
+                        final ProcessRecord app = apps.valueAt(ia);
                         if (app.persistent) {
-                            // we don't kill persistent processes
+                            // We don't kill persistent processes.
+                            continue;
+                        }
+                        if (targetSdkVersion > 0
+                                && app.info.targetSdkVersion >= targetSdkVersion) {
                             continue;
                         }
                         if (app.removed) {
@@ -5343,11 +5374,13 @@
                     }
                 }
 
-                int N = procs.size();
-                for (int i=0; i<N; i++) {
+                final int N = procs.size();
+                for (int i = 0; i < N; i++) {
                     removeProcessLocked(procs.get(i), false, true, "kill all background");
                 }
+
                 mAllowLowerMemLevel = true;
+
                 updateOomAdjLocked();
                 doLowMemReportIfNeededLocked(null);
             }
@@ -7069,7 +7102,7 @@
     }
 
     @Override
-    public boolean inMultiWindowMode(IBinder token) {
+    public boolean inMultiWindow(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized(this) {
@@ -7086,7 +7119,7 @@
     }
 
     @Override
-    public boolean inPictureInPictureMode(IBinder token) {
+    public boolean inPictureInPicture(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized(this) {
@@ -7102,24 +7135,24 @@
     }
 
     @Override
-    public void enterPictureInPictureMode(IBinder token) {
+    public void enterPictureInPicture(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
         try {
             synchronized(this) {
                 if (!mSupportsPictureInPicture) {
-                    throw new IllegalStateException("enterPictureInPictureMode: "
+                    throw new IllegalStateException("enterPictureInPicture: "
                             + "Device doesn't support picture-in-picture mode.");
                 }
 
                 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
 
                 if (r == null) {
-                    throw new IllegalStateException("enterPictureInPictureMode: "
+                    throw new IllegalStateException("enterPictureInPicture: "
                             + "Can't find activity for token=" + token);
                 }
 
                 if (!r.supportsPictureInPicture()) {
-                    throw new IllegalArgumentException("enterPictureInPictureMode: "
+                    throw new IllegalArgumentException("enterPictureInPicture: "
                             + "Picture-In-Picture not supported for r=" + r);
                 }
 
@@ -7128,7 +7161,7 @@
                         ? mDefaultPinnedStackBounds : null;
 
                 mStackSupervisor.moveActivityToStackLocked(
-                        r, PINNED_STACK_ID, "enterPictureInPictureMode", bounds);
+                        r, PINNED_STACK_ID, "enterPictureInPicture", bounds);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -8745,6 +8778,13 @@
                         continue;
                     }
 
+                    if (!tr.mUserSetupComplete) {
+                        // Don't include task launched while user is not done setting-up.
+                        if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+                                "Skipping, user setup not complete: " + tr);
+                        continue;
+                    }
+
                     ActivityManager.RecentTaskInfo rti = createRecentTaskInfoFromTaskRecord(tr);
                     if (!detailed) {
                         rti.baseIntent.replaceExtras((Bundle)null);
@@ -9352,6 +9392,10 @@
             try {
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
                         + " to stackId=" + stackId + " toTop=" + toTop);
+                if (stackId == DOCKED_STACK_ID) {
+                    mWindowManager.setDockedStackCreateState(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
+                            null /* initialBounds */);
+                }
                 mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop, !FORCE_FOCUS,
                         "moveTaskToStack", ANIMATE);
             } finally {
@@ -12406,9 +12450,8 @@
             mLocalDeviceIdleController
                     = LocalServices.getService(DeviceIdleController.LocalService.class);
 
-            // Make sure we have the current profile info, since it is needed for
-            // security checks.
-            mUserController.updateCurrentProfileIdsLocked();
+            // Make sure we have the current profile info, since it is needed for security checks.
+            mUserController.onSystemReady();
 
             mRecentTasks.onSystemReady();
             // Check to see if there are any update receivers to run.
@@ -17638,6 +17681,22 @@
             final long origId = Binder.clearCallingIdentity();
             final ActivityStack stack = mStackSupervisor.getStack(fromStackId);
             if (stack != null) {
+                if (fromStackId == DOCKED_STACK_ID) {
+
+                    // We are moving all tasks from the docked stack to the fullscreen stack, which
+                    // is dismissing the docked stack, so resize all other stacks to fullscreen here
+                    // already so we don't end up with resize trashing.
+                    for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
+                        if (StackId.isResizeableByDockedStack(i)) {
+                            ActivityStack otherStack = mStackSupervisor.getStack(i);
+                            if (otherStack != null) {
+                                mStackSupervisor.resizeStackLocked(i,
+                                        null, null, null, PRESERVE_WINDOWS,
+                                        true /* allowResizeInDockedMode */);
+                            }
+                        }
+                    }
+                }
                 final ArrayList<TaskRecord> tasks = stack.getAllTasks();
                 final int size = tasks.size();
                 if (onTop) {
@@ -17776,7 +17835,7 @@
                     if (values.getLocales().size() == 1) {
                         // This is an optimization to avoid the JNI call when the result of
                         // getFirstMatch() does not depend on the supported locales.
-                        locale = values.getLocales().getPrimary();
+                        locale = values.getLocales().get(0);
                     } else {
                         if (mSupportedSystemLocales == null) {
                             mSupportedSystemLocales =
@@ -17827,6 +17886,11 @@
                     mHandler.sendMessage(msg);
                 }
 
+                final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
+                if (isDensityChange) {
+                    killAllBackgroundProcesses(Build.VERSION_CODES.N);
+                }
+
                 for (int i=mLruProcesses.size()-1; i>=0; i--) {
                     ProcessRecord app = mLruProcesses.get(i);
                     try {
@@ -18102,7 +18166,7 @@
         if (app == TOP_APP) {
             // The last app on the list is the foreground app.
             adj = ProcessList.FOREGROUND_APP_ADJ;
-            schedGroup = Process.THREAD_GROUP_DEFAULT;
+            schedGroup = Process.THREAD_GROUP_TOP_APP;
             app.adjType = "top-activity";
             foregroundActivities = true;
             procState = PROCESS_STATE_CUR_TOP;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index ed26e0c..90a7da9 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManager.StackId;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
@@ -409,15 +410,40 @@
     }
 
     void scheduleConfigurationChanged(Configuration config, boolean reportToActivity) {
-        if (app != null && app.thread != null) {
-            try {
-                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + " " +
-                        "reportToActivity=" + reportToActivity + " and config: " + config);
-                app.thread.scheduleActivityConfigurationChanged(
-                        appToken, new Configuration(config), reportToActivity);
-            } catch (RemoteException e) {
-                // If process died, whatever.
-            }
+        if (app == null || app.thread == null) {
+            return;
+        }
+        try {
+            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + " " +
+                    "reportToActivity=" + reportToActivity + " and config: " + config);
+            app.thread.scheduleActivityConfigurationChanged(
+                    appToken, new Configuration(config), reportToActivity);
+        } catch (RemoteException e) {
+            // If process died, whatever.
+        }
+    }
+
+    void scheduleMultiWindowChanged() {
+        if (task == null || task.stack == null || app == null || app.thread == null) {
+            return;
+        }
+        try {
+            // An activity is considered to be in multi-window mode if its task isn't fullscreen.
+            app.thread.scheduleMultiWindowChanged(appToken, !task.mFullscreen);
+        } catch (Exception e) {
+            // If process died, I don't care.
+        }
+    }
+
+    void schedulePictureInPictureChanged() {
+        if (task == null || task.stack == null || app == null || app.thread == null) {
+            return;
+        }
+        try {
+            app.thread.schedulePictureInPictureChanged(
+                    appToken, task.stack.mStackId == PINNED_STACK_ID);
+        } catch (Exception e) {
+            // If process died, no one cares.
         }
     }
 
@@ -584,13 +610,16 @@
         haveState = true;
 
         if (aInfo != null) {
+            // If the class name in the intent doesn't match that of the target, this is
+            // probably an alias. We have to create a new ComponentName object to keep track
+            // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
             if (aInfo.targetActivity == null
-                    || aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
-                    || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
+                    || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
+                    && (aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
+                    || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP))) {
                 realActivity = _intent.getComponent();
             } else {
-                realActivity = new ComponentName(aInfo.packageName,
-                        aInfo.targetActivity);
+                realActivity = new ComponentName(aInfo.packageName, aInfo.targetActivity);
             }
             taskAffinity = aInfo.taskAffinity;
             stateNotNeeded = (aInfo.flags&
@@ -654,7 +683,6 @@
                     _intent.getCategories().size() == 1 &&
                     _intent.getData() == null &&
                     _intent.getType() == null &&
-                    (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                     !isResolverActivity()) {
                 // This sure looks like a home activity!
                 mActivityType = HOME_ACTIVITY_TYPE;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 7de254e..c352fc8 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -395,6 +395,13 @@
             mTaskPositioner.setDisplay(activityDisplay.mDisplay);
             mTaskPositioner.configure(mBounds);
         }
+
+        if (mStackId == DOCKED_STACK_ID) {
+            // If we created a docked stack we want to resize it so it resizes all other stacks
+            // in the system.
+            mStackSupervisor.resizeDockedStackLocked(
+                    mBounds, null, null, null, null, PRESERVE_WINDOWS);
+        }
     }
 
     void detachDisplay() {
@@ -1673,11 +1680,37 @@
             TaskRecord task, ActivityRecord r) {
         if (r.fullscreen) {
             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
-                    + " stackInvisible=" + stackInvisible
-                    + " behindFullscreenActivity=" + behindFullscreenActivity);
+                        + " stackInvisible=" + stackInvisible
+                        + " behindFullscreenActivity=" + behindFullscreenActivity);
             // At this point, nothing else needs to be shown in this task.
             behindFullscreenActivity = true;
-        } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
+        } else if (isHomeStack()) {
+            if (r.isHomeActivity()) {
+                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home activity: at " + r
+                        + " stackInvisible=" + stackInvisible
+                        + " behindFullscreenActivity=" + behindFullscreenActivity);
+                // No other activity in the home stack should be visible behind the home activity.
+                // Home activities is usually a translucent activity with the wallpaper behind them.
+                // However, when they don't have the wallpaper behind them, we want to show
+                // activities in the next application stack behind them vs. another activity in the
+                // home stack like recents.
+                behindFullscreenActivity = true;
+            } else if (r.isRecentsActivity()
+                    && task.getTaskToReturnTo() == APPLICATION_ACTIVITY_TYPE) {
+                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                        "Recents activity returning to app: at " + r
+                        + " stackInvisible=" + stackInvisible
+                        + " behindFullscreenActivity=" + behindFullscreenActivity);
+                // We don't want any other activities in the home stack visible if the recents
+                // activity is going to be returning to an application activity type.
+                // We do this to preserve the visible order the user used to get into the recents
+                // activity. The recents activity is normally translucent and if it doesn't have
+                // the wallpaper behind it the next activity in the home stack shouldn't be visible
+                // when the home stack is brought to the front to display the recents activity from
+                // an app.
+                behindFullscreenActivity = true;
+            }
+        } else if (r.frontOfTask && task.isOverHomeStack()) {
             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r
                     + " stackInvisible=" + stackInvisible
                     + " behindFullscreenActivity=" + behindFullscreenActivity);
@@ -2135,7 +2168,9 @@
             if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next);
 
             // This activity is now becoming visible.
-            mWindowManager.setAppVisibility(next.appToken, true);
+            if (!next.visible) {
+                mWindowManager.setAppVisibility(next.appToken, true);
+            }
 
             // schedule launch ticks to collect information about slow apps.
             next.startLaunchTickingLocked();
@@ -4271,6 +4306,12 @@
             oldTaskOverride = record.task.extractOverrideConfig(record.configuration);
         }
 
+        // Conversely, do the same when going the other direction.
+        if (Configuration.EMPTY.equals(taskConfig)
+                && !Configuration.EMPTY.equals(oldTaskOverride)) {
+            taskConfig = record.task.extractOverrideConfig(record.configuration);
+        }
+
         // Determine what has changed.  May be nothing, if this is a config
         // that has come back from the app after going idle.  In that case
         // we just want to leave the official config object now in the
@@ -4801,7 +4842,7 @@
 
     private void postAddTask(TaskRecord task, ActivityStack prevStack) {
         if (prevStack != null) {
-            task.reportPictureInPictureModeChangeIfNeeded(prevStack);
+            mStackSupervisor.scheduleReportPictureInPictureChangedIfNeeded(task, prevStack);
         } else if (task.voiceSession != null) {
             try {
                 task.voiceSession.taskStarted(task.intent, task.taskId);
@@ -4860,7 +4901,7 @@
         r.setTask(task, null);
         task.addActivityToTop(r);
         setAppTask(r, task);
-        task.reportPictureInPictureModeChangeIfNeeded(prevStack);
+        mStackSupervisor.scheduleReportPictureInPictureChangedIfNeeded(task, prevStack);
         moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, "moveActivityToStack");
         if (wasResumed) {
             prevStack.mResumedActivity = null;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 5f65b3d..f53e71a 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -203,6 +203,8 @@
     static final int CONTAINER_CALLBACK_TASK_LIST_EMPTY = FIRST_SUPERVISOR_STACK_MSG + 11;
     static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12;
     static final int SHOW_LOCK_TASK_ESCAPE_MESSAGE_MSG = FIRST_SUPERVISOR_STACK_MSG + 13;
+    static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14;
+    static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15;
 
     private static final String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay";
 
@@ -322,6 +324,14 @@
     /** List of activities that are in the process of going to sleep. */
     final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<>();
 
+    /** List of activities whose multi-window mode changed that we need to report to the
+     * application */
+    final ArrayList<ActivityRecord> mMultiWindowModeChangedActivities = new ArrayList<>();
+
+    /** List of activities whose picture-in-picture mode changed that we need to report to the
+     * application */
+    final ArrayList<ActivityRecord> mPipModeChangedActivities = new ArrayList<>();
+
     /** Used on user changes */
     final ArrayList<UserState> mStartingUsers = new ArrayList<>();
 
@@ -573,7 +583,7 @@
         }
 
         final ActivityRecord r = topRunningActivityLocked();
-        if (mService.mFocusedActivity != r) {
+        if (!mService.mDoingSetFocusedActivity && mService.mFocusedActivity != r) {
             // The focus activity should always be the top activity in the focused stack.
             // There will be chaos and anarchy if it isn't...
             mService.setFocusedActivityLocked(r, reason + " setFocusStack");
@@ -1553,14 +1563,6 @@
                     mService.mUserController.finishUserSwitch(startingUsers.get(i));
                 }
             }
-            // Complete starting up of background users
-            if (mStartingBackgroundUsers.size() > 0) {
-                startingUsers = new ArrayList<UserState>(mStartingBackgroundUsers);
-                mStartingBackgroundUsers.clear();
-                for (int i = 0; i < startingUsers.size(); i++) {
-                    mService.mUserController.finishUserBoot(startingUsers.get(i));
-                }
-            }
         }
 
         mService.trimApplications();
@@ -1891,12 +1893,6 @@
 
     private void resizeStackUncheckedLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds,
             Rect tempTaskInsetBounds) {
-        if (bounds != null && mWindowManager.isFullscreenBounds(stack.mStackId, bounds)) {
-            // The bounds passed in corresponds to the fullscreen bounds which we normally
-            // represent with null. Go ahead and set it to null so that all tasks configuration
-            // can have the right fullscreen state.
-            bounds = null;
-        }
         bounds = TaskRecord.validateBounds(bounds);
 
         mTmpBounds.clear();
@@ -1915,7 +1911,8 @@
                     task.updateOverrideConfiguration(tempRect2);
                 } else {
                     task.updateOverrideConfiguration(
-                            tempTaskBounds != null ? tempTaskBounds : bounds);
+                            tempTaskBounds != null ? tempTaskBounds : bounds,
+                            tempTaskInsetBounds != null ? tempTaskInsetBounds : bounds);
                 }
             }
 
@@ -1991,7 +1988,7 @@
                 // We get the bounds to use from window manager which has been adjusted for any
                 // screen controls and is also the same for all stacks.
                 mWindowManager.getStackDockedModeBounds(
-                        HOME_STACK_ID, tempRect, true /* ignoreVisibilityOnKeyguardShowing */);
+                        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);
@@ -2215,9 +2212,9 @@
         // Temporarily disable resizeablility of task we are moving. We don't want it to be resized
         // if a docked stack is created below which will lead to the stack we are moving from and
         // its resizeable tasks being resized.
-        task.mResizeMode = RESIZE_MODE_UNRESIZEABLE;
+        task.mTemporarilyUnresizable = true;
         final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, toTop);
-        task.mResizeMode = resizeMode;
+        task.mTemporarilyUnresizable = false;
         mWindowManager.moveTaskToStack(task.taskId, stack.mStackId, toTop);
         stack.addTask(task, toTop, reason);
 
@@ -2244,8 +2241,9 @@
         }
 
         final ActivityRecord topActivity = task.getTopActivity();
+        final int sourceStackId = task.stack != null ? task.stack.mStackId : INVALID_STACK_ID;
         final boolean mightReplaceWindow =
-                StackId.preserveWindowOnTaskMove(stackId) && topActivity != null;
+                StackId.replaceWindowsOnTaskMove(sourceStackId, stackId) && topActivity != null;
         if (mightReplaceWindow) {
             // We are about to relaunch the activity because its configuration changed due to
             // being maximized, i.e. size change. The activity will first remove the old window
@@ -2257,25 +2255,34 @@
             // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
             mWindowManager.setReplacingWindow(topActivity.appToken, animate);
         }
+
+        mWindowManager.deferSurfaceLayout();
         final int preferredLaunchStackId = stackId;
-        final ActivityStack stack = moveTaskToStackUncheckedLocked(
-                task, stackId, toTop, forceFocus, "moveTaskToStack:" + reason);
-        stackId = stack.mStackId;
-
-        if (!animate) {
-            stack.mNoAnimActivities.add(topActivity);
-        }
-
         boolean kept = true;
-        // Make sure the task has the appropriate bounds/size for the stack it is in.
-        if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
-            kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
-        } else if (stackId == FREEFORM_WORKSPACE_STACK_ID
-                && task.mBounds == null && task.mLastNonFullscreenBounds != null) {
-            kept = resizeTaskLocked(task, task.mLastNonFullscreenBounds,
-                    RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
-        } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
-            kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
+        try {
+            final ActivityStack stack = moveTaskToStackUncheckedLocked(
+                    task, stackId, toTop, forceFocus, "moveTaskToStack:" + reason);
+            stackId = stack.mStackId;
+
+            if (!animate) {
+                stack.mNoAnimActivities.add(topActivity);
+            }
+
+            // We might trigger a configuration change. Save the current task bounds for freezing.
+            mWindowManager.prepareFreezingTaskBounds(stack.mStackId);
+
+            // Make sure the task has the appropriate bounds/size for the stack it is in.
+            if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
+                kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
+            } else if (stackId == FREEFORM_WORKSPACE_STACK_ID
+                    && task.mBounds == null && task.mLastNonFullscreenBounds != null) {
+                kept = resizeTaskLocked(task, task.mLastNonFullscreenBounds,
+                        RESIZE_MODE_SYSTEM, !mightReplaceWindow);
+            } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
+                kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
+            }
+        } finally {
+            mWindowManager.continueSurfaceLayout();
         }
 
         if (mightReplaceWindow) {
@@ -2287,7 +2294,7 @@
 
         // The task might have already been running and its visibility needs to be synchronized with
         // the visibility of the stack / windows.
-        ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+        ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
         resumeFocusedStackTopActivityLocked();
 
         showNonResizeableDockToastIfNeeded(task, preferredLaunchStackId, stackId);
@@ -2598,9 +2605,11 @@
 
         stack.setVisibleBehindActivity(visible ? r : null);
         if (!visible) {
-            // Make the activity immediately above r opaque.
+            // If there is a translucent home activity, we need to force it stop being translucent,
+            // because we can't depend on the application to necessarily perform that operation.
+            // Check out b/14469711 for details.
             final ActivityRecord next = stack.findNextTranslucentActivity(r);
-            if (next != null) {
+            if (next != null && next.isHomeActivity()) {
                 mService.convertFromTranslucent(next.appToken);
             }
         }
@@ -2769,15 +2778,6 @@
         return homeInFront;
     }
 
-    /**
-     * Add background users to send boot completed events to.
-     * @param userId The user being started in the background
-     * @param uss The state object for the user.
-     */
-    public void startBackgroundUserLocked(int userId, UserState uss) {
-        mStartingBackgroundUsers.add(uss);
-    }
-
     /** Checks whether the userid is a profile of the current user. */
     boolean isCurrentProfileLocked(int userId) {
         if (userId == mCurrentUser) return true;
@@ -3406,6 +3406,38 @@
         mActivityMetricsLogger.logWindowState();
     }
 
+    void scheduleReportMultiWindowChanged(TaskRecord task) {
+        for (int i = task.mActivities.size() - 1; i >= 0; i--) {
+            final ActivityRecord r = task.mActivities.get(i);
+            if (r.app != null && r.app.thread != null) {
+                mMultiWindowModeChangedActivities.add(r);
+            }
+        }
+
+        if (!mHandler.hasMessages(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG)) {
+            mHandler.sendEmptyMessage(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG);
+        }
+    }
+
+    void scheduleReportPictureInPictureChangedIfNeeded(TaskRecord task, ActivityStack prevStack) {
+        final ActivityStack stack = task.stack;
+        if (prevStack == null || prevStack == stack
+                || (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
+            return;
+        }
+
+        for (int i = task.mActivities.size() - 1; i >= 0; i--) {
+            final ActivityRecord r = task.mActivities.get(i);
+            if (r.app != null && r.app.thread != null) {
+                mPipModeChangedActivities.add(r);
+            }
+        }
+
+        if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
+            mHandler.sendEmptyMessage(REPORT_PIP_MODE_CHANGED_MSG);
+        }
+    }
+
     private final class ActivityStackSupervisorHandler extends Handler {
 
         public ActivityStackSupervisorHandler(Looper looper) {
@@ -3421,6 +3453,22 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
+                case REPORT_MULTI_WINDOW_MODE_CHANGED_MSG: {
+                    synchronized (mService) {
+                        for (int i = mMultiWindowModeChangedActivities.size() - 1; i >= 0; i--) {
+                            final ActivityRecord r = mMultiWindowModeChangedActivities.remove(i);
+                            r.scheduleMultiWindowChanged();
+                        }
+                    }
+                } break;
+                case REPORT_PIP_MODE_CHANGED_MSG: {
+                    synchronized (mService) {
+                        for (int i = mPipModeChangedActivities.size() - 1; i >= 0; i--) {
+                            final ActivityRecord r = mPipModeChangedActivities.remove(i);
+                            r.schedulePictureInPictureChanged();
+                        }
+                    }
+                } break;
                 case IDLE_TIMEOUT_MSG: {
                     if (DEBUG_IDLE) Slog.d(TAG_IDLE,
                             "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 8a01659..b360b89 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -48,6 +48,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityManagerService.ANIMATE;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
@@ -941,12 +942,8 @@
                 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
                 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
             }
-            if (!mMovedHome
-                    && (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
-                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
-                // Caller wants to appear on home activity, so before starting
-                // their own activity we will bring home to the front.
-                mStartActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
+            if (!mMovedHome) {
+                updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
             }
         } else if (mSourceRecord != null) {
             if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
@@ -997,8 +994,15 @@
                 // activity.
                 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
             }
-            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
-                    mOptions);
+            if (mTargetStack.isFocusable()) {
+                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
+                        mOptions);
+            } else {
+                // If the activity is not focusable, we can't resume it, but still would like to
+                // make sure it becomes visible as it starts (this will also trigger entry
+                // animation). An example of this are PIP activities.
+                mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
+            }
         } else {
             mTargetStack.addRecentActivityLocked(mStartActivity);
         }
@@ -1280,11 +1284,7 @@
                             mOptions, mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
                     mMovedToFront = true;
                 }
-                if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
-                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
-                    // Caller wants to appear on home activity.
-                    intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
-                }
+                updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
                 mOptions = null;
             }
         }
@@ -1301,6 +1301,23 @@
         return intentActivity;
     }
 
+    private void updateTaskReturnToType(
+            TaskRecord task, int launchFlags, ActivityStack focusedStack) {
+        if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
+                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
+            // Caller wants to appear on home activity.
+            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
+            return;
+        } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
+            // Task will be launched over the home stack, so return home.
+            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
+            return;
+        }
+
+        // Else we are coming from an application stack so return to an application.
+        task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
+    }
+
     private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
         if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
@@ -1399,9 +1416,7 @@
             if (mLaunchBounds != null) {
                 final int stackId = mTargetStack.mStackId;
                 if (StackId.resizeStackWithLaunchBounds(stackId)) {
-                    mSupervisor.resizeStackLocked(stackId, mLaunchBounds,
-                            null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
-                            !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */);
+                    mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE);
                 } else {
                     mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
                 }
@@ -1489,9 +1504,7 @@
                 stackId = stack.mStackId;
             }
             if (StackId.resizeStackWithLaunchBounds(stackId)) {
-                mSupervisor.resizeStackLocked(stackId, mLaunchBounds,
-                        null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
-                        !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */);
+                mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE);
             }
         }
         mTargetStack = mInTask.stack;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 97ef10b..28882de 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -81,12 +81,6 @@
     Context mContext;
     PowerManagerInternal mPowerManagerInternal;
 
-    final int UPDATE_CPU = 0x01;
-    final int UPDATE_WIFI = 0x02;
-    final int UPDATE_RADIO = 0x04;
-    final int UPDATE_BT = 0x08;
-    final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
-
     class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
         public static final int MSG_SYNC_EXTERNAL_STATS = 1;
         public static final int MSG_WRITE_TO_DISK = 2;
@@ -133,16 +127,9 @@
         }
 
         @Override
-        public void scheduleSync(String reason) {
+        public void scheduleSync(String reason, int updateFlags) {
             synchronized (this) {
-                scheduleSyncLocked(reason, UPDATE_ALL);
-            }
-        }
-
-        @Override
-        public void scheduleWifiSync(String reason) {
-            synchronized (this) {
-                scheduleSyncLocked(reason, UPDATE_WIFI);
+                scheduleSyncLocked(reason, updateFlags);
             }
         }
 
@@ -194,7 +181,7 @@
     public void shutdown() {
         Slog.w("BatteryStats", "Writing battery stats before shutdown...");
 
-        updateExternalStats("shutdown", UPDATE_ALL);
+        updateExternalStats("shutdown", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
         synchronized (mStats) {
             mStats.shutdownLocked();
         }
@@ -294,7 +281,7 @@
         //Slog.i("foo", "SENDING BATTERY INFO:");
         //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
         Parcel out = Parcel.obtain();
-        updateExternalStats("get-stats", UPDATE_ALL);
+        updateExternalStats("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
         synchronized (mStats) {
             mStats.writeToParcel(out, 0);
         }
@@ -309,7 +296,7 @@
         //Slog.i("foo", "SENDING BATTERY INFO:");
         //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
         Parcel out = Parcel.obtain();
-        updateExternalStats("get-stats", UPDATE_ALL);
+        updateExternalStats("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
         synchronized (mStats) {
             mStats.writeToParcel(out, 0);
         }
@@ -672,7 +659,8 @@
                 final String type = (powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH ||
                         powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active"
                         : "inactive";
-                mHandler.scheduleWifiSync("wifi-data: " + type);
+                mHandler.scheduleSync("wifi-data: " + type,
+                        BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI);
             }
             mStats.noteWifiRadioPowerState(powerState, tsNanos);
         }
@@ -860,13 +848,25 @@
     @Override
     public void noteBleScanStarted(WorkSource ws) {
         enforceCallingPermission();
-        Slog.d(TAG, "BLE scan started for " + ws);
+        synchronized (mStats) {
+            mStats.noteBluetoothScanStartedFromSourceLocked(ws);
+        }
     }
 
     @Override
     public void noteBleScanStopped(WorkSource ws) {
         enforceCallingPermission();
-        Slog.d(TAG, "BLE scan stopped for " + ws);
+        synchronized (mStats) {
+            mStats.noteBluetoothScanStoppedFromSourceLocked(ws);
+        }
+    }
+
+    @Override
+    public void noteResetBleScan() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteResetBluetoothScanLocked();
+        }
     }
 
     public boolean isOnBattery() {
@@ -895,7 +895,7 @@
 
                 // Sync external stats first as the battery has changed states. If we don't sync
                 // immediately here, we may not collect the relevant data later.
-                updateExternalStats("battery-state", UPDATE_ALL);
+                updateExternalStats("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
                 synchronized (mStats) {
                     mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
                 }
@@ -1082,9 +1082,9 @@
                         pw.println("Battery stats reset.");
                         noOutput = true;
                     }
-                    updateExternalStats("dump", UPDATE_ALL);
+                    updateExternalStats("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
                 } else if ("--write".equals(arg)) {
-                    updateExternalStats("dump", UPDATE_ALL);
+                    updateExternalStats("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
                     synchronized (mStats) {
                         mStats.writeSyncLocked();
                         pw.println("Battery stats written.");
@@ -1148,7 +1148,7 @@
                 flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
             }
             // Fetch data from external sources and update the BatteryStatsImpl object with them.
-            updateExternalStats("dump", UPDATE_ALL);
+            updateExternalStats("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -1358,8 +1358,10 @@
      *
      * @param reason The reason why this collection was requested. Useful for debugging.
      * @param updateFlags Which external stats to update. Can be a combination of
-     *                    {@link #UPDATE_CPU}, {@link #UPDATE_RADIO}, {@link #UPDATE_WIFI},
-     *                    and {@link #UPDATE_BT}.
+     *                    {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_CPU},
+     *                    {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_RADIO},
+     *                    {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_WIFI},
+     *                    and {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_BT}.
      */
     void updateExternalStats(final String reason, final int updateFlags) {
         synchronized (mExternalStatsLock) {
@@ -1374,17 +1376,17 @@
             }
 
             WifiActivityEnergyInfo wifiEnergyInfo = null;
-            if ((updateFlags & UPDATE_WIFI) != 0) {
+            if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
                 wifiEnergyInfo = pullWifiEnergyInfoLocked();
             }
 
             ModemActivityInfo modemActivityInfo = null;
-            if ((updateFlags & UPDATE_RADIO) != 0) {
+            if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) {
                 modemActivityInfo = pullModemActivityInfoLocked();
             }
 
             BluetoothActivityEnergyInfo bluetoothEnergyInfo = null;
-            if ((updateFlags & UPDATE_BT) != 0) {
+            if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) {
                 // We only pull bluetooth stats when we have to, as we are not distributing its
                 // use amongst apps and the sampling frequency does not matter.
                 bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked();
@@ -1398,20 +1400,20 @@
                             BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS, reason, 0);
                 }
 
-                if ((updateFlags & UPDATE_CPU) != 0) {
+                if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU) != 0) {
                     mStats.updateCpuTimeLocked();
                     mStats.updateKernelWakelocksLocked();
                 }
 
-                if ((updateFlags & UPDATE_RADIO) != 0) {
+                if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) {
                     mStats.updateMobileRadioStateLocked(elapsedRealtime, modemActivityInfo);
                 }
 
-                if ((updateFlags & UPDATE_WIFI) != 0) {
+                if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
                     mStats.updateWifiStateLocked(wifiEnergyInfo);
                 }
 
-                if ((updateFlags & UPDATE_BT) != 0) {
+                if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) {
                     mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
                 }
             }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index be97c5a..10f0977 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -16,37 +16,7 @@
 
 package com.android.server.am;
 
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.HOME_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
-import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
-import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityManagerService.LOCK_SCREEN_SHOWN;
-import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
-
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManager.StackId;
@@ -55,6 +25,7 @@
 import android.app.ActivityManager.TaskThumbnailInfo;
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
+import android.app.IActivityManager;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -86,6 +57,37 @@
 import java.util.ArrayList;
 import java.util.Objects;
 
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityManagerService.LOCK_SCREEN_SHOWN;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
+
 final class TaskRecord {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
@@ -106,6 +108,7 @@
     private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
     private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
     private static final String ATTR_USERID = "user_id";
+    private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
     private static final String ATTR_EFFECTIVE_UID = "effective_uid";
     private static final String ATTR_TASKTYPE = "task_type";
     private static final String ATTR_FIRSTACTIVETIME = "first_active_time";
@@ -128,8 +131,6 @@
 
     private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
 
-    static final boolean IGNORE_RETURN_TO_RECENTS = true;
-
     static final int INVALID_TASK_ID = -1;
 
     final int taskId;       // Unique identifier for this task.
@@ -157,11 +158,15 @@
 
     String stringName;      // caching of toString() result.
     int userId;             // user for which this task was created
+    boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
+                                // was changed.
 
     int numFullscreen;      // Number of fullscreen activities.
 
     int mResizeMode;        // The resize mode of this task and its activities.
                             // Based on the {@link ActivityInfo#resizeMode} of the root activity.
+    boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
+                                     // changes on a temporary basis.
     int mLockTaskMode;      // Which tasklock mode to launch this task in. One of
                             // ActivityManager.LOCK_TASK_LAUNCH_MODE_*
     private boolean mPrivileged;    // The root activity application of this task holds
@@ -240,6 +245,9 @@
 
     // Bounds of the Task. null for fullscreen tasks.
     Rect mBounds = null;
+    private final Rect mTmpRect = new Rect();
+    private final Rect mTmpRect2 = new Rect();
+
     // Last non-fullscreen bounds the task was launched in or resized to.
     // The information is persisted and used to determine the appropriate stack to launch the
     // task into on restore.
@@ -313,7 +321,8 @@
             boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
             TaskThumbnailInfo lastThumbnailInfo, int taskAffiliation, int prevTaskId,
             int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
-            int resizeMode, boolean privileged, boolean _realActivitySuspended) {
+            int resizeMode, boolean privileged, boolean _realActivitySuspended,
+            boolean userSetupComplete) {
         mService = service;
         mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
                 TaskPersister.IMAGE_EXTENSION;
@@ -336,6 +345,7 @@
         taskType = _taskType;
         mTaskToReturnTo = HOME_ACTIVITY_TYPE;
         userId = _userId;
+        mUserSetupComplete = userSetupComplete;
         effectiveUid = _effectiveUid;
         firstActiveTime = _firstActiveTime;
         lastActiveTime = _lastActiveTime;
@@ -436,6 +446,7 @@
         }
 
         userId = UserHandle.getUserId(info.applicationInfo.uid);
+        mUserSetupComplete = mService.mUserController.isUserSetupCompleteLocked(userId);
         if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
             // If the activity itself has requested auto-remove, then just always do it.
             autoRemoveRecents = true;
@@ -459,8 +470,8 @@
     }
 
     void setTaskToReturnTo(int taskToReturnTo) {
-        mTaskToReturnTo = (IGNORE_RETURN_TO_RECENTS && taskToReturnTo == RECENTS_ACTIVITY_TYPE)
-            ? HOME_ACTIVITY_TYPE : taskToReturnTo;
+        mTaskToReturnTo = (taskToReturnTo == RECENTS_ACTIVITY_TYPE)
+                ? HOME_ACTIVITY_TYPE : taskToReturnTo;
     }
 
     int getTaskToReturnTo() {
@@ -936,7 +947,7 @@
 
     boolean isResizeable() {
         return !isHomeTask() && (mService.mForceResizableActivities
-                || ActivityInfo.isResizeableMode(mResizeMode));
+                || ActivityInfo.isResizeableMode(mResizeMode)) && !mTemporarilyUnresizable;
     }
 
     boolean inCropWindowsResizeMode() {
@@ -1066,6 +1077,7 @@
         out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
         out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
         out.attribute(null, ATTR_USERID, String.valueOf(userId));
+        out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
         out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
         out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
         out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime));
@@ -1135,6 +1147,7 @@
         boolean askedCompatMode = false;
         int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
         int userId = 0;
+        boolean userSetupComplete = true;
         int effectiveUid = -1;
         String lastDescription = null;
         long firstActiveTime = -1;
@@ -1181,6 +1194,8 @@
                 askedCompatMode = Boolean.valueOf(attrValue);
             } else if (ATTR_USERID.equals(attrName)) {
                 userId = Integer.valueOf(attrValue);
+            } else if (ATTR_USER_SETUP_COMPLETE.equals(attrName)) {
+                userSetupComplete = Boolean.valueOf(attrValue);
             } else if (ATTR_EFFECTIVE_UID.equals(attrName)) {
                 effectiveUid = Integer.valueOf(attrValue);
             } else if (ATTR_TASKTYPE.equals(attrName)) {
@@ -1280,7 +1295,7 @@
                 activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
                 taskDescription, thumbnailInfo, taskAffiliation, prevTaskId, nextTaskId,
                 taskAffiliationColor, callingUid, callingPackage, resizeMode, privileged,
-                realActivitySuspended);
+                realActivitySuspended, userSetupComplete);
         task.updateOverrideConfiguration(bounds);
 
         for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
@@ -1293,9 +1308,22 @@
 
     /**
      * Update task's override configuration based on the bounds.
+     * @param bounds The bounds of the task.
      * @return Update configuration or null if there is no change.
      */
     Configuration updateOverrideConfiguration(Rect bounds) {
+        return updateOverrideConfiguration(bounds, null /* insetBounds */);
+    }
+
+    /**
+     * Update task's override configuration based on the bounds.
+     * @param bounds The bounds of the task.
+     * @param insetBounds The bounds used to calculate the system insets, which is used here to
+     *                    subtract the navigation bar/status bar size from the screen size reported
+     *                    to the application. See {@link IActivityManager#resizeDockedStack}.
+     * @return Update configuration or null if there is no change.
+     */
+    Configuration updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
         if (Objects.equals(mBounds, bounds)) {
             return null;
         }
@@ -1318,16 +1346,31 @@
             if (stack == null || StackId.persistTaskBounds(stack.mStackId)) {
                 mLastNonFullscreenBounds = mBounds;
             }
-            mOverrideConfig = calculateOverrideConfig(mBounds);
+
+            // Stable insets need to be subtracted because we also subtract it in the fullscreen
+            // configuration.
+            mTmpRect.set(bounds);
+            subtractStableInsets(mTmpRect, insetBounds != null ? insetBounds : mTmpRect);
+            mOverrideConfig = calculateOverrideConfig(mTmpRect);
         }
 
         if (mFullscreen != oldFullscreen) {
-            reportMultiWindowModeChange();
+            mService.mStackSupervisor.scheduleReportMultiWindowChanged(this);
         }
 
         return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
     }
 
+    private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds) {
+        mTmpRect2.set(inInsetBounds);
+        mService.mWindowManager.subtractStableInsets(mTmpRect2);
+        int leftInset = mTmpRect2.left - inInsetBounds.left;
+        int topInset = mTmpRect2.top - inInsetBounds.top;
+        int rightInset = inInsetBounds.right - mTmpRect2.right;
+        int bottomInset = inInsetBounds.bottom - mTmpRect2.bottom;
+        inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
+    }
+
     Configuration calculateOverrideConfig(Rect bounds) {
         final Configuration serviceConfig = mService.mConfiguration;
         final Configuration config = new Configuration(Configuration.EMPTY);
@@ -1343,8 +1386,9 @@
                 ? Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         final int sl = Configuration.resetScreenLayout(serviceConfig.screenLayout);
-        config.screenLayout = Configuration.reduceScreenLayout(
-                sl, config.screenWidthDp, config.screenHeightDp);
+        int longSize = Math.max(config.screenWidthDp, config.screenHeightDp);
+        int shortSize = Math.min(config.screenWidthDp, config.screenHeightDp);
+        config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
         return config;
     }
 
@@ -1377,40 +1421,6 @@
         return bounds;
     }
 
-    private void reportMultiWindowModeChange() {
-        for (int i = mActivities.size() - 1; i >= 0; i--) {
-            final ActivityRecord r = mActivities.get(i);
-            if (r.app != null && r.app.thread != null) {
-                try {
-                    // An activity is consider to be in multi-window mode if its task isn't
-                    // fullscreen.
-                    r.app.thread.scheduleMultiWindowModeChanged(r.appToken, !mFullscreen);
-                } catch (Exception e) {
-                    Slog.e(TAG, "TaskRecord.reportMultiWindowModeChange: ", e);
-                }
-            }
-        }
-    }
-
-    void reportPictureInPictureModeChangeIfNeeded(ActivityStack prevStack) {
-        if (prevStack == null || prevStack == stack
-                || (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
-            return;
-        }
-
-        for (int i = mActivities.size() - 1; i >= 0; i--) {
-            final ActivityRecord r = mActivities.get(i);
-            if (r.app != null && r.app.thread != null) {
-                try {
-                    r.app.thread.schedulePictureInPictureModeChanged(
-                            r.appToken, stack.mStackId == PINNED_STACK_ID);
-                } catch (Exception e) {
-                    Slog.e(TAG, "TaskRecord.reportMultiWindowModeChange: ", e);
-                }
-            }
-        }
-    }
-
     /** Updates the task's bounds and override configuration to match what is expected for the
      * input stack. */
     void updateOverrideConfigurationForStack(ActivityStack inStack) {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index a21570ce..2f63b2d3 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -24,6 +24,7 @@
 import static android.app.ActivityManager.USER_OP_SUCCESS;
 import static android.content.Context.KEYGUARD_SERVICE;
 import static android.os.Process.SYSTEM_UID;
+import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -45,11 +46,14 @@
 import android.app.IStopUserCallback;
 import android.app.IUserSwitchObserver;
 import android.app.KeyguardManager;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Bundle;
@@ -66,10 +70,12 @@
 import android.os.UserManager;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
+import android.provider.Settings;
 import android.util.IntArray;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.R;
@@ -145,6 +151,34 @@
 
     private final LockPatternUtils mLockPatternUtils;
 
+    // Set of users who have completed the set-up process.
+    private final SparseBooleanArray mSetupCompletedUsers = new SparseBooleanArray();
+    private final UserSetupCompleteContentObserver mUserSetupCompleteContentObserver;
+
+    private class UserSetupCompleteContentObserver extends ContentObserver {
+        private final Uri mUserSetupComplete = Settings.Secure.getUriFor(USER_SETUP_COMPLETE);
+
+        public UserSetupCompleteContentObserver(Handler handler) {
+            super(handler);
+        }
+
+        void register(ContentResolver resolver) {
+            resolver.registerContentObserver(mUserSetupComplete, false, this, UserHandle.USER_ALL);
+            synchronized (mService) {
+                updateCurrentUserSetupCompleteLocked();
+            }
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            if (mUserSetupComplete.equals(uri)) {
+                synchronized (mService) {
+                    updateCurrentUserSetupCompleteLocked();
+                }
+            }
+        }
+    }
+
     UserController(ActivityManagerService service) {
         mService = service;
         mHandler = mService.mHandler;
@@ -154,6 +188,7 @@
         mUserLru.add(UserHandle.USER_SYSTEM);
         mLockPatternUtils = new LockPatternUtils(mService.mContext);
         updateStartedUserArrayLocked();
+        mUserSetupCompleteContentObserver = new UserSetupCompleteContentObserver(mHandler);
     }
 
     void finishUserSwitch(UserState uss) {
@@ -202,11 +237,11 @@
         }
     }
 
-    void finishUserBoot(UserState uss) {
+    private void finishUserBoot(UserState uss) {
         finishUserBoot(uss, null);
     }
 
-    void finishUserBoot(UserState uss, IIntentReceiver resultTo) {
+    private void finishUserBoot(UserState uss, IIntentReceiver resultTo) {
         final int userId = uss.mHandle.getIdentifier();
         synchronized (mService) {
             // Bail if we ended up with a stale user
@@ -424,6 +459,7 @@
                 mStartedUsers.remove(userId);
                 mUserLru.remove(Integer.valueOf(userId));
                 updateStartedUserArrayLocked();
+                mSetupCompletedUsers.delete(userId);
 
                 mService.onUserStoppedLocked(userId);
                 // Clean up all state and processes associated with the user.
@@ -619,6 +655,7 @@
                 final Integer userIdInt = userId;
                 mUserLru.remove(userIdInt);
                 mUserLru.add(userIdInt);
+                updateCurrentUserSetupCompleteLocked();
 
                 if (foreground) {
                     mCurrentUserId = userId;
@@ -711,7 +748,7 @@
                         moveUserToForegroundLocked(uss, oldUserId, userId);
                     }
                 } else {
-                    mService.mStackSupervisor.startBackgroundUserLocked(userId, uss);
+                    mService.mUserController.finishUserBoot(uss);
                 }
 
                 if (needStart) {
@@ -833,6 +870,17 @@
         mUserSwitchObservers.finishBroadcast();
     }
 
+    void updateCurrentUserSetupCompleteLocked() {
+        final ContentResolver cr = mService.mContext.getContentResolver();
+        final boolean setupComplete =
+                Settings.Secure.getIntForUser(cr, USER_SETUP_COMPLETE, 0, mCurrentUserId) != 0;
+        mSetupCompletedUsers.put(mCurrentUserId, setupComplete);
+    }
+
+    boolean isUserSetupCompleteLocked(int userId) {
+        return mSetupCompletedUsers.get(userId);
+    }
+
     private void stopBackgroundUsersIfEnforced(int oldUserId) {
         // Never stop system user
         if (oldUserId == UserHandle.USER_SYSTEM) {
@@ -1141,12 +1189,17 @@
         }
     }
 
+    void onSystemReady() {
+        updateCurrentProfileIdsLocked();
+        mUserSetupCompleteContentObserver.register(mService.mContext.getContentResolver());
+    }
+
     /**
      * Refreshes the list of users related to the current user when either a
      * user switch happens or when a new related user is started in the
      * background.
      */
-    void updateCurrentProfileIdsLocked() {
+    private void updateCurrentProfileIdsLocked() {
         final List<UserInfo> profiles = getUserManager().getProfiles(mCurrentUserId,
                 false /* enabledOnly */);
         int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 64c0891..548f563 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3889,8 +3889,29 @@
             int index;
             if (mIsMuted) {
                 index = 0;
-            } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
-                    || ((device & mFullVolumeDevices) != 0)) {
+            } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) {
+                /* Special handling for Bluetooth Absolute Volume scenario
+                 * If we send full audio gain, some accessories are too loud even at its lowest
+                 * volume. We are not able to enumerate all such accessories, so here is the
+                 * workaround from phone side.
+                 * For the lowest volume steps 1 and 2, restrict audio gain to 50% and 75%.
+                 * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
+                 */
+                int i = (getIndex(device) + 5)/10;
+                if (i == 0) {
+                    // 0% for volume 0
+                    index = 0;
+                } else if (i == 1) {
+                    // 50% for volume 1
+                    index = (int)(mIndexMax * 0.5) /10;
+                } else if (i == 2) {
+                    // 75% for volume 2
+                    index = (int)(mIndexMax * 0.75) /10;
+                } else {
+                    // otherwise, full gain
+                    index = (mIndexMax + 5)/10;
+                }
+            } else if ((device & mFullVolumeDevices) != 0) {
                 index = (mIndexMax + 5)/10;
             } else {
                 index = (getIndex(device) + 5)/10;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index a73a67a..760b218 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -451,7 +451,7 @@
                 ((BluetoothPan) proxy).setBluetoothTethering(enable);
                 // TODO: Enabling bluetooth tethering can fail asynchronously here.
                 // We should figure out a way to bubble up that failure instead of sending success.
-                int result = ((BluetoothPan) proxy).isTetheringOn() ?
+                int result = ((BluetoothPan) proxy).isTetheringOn() == enable ?
                         ConnectivityManager.TETHER_ERROR_NO_ERROR :
                         ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
                 sendTetherResult(receiver, result);
diff --git a/services/core/java/com/android/server/content/AppIdleMonitor.java b/services/core/java/com/android/server/content/AppIdleMonitor.java
deleted file mode 100644
index 2d768d8..0000000
--- a/services/core/java/com/android/server/content/AppIdleMonitor.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.content;
-
-import android.app.usage.UsageStatsManagerInternal;
-import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
-import android.os.UserHandle;
-
-import com.android.server.LocalServices;
-
-/**
- * Helper to listen for app idle and charging status changes and restart backed off
- * sync operations.
- */
-class AppIdleMonitor extends AppIdleStateChangeListener {
-
-    private final SyncManager mSyncManager;
-    private final UsageStatsManagerInternal mUsageStats;
-    private boolean mAppIdleParoleOn;
-
-    AppIdleMonitor(SyncManager syncManager) {
-        mSyncManager = syncManager;
-        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
-        mAppIdleParoleOn = mUsageStats.isAppIdleParoleOn();
-
-        mUsageStats.addAppIdleStateChangeListener(this);
-    }
-
-    void setAppIdleParoleOn(boolean appIdleParoleOn) {
-        if (mAppIdleParoleOn == appIdleParoleOn) {
-            return;
-        }
-        mAppIdleParoleOn = appIdleParoleOn;
-        if (mAppIdleParoleOn) {
-            mSyncManager.onAppNotIdle(null, UserHandle.USER_ALL);
-        }
-    }
-
-    boolean isAppIdle(String packageName, int uidForAppId, int userId) {
-        return !mAppIdleParoleOn && mUsageStats.isAppIdle(packageName, uidForAppId, userId);
-    }
-
-    @Override
-    public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
-        // Don't care if the app is becoming idle
-        if (idle) return;
-        mSyncManager.onAppNotIdle(packageName, userId);
-    }
-
-    @Override
-    public void onParoleStateChanged(boolean isParoleOn) {
-        setAppIdleParoleOn(isParoleOn);
-    }
-}
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index f72b1c3..212e077 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -126,7 +126,7 @@
                 for (int i=0; i<sorted.size(); i++) {
                     int pid = sorted.get(i);
                     pw.print("  pid "); pw.print(pid); pw.print(": ");
-                            pw.print(pidCounts.get(pid)); pw.println(" observers");
+                    pw.print(pidCounts.get(pid)); pw.println(" observers");
                 }
                 pw.println();
                 pw.print(" Total number of nodes: "); pw.println(counts[0]);
@@ -162,11 +162,11 @@
                 PackageManagerInternal.class);
         packageManagerInternal.setSyncAdapterPackagesprovider(
                 new PackageManagerInternal.SyncAdapterPackagesProvider() {
-            @Override
-            public String[] getPackages(String authority, int userId) {
-                return getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
-            }
-        });
+                    @Override
+                    public String[] getPackages(String authority, int userId) {
+                        return getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
+                    }
+                });
     }
 
     public void systemReady() {
@@ -183,7 +183,7 @@
      */
     @Override
     public void registerContentObserver(Uri uri, boolean notifyForDescendants,
-            IContentObserver observer, int userHandle) {
+                                        IContentObserver observer, int userHandle) {
         if (observer == null || uri == null) {
             throw new IllegalArgumentException("You must pass a valid uri and observer");
         }
@@ -218,7 +218,7 @@
     }
 
     public void registerContentObserver(Uri uri, boolean notifyForDescendants,
-            IContentObserver observer) {
+                                        IContentObserver observer) {
         registerContentObserver(uri, notifyForDescendants, observer,
                 UserHandle.getCallingUserId());
     }
@@ -243,8 +243,8 @@
      */
     @Override
     public void notifyChange(Uri uri, IContentObserver observer,
-            boolean observerWantsSelfNotifications, boolean syncToNetwork,
-            int userHandle) {
+                             boolean observerWantsSelfNotifications, boolean syncToNetwork,
+                             int userHandle) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
                     + " from observer " + observer + ", syncToNetwork " + syncToNetwork);
@@ -318,7 +318,7 @@
     }
 
     public void notifyChange(Uri uri, IContentObserver observer,
-            boolean observerWantsSelfNotifications, boolean syncToNetwork) {
+                             boolean observerWantsSelfNotifications, boolean syncToNetwork) {
         notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
                 UserHandle.getCallingUserId());
     }
@@ -400,14 +400,14 @@
                 SyncStorageEngine.EndPoint info;
                 info = new SyncStorageEngine.EndPoint(
                         request.getAccount(), request.getProvider(), userId);
-                if (runAtTime < 60) {
+                if (runAtTime < 3600) {
                     Slog.w(TAG, "Requested poll frequency of " + runAtTime
-                            + " seconds being rounded up to 60 seconds.");
-                    runAtTime = 60;
+                            + " seconds being rounded up to 1 hour.");
+                    runAtTime = 3600;
                 }
                 // Schedule periodic sync.
-                getSyncManager().getSyncStorageEngine()
-                    .updateOrAddPeriodicSync(info, runAtTime, flextime, extras);
+                getSyncManager().updateOrAddPeriodicSync(info, runAtTime,
+                        flextime, extras);
             } else {
                 long beforeRuntimeMillis = (flextime) * 1000;
                 long runtimeMillis = runAtTime * 1000;
@@ -450,7 +450,7 @@
      */
     @Override
     public void cancelSyncAsUser(Account account, String authority, ComponentName cname,
-            int userId) {
+                                 int userId) {
         if (authority != null && authority.length() == 0) {
             throw new IllegalArgumentException("Authority must be non-empty");
         }
@@ -459,15 +459,15 @@
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
         long identityToken = clearCallingIdentity();
+        if (cname != null) {
+            Slog.e(TAG, "cname not null.");
+            return;
+        }
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
                 SyncStorageEngine.EndPoint info;
-                if (cname == null) {
-                    info = new SyncStorageEngine.EndPoint(account, authority, userId);
-                } else {
-                    info = new SyncStorageEngine.EndPoint(cname, userId, -1);
-                }
+                info = new SyncStorageEngine.EndPoint(account, authority, userId);
                 syncManager.clearScheduledSyncOperations(info);
                 syncManager.cancelActiveSync(info, null /* all syncs for this adapter */);
             }
@@ -492,7 +492,7 @@
                 // Remove periodic sync.
                 mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                         "no permission to write the sync settings");
-                getSyncManager().getSyncStorageEngine().removePeriodicSync(info, extras);
+                getSyncManager().removePeriodicSync(info, extras);
             }
             // Cancel active syncs and clear pending syncs from the queue.
             syncManager.cancelScheduledSyncOperation(info, extras);
@@ -585,7 +585,7 @@
 
     @Override
     public void setSyncAutomaticallyAsUser(Account account, String providerName, boolean sync,
-            int userId) {
+                                           int userId) {
         if (TextUtils.isEmpty(providerName)) {
             throw new IllegalArgumentException("Authority must be non-empty");
         }
@@ -606,10 +606,10 @@
         }
     }
 
-    /** Old API. Schedule periodic sync with default flex time. */
+    /** Old API. Schedule periodic sync with default flexMillis time. */
     @Override
     public void addPeriodicSync(Account account, String authority, Bundle extras,
-            long pollFrequency) {
+                                long pollFrequency) {
         if (account == null) {
             throw new IllegalArgumentException("Account must not be null");
         }
@@ -620,10 +620,10 @@
                 "no permission to write the sync settings");
 
         int userId = UserHandle.getCallingUserId();
-        if (pollFrequency < 60) {
+        if (pollFrequency < 3600) {
             Slog.w(TAG, "Requested poll frequency of " + pollFrequency
-                    + " seconds being rounded up to 60 seconds.");
-            pollFrequency = 60;
+                    + " seconds being rounded up to 1 hour.");
+            pollFrequency = 3600;
         }
         long defaultFlex = SyncStorageEngine.calculateDefaultFlexTime(pollFrequency);
 
@@ -631,11 +631,8 @@
         try {
             SyncStorageEngine.EndPoint info =
                     new SyncStorageEngine.EndPoint(account, authority, userId);
-            getSyncManager().getSyncStorageEngine()
-                .updateOrAddPeriodicSync(info,
-                        pollFrequency,
-                        defaultFlex,
-                        extras);
+            getSyncManager().updateOrAddPeriodicSync(info, pollFrequency,
+                    defaultFlex, extras);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -654,10 +651,10 @@
         int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
-            getSyncManager().getSyncStorageEngine()
-                .removePeriodicSync(
-                        new SyncStorageEngine.EndPoint(account, authority, userId),
-                        extras);
+            getSyncManager()
+                    .removePeriodicSync(
+                            new SyncStorageEngine.EndPoint(account, authority, userId),
+                            extras);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -665,7 +662,7 @@
 
 
     public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName,
-            ComponentName cname) {
+                                               ComponentName cname) {
         if (account == null) {
             throw new IllegalArgumentException("Account must not be null");
         }
@@ -678,7 +675,7 @@
         int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
-            return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
+            return getSyncManager().getPeriodicSyncs(
                     new SyncStorageEngine.EndPoint(account, providerName, userId));
         } finally {
             restoreCallingIdentity(identityToken);
@@ -836,7 +833,7 @@
      * INTERACT_ACROSS_USERS_FULL permission.
      */
     public SyncStatusInfo getSyncStatusAsUser(Account account, String authority,
-            ComponentName cname, int userId) {
+                                              ComponentName cname, int userId) {
         if (TextUtils.isEmpty(authority)) {
             throw new IllegalArgumentException("Authority must not be empty");
         }
@@ -871,7 +868,7 @@
 
     @Override
     public boolean isSyncPendingAsUser(Account account, String authority, ComponentName cname,
-            int userId) {
+                                       int userId) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
         enforceCrossUserPermission(userId,
@@ -954,7 +951,7 @@
             private final Object observersLock;
 
             public ObserverEntry(IContentObserver o, boolean n, Object observersLock,
-                    int _uid, int _pid, int _userHandle) {
+                                 int _uid, int _pid, int _userHandle) {
                 this.observersLock = observersLock;
                 observer = o;
                 uid = _uid;
@@ -975,14 +972,14 @@
             }
 
             public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
-                    String name, String prefix, SparseIntArray pidCounts) {
+                                   String name, String prefix, SparseIntArray pidCounts) {
                 pidCounts.put(pid, pidCounts.get(pid)+1);
                 pw.print(prefix); pw.print(name); pw.print(": pid=");
-                        pw.print(pid); pw.print(" uid=");
-                        pw.print(uid); pw.print(" user=");
-                        pw.print(userHandle); pw.print(" target=");
-                        pw.println(Integer.toHexString(System.identityHashCode(
-                                observer != null ? observer.asBinder() : null)));
+                pw.print(pid); pw.print(" uid=");
+                pw.print(uid); pw.print(" user=");
+                pw.print(userHandle); pw.print(" target=");
+                pw.println(Integer.toHexString(System.identityHashCode(
+                        observer != null ? observer.asBinder() : null)));
             }
         }
 
@@ -999,7 +996,7 @@
         }
 
         public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
-                String name, String prefix, int[] counts, SparseIntArray pidCounts) {
+                               String name, String prefix, int[] counts, SparseIntArray pidCounts) {
             String innerName = null;
             if (mObservers.size() > 0) {
                 if ("".equals(name)) {
@@ -1050,15 +1047,15 @@
 
         // Invariant:  userHandle is either a hard user number or is USER_ALL
         public void addObserverLocked(Uri uri, IContentObserver observer,
-                boolean notifyForDescendants, Object observersLock,
-                int uid, int pid, int userHandle) {
+                                      boolean notifyForDescendants, Object observersLock,
+                                      int uid, int pid, int userHandle) {
             addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock,
                     uid, pid, userHandle);
         }
 
         private void addObserverLocked(Uri uri, int index, IContentObserver observer,
-                boolean notifyForDescendants, Object observersLock,
-                int uid, int pid, int userHandle) {
+                                       boolean notifyForDescendants, Object observersLock,
+                                       int uid, int pid, int userHandle) {
             // If this is the leaf node add the observer
             if (index == countUriSegments(uri)) {
                 mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,
@@ -1118,8 +1115,8 @@
         }
 
         private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
-                boolean observerWantsSelfNotifications, int targetUserHandle,
-                ArrayList<ObserverCall> calls) {
+                                              boolean observerWantsSelfNotifications, int targetUserHandle,
+                                              ArrayList<ObserverCall> calls) {
             int N = mObservers.size();
             IBinder observerBinder = observer == null ? null : observer.asBinder();
             for (int i = 0; i < N; i++) {
@@ -1148,8 +1145,8 @@
          * 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 targetUserHandle,
+                                           ArrayList<ObserverCall> calls) {
             String segment = null;
             int segmentCount = countUriSegments(uri);
             if (index >= segmentCount) {
diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
new file mode 100644
index 0000000..a621d73
--- /dev/null
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.content;
+
+import android.app.job.JobParameters;
+import android.app.job.JobService;
+import android.content.Intent;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+
+public class SyncJobService extends JobService {
+    private static final String TAG = "SyncManager";
+
+    public static final String EXTRA_MESSENGER = "messenger";
+
+    private Messenger mMessenger;
+    private SparseArray<JobParameters> jobParamsMap = new SparseArray<JobParameters>();
+
+    /**
+     * This service is started by the SyncManager which passes a messenger object to
+     * communicate back with it. It never stops while the device is running.
+     */
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        mMessenger = intent.getParcelableExtra(EXTRA_MESSENGER);
+        Message m = Message.obtain();
+        m.what = SyncManager.SyncHandler.MESSAGE_JOBSERVICE_OBJECT;
+        m.obj = this;
+        sendMessage(m);
+
+        return START_NOT_STICKY;
+    }
+
+    private void sendMessage(Message message) {
+        if (mMessenger == null) {
+            Slog.e(TAG, "Messenger not initialized.");
+            return;
+        }
+        try {
+            mMessenger.send(message);
+        } catch (RemoteException e) {
+            Slog.e(TAG, e.toString());
+        }
+    }
+
+    @Override
+    public boolean onStartJob(JobParameters params) {
+        boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
+        synchronized (jobParamsMap) {
+            jobParamsMap.put(params.getJobId(), params);
+        }
+        Message m = Message.obtain();
+        m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC;
+        SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
+        if (op == null) {
+            Slog.e(TAG, "Got invalid job " + params.getJobId());
+            return false;
+        }
+        if (isLoggable) {
+            Slog.v(TAG, "Got start job message " + op.target);
+        }
+        m.obj = op;
+        sendMessage(m);
+        return true;
+    }
+
+    @Override
+    public boolean onStopJob(JobParameters params) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Slog.v(TAG, "onStopJob called " + params.getJobId() + ", reason: "
+                    + params.getStopReason());
+        }
+
+        synchronized (jobParamsMap) {
+            jobParamsMap.remove(params.getJobId());
+        }
+        Message m = Message.obtain();
+        m.what = SyncManager.SyncHandler.MESSAGE_STOP_SYNC;
+        m.obj = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
+        if (m.obj == null) {
+            return false;
+        }
+
+        // Reschedule if this job was NOT explicitly canceled.
+        m.arg1 = params.getStopReason() != JobParameters.REASON_CANCELED ? 1 : 0;
+        // Apply backoff only if stop is called due to timeout.
+        m.arg2 = params.getStopReason() == JobParameters.REASON_TIMEOUT ? 1 : 0;
+
+        sendMessage(m);
+        return false;
+    }
+
+    public void callJobFinished(int jobId, boolean needsReschedule) {
+        synchronized (jobParamsMap) {
+            JobParameters params = jobParamsMap.get(jobId);
+            if (params != null) {
+                jobFinished(params, needsReschedule);
+                jobParamsMap.remove(jobId);
+            } else {
+                Slog.e(TAG, "Job params not found for " + String.valueOf(jobId));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 2eb9095..daf839a 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -19,23 +19,20 @@
 import android.accounts.Account;
 import android.accounts.AccountAndUser;
 import android.accounts.AccountManager;
-import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
-import android.app.AlarmManager;
 import android.app.AppGlobals;
-import android.app.IUidObserver;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.ISyncAdapter;
 import android.content.ISyncContext;
-import android.content.ISyncServiceAdapter;
-import android.content.ISyncStatusObserver;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.PeriodicSync;
@@ -73,47 +70,70 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.WorkSource;
+import android.os.Messenger;
 import android.provider.Settings;
 import android.text.format.DateUtils;
 import android.text.format.Time;
-import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.Slog;
 import android.util.Pair;
 
-import android.util.Slog;
+import android.util.SparseArray;
 import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.DeviceIdleController;
-import com.android.server.LocalServices;
 import com.android.server.accounts.AccountManagerService;
 import com.android.server.content.SyncStorageEngine.AuthorityInfo;
 import com.android.server.content.SyncStorageEngine.EndPoint;
 import com.android.server.content.SyncStorageEngine.OnSyncRequestListener;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Random;
+import java.util.List;
+import java.util.HashSet;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.Objects;
-import java.util.Random;
-import java.util.Set;
 
 /**
+ * Implementation details:
+ * All scheduled syncs will be passed on to JobScheduler as jobs
+ * (See {@link #scheduleSyncOperationH(SyncOperation, long)}. This function schedules a job
+ * with JobScheduler with appropriate delay and constraints (according to backoffs and extras).
+ * A local copy of each scheduled SyncOperation object is stored in {@link mScheduledSyncs}.This
+ * acts as a cache, so that we don't have to query JobScheduler every time we want to get a list of
+ * all scheduled operations. The scheduleSyncOperationH function also assigns a unique jobId to each
+ * SyncOperation.
+ *
+ * Periodic Syncs:
+ * Each periodic sync is scheduled as a periodic job. If a periodic sync fails, we create a new
+ * one off SyncOperation and set its {@link SyncOperation#sourcePeriodicId} field to the jobId of the
+ * periodic sync. We don't allow the periodic job to run while any job initiated by it is pending.
+ *
+ * Backoffs:
+ * Each {@link EndPoint} has a backoff associated with it. When a SyncOperation fails, we increase
+ * the backoff on the authority. Then we reschedule all syncs associated with that authority to
+ * run at a later time. Similarly, when a sync succeeds, backoff is cleared and all associated syncs
+ * are rescheduled. A rescheduled sync will get a new jobId.
+ *
+ * State of {@link mScheduledSyncs}:
+ * Every one-off SyncOperation will be put into this SparseArray when it is scheduled with
+ * JobScheduler. And it will be removed once JobScheduler has started the job. Periodic syncs work
+ * differently. They will always be present in mScheduledSyncs until the periodic sync is removed.
+ * This is to ensure that if a request to add a periodic sync comes in, we add a new one only if a
+ * duplicate doesn't exist. At every point of time, mScheduledSyncs and JobScheduler will show the
+ * same pending syncs.
+ *
  * @hide
  */
 public class SyncManager {
@@ -122,30 +142,11 @@
     /** Delay a sync due to local changes this long. In milliseconds */
     private static final long LOCAL_SYNC_DELAY;
 
-    /**
-     * If a sync takes longer than this and the sync queue is not empty then we will
-     * cancel it and add it back to the end of the sync queue. In milliseconds.
-     */
-    private static final long MAX_TIME_PER_SYNC;
-
     static {
-        final boolean isLargeRAM = !ActivityManager.isLowRamDeviceStatic();
-        int defaultMaxInitSyncs = isLargeRAM ? 5 : 2;
-        int defaultMaxRegularSyncs = isLargeRAM ? 2 : 1;
-        MAX_SIMULTANEOUS_INITIALIZATION_SYNCS =
-                SystemProperties.getInt("sync.max_init_syncs", defaultMaxInitSyncs);
-        MAX_SIMULTANEOUS_REGULAR_SYNCS =
-                SystemProperties.getInt("sync.max_regular_syncs", defaultMaxRegularSyncs);
         LOCAL_SYNC_DELAY =
                 SystemProperties.getLong("sync.local_sync_delay", 30 * 1000 /* 30 seconds */);
-        MAX_TIME_PER_SYNC =
-                SystemProperties.getLong("sync.max_time_per_sync", 5 * 60 * 1000 /* 5 minutes */);
-        SYNC_NOTIFICATION_DELAY =
-                SystemProperties.getLong("sync.notification_delay", 30 * 1000 /* 30 seconds */);
     }
 
-    private static final long SYNC_NOTIFICATION_DELAY;
-
     /**
      * When retrying a sync for the first time use this delay. After that
      * the retry time will double until it reached MAX_SYNC_RETRY_TIME.
@@ -164,11 +165,6 @@
     private static final int DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS = 10;
 
     /**
-     * How long to wait before considering an active sync to have timed-out, and cancelling it.
-     */
-    private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000;  // 30 mins
-
-    /**
      * How often to periodically poll network traffic for an adapter performing a sync to determine
      * whether progress is being made.
      */
@@ -185,21 +181,30 @@
      * How long to delay each queued {@link SyncHandler} message that may have occurred before boot
      * or befor the device became provisioned.
      */
-    private static final long PER_SYNC_BOOT_DELAY_MILLIS = 3000L;  // 3 seconds
+    private static final long PER_SYNC_BOOT_DELAY_MILLIS = 1000L;  // 1 second
 
     /**
      * The maximum amount of time we're willing to delay syncs out of boot, after device has been
      * provisioned, etc.
      */
-    private static final long MAX_SYNC_BOOT_DELAY_MILLIS = 120000L;  // 2 minutes
+    private static final long MAX_SYNC_BOOT_DELAY_MILLIS = 60000L;  // 1 minute
+
+    /**
+     * If a previously scheduled sync becomes ready and we are low on storage, it gets
+     * pushed back for this amount of time.
+     */
+    private static final long SYNC_DELAY_ON_LOW_STORAGE = 60*60*1000;   // 1 hour
+
+    /**
+     * If a sync becomes ready and it conflicts with an already running sync, it gets
+     * pushed back for this amount of time.
+     */
+    private static final long SYNC_DELAY_ON_CONFLICT = 10*1000; // 10 seconds
 
     private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
     private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
     private static final String SYNC_LOOP_WAKE_LOCK = "SyncLoopWakeLock";
 
-    private static final int MAX_SIMULTANEOUS_REGULAR_SYNCS;
-    private static final int MAX_SIMULTANEOUS_INITIALIZATION_SYNCS;
-
     private Context mContext;
 
     private static final AccountAndUser[] INITIAL_ACCOUNTS_ARRAY = new AccountAndUser[0];
@@ -215,30 +220,59 @@
     volatile private boolean mReportedSyncActive = false;
 
     private final NotificationManager mNotificationMgr;
-    private AlarmManager mAlarmService = null;
     private final IBatteryStats mBatteryStats;
+    private JobScheduler mJobScheduler;
+    private SyncJobService mSyncJobService;
 
     private SyncStorageEngine mSyncStorageEngine;
 
-    @GuardedBy("mSyncQueue")
-    private final SyncQueue mSyncQueue;
-
     protected final ArrayList<ActiveSyncContext> mActiveSyncContexts = Lists.newArrayList();
 
-    // set if the sync active indicator should be reported
-    private boolean mNeedSyncActiveNotification = false;
-
-    private final PendingIntent mSyncAlarmIntent;
     // Synchronized on "this". Instead of using this directly one should instead call
     // its accessor, getConnManager().
     private ConnectivityManager mConnManagerDoNotUseDirectly;
 
     /** Track whether the device has already been provisioned. */
-    private boolean mProvisioned;
+    private volatile boolean mProvisioned;
 
     protected SyncAdaptersCache mSyncAdapters;
 
-    private final AppIdleMonitor mAppIdleMonitor;
+    // Cache of all operations scheduled on the JobScheduler so that JobScheduler doesn't have
+    // to be queried often.
+    private SparseArray<SyncOperation> mScheduledSyncs = new SparseArray<SyncOperation>(32);
+    private final Random mRand;
+
+    private int getUnusedJobId() {
+        synchronized (mScheduledSyncs) {
+            int newJobId = mRand.nextInt(Integer.MAX_VALUE);
+            while (mScheduledSyncs.indexOfKey(newJobId) >= 0) {
+                newJobId = mRand.nextInt(Integer.MAX_VALUE);
+            }
+            return newJobId;
+        }
+    }
+
+    private void addSyncOperationToCache(SyncOperation op) {
+        synchronized (mScheduledSyncs) {
+            mScheduledSyncs.put(op.jobId, op);
+        }
+    }
+
+    private void removeSyncOperationFromCache(int jobId) {
+        synchronized (mScheduledSyncs) {
+            mScheduledSyncs.remove(jobId);
+        }
+    }
+
+    private List<SyncOperation> getAllPendingSyncsFromCache() {
+        synchronized (mScheduledSyncs) {
+            List<SyncOperation> pending = new ArrayList<SyncOperation>(mScheduledSyncs.size());
+            for (int i=0; i<mScheduledSyncs.size(); i++) {
+                pending.add(mScheduledSyncs.valueAt(i));
+            }
+            return pending;
+        }
+    }
 
     private final BroadcastReceiver mStorageIntentReceiver =
             new BroadcastReceiver() {
@@ -247,7 +281,7 @@
                     String action = intent.getAction();
                     if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(action)) {
                         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "Internal storage is low.");
+                            Slog.v(TAG, "Internal storage is low.");
                         }
                         mStorageIsLow = true;
                         cancelActiveSync(
@@ -255,39 +289,20 @@
                                 null /* any sync */);
                     } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
                         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "Internal storage is ok.");
+                            Slog.v(TAG, "Internal storage is ok.");
                         }
                         mStorageIsLow = false;
-                        sendCheckAlarmsMessage();
+                        rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL);
                     }
                 }
             };
 
-    private final BroadcastReceiver mDeviceIdleReceiver = new BroadcastReceiver() {
-        @Override public void onReceive(Context context, Intent intent) {
-            boolean idle = mPowerManager.isDeviceIdleMode()
-                    || mPowerManager.isLightDeviceIdleMode();
-            mDeviceIsIdle = idle;
-            if (idle) {
-                cancelActiveSync(
-                        SyncStorageEngine.EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL,
-                        null /* any sync */);
-            } else {
-                if (mLocalDeviceIdleController != null) {
-                    if (!mReportedSyncActive) {
-                        mReportedSyncActive = true;
-                        mLocalDeviceIdleController.setSyncActive(true);
-                    }
-                }
-                sendCheckAlarmsMessage();
-            }
-        }
-    };
-
     private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             mBootCompleted = true;
+            // Called because it gets all pending jobs and stores them in mScheduledSyncs cache.
+            verifyJobScheduler();
             mSyncHandler.onBootCompleted();
         }
     };
@@ -295,39 +310,15 @@
     private final BroadcastReceiver mAccountsUpdatedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            updateRunningAccounts();
-
-            // Kick off sync for everyone, since this was a radical account change
-            scheduleSync(null, UserHandle.USER_ALL, SyncOperation.REASON_ACCOUNTS_UPDATED, null,
-                    null, 0 /* no delay */, 0/* no delay */, false);
-        }
-    };
-
-    private final IUidObserver mUidObserver = new IUidObserver.Stub() {
-        @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
-        }
-
-        @Override public void onUidGone(int uid) throws RemoteException {
-        }
-
-        @Override public void onUidActive(int uid) throws RemoteException {
-        }
-
-        @Override public void onUidIdle(int uid) throws RemoteException {
-            cancelSyncsForUid(uid);
+            updateRunningAccounts(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL
+                        /* sync all targets */);
         }
     };
 
     private final PowerManager mPowerManager;
-    DeviceIdleController.LocalService mLocalDeviceIdleController;
-
-    // Use this as a random offset to seed all periodic syncs.
-    private int mSyncRandomOffsetMillis;
 
     private final UserManager mUserManager;
 
-    private static final long SYNC_ALARM_TIMEOUT_MIN = 30 * 1000; // 30 seconds
-
     private List<UserInfo> getAllUsers() {
         return mUserManager.getUsers();
     }
@@ -344,10 +335,13 @@
         return found;
     }
 
-    public void updateRunningAccounts() {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_ACCOUNTS_UPDATED");
+    /** target indicates endpoints that should be synced after account info is updated. */
+    private void updateRunningAccounts(EndPoint target) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "sending MESSAGE_ACCOUNTS_UPDATED");
         // Update accounts in handler thread.
-        mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_ACCOUNTS_UPDATED);
+        Message m = mSyncHandler.obtainMessage(SyncHandler.MESSAGE_ACCOUNTS_UPDATED);
+        m.obj = target;
+        m.sendToTarget();
     }
 
     private void doDatabaseCleanup() {
@@ -356,32 +350,35 @@
             if (user.partial) continue;
             Account[] accountsForUser = AccountManagerService.getSingleton().getAccounts(
                     user.id, mContext.getOpPackageName());
+
             mSyncStorageEngine.doDatabaseCleanup(accountsForUser, user.id);
         }
     }
 
     private BroadcastReceiver mConnectivityIntentReceiver =
             new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final boolean wasConnected = mDataConnectionIsConnected;
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    final boolean wasConnected = mDataConnectionIsConnected;
 
-            // don't use the intent to figure out if network is connected, just check
-            // ConnectivityManager directly.
-            mDataConnectionIsConnected = readDataConnectionState();
-            if (mDataConnectionIsConnected) {
-                if (!wasConnected) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "Reconnection detected: clearing all backoffs");
-                    }
-                    synchronized (mSyncQueue) {
-                        mSyncStorageEngine.clearAllBackoffsLocked(mSyncQueue);
+                    // Don't use the intent to figure out if network is connected, just check
+                    // ConnectivityManager directly.
+                    mDataConnectionIsConnected = readDataConnectionState();
+                    if (mDataConnectionIsConnected) {
+                        if (!wasConnected) {
+                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                                Slog.v(TAG, "Reconnection detected: clearing all backoffs");
+                            }
+                        }
+                        clearAllBackoffs();
                     }
                 }
-                sendCheckAlarmsMessage();
-            }
-        }
-    };
+            };
+
+    private void clearAllBackoffs() {
+        mSyncStorageEngine.clearAllBackoffsLocked();
+        rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL);
+    }
 
     private boolean readDataConnectionState() {
         NetworkInfo networkInfo = getConnectivityManager().getActiveNetworkInfo();
@@ -390,12 +387,12 @@
 
     private BroadcastReceiver mShutdownIntentReceiver =
             new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            Log.w(TAG, "Writing sync state before shutdown...");
-            getSyncStorageEngine().writeAllState();
-        }
-    };
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    Log.w(TAG, "Writing sync state before shutdown...");
+                    getSyncStorageEngine().writeAllState();
+                }
+            };
 
     private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
         @Override
@@ -414,7 +411,6 @@
         }
     };
 
-    private static final String ACTION_SYNC_ALARM = "android.content.syncmanager.SYNC_ALARM";
     private final SyncHandler mSyncHandler;
 
     private volatile boolean mBootCompleted = false;
@@ -429,6 +425,37 @@
         }
     }
 
+    private synchronized void verifyJobScheduler() {
+        if (mJobScheduler != null) {
+            return;
+        }
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.d(TAG, "initializing JobScheduler object.");
+        }
+        mJobScheduler = (JobScheduler) mContext.getSystemService(
+                Context.JOB_SCHEDULER_SERVICE);
+        // Get all persisted syncs from JobScheduler
+        List<JobInfo> pendingJobs = mJobScheduler.getAllPendingJobs();
+        synchronized (mScheduledSyncs) {
+            for (JobInfo job : pendingJobs) {
+                SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras());
+                if (op != null) {
+                    mScheduledSyncs.put(op.jobId, op);
+                    if (!op.isPeriodic) {
+                        // Set the pending status of this EndPoint to true. Pending icon is
+                        // shown on the settings activity.
+                        mSyncStorageEngine.markPending(op.target, true);
+                    }
+                }
+            }
+        }
+    }
+
+    private JobScheduler getJobScheduler() {
+        verifyJobScheduler();
+        return mJobScheduler;
+    }
+
     /**
      * Should only be created after {@link ContentService#systemReady()} so that
      * {@link PackageManager} is ready to query.
@@ -443,21 +470,30 @@
         mSyncStorageEngine.setOnSyncRequestListener(new OnSyncRequestListener() {
             @Override
             public void onSyncRequest(SyncStorageEngine.EndPoint info, int reason, Bundle extras) {
-                if (info.target_provider) {
-                    scheduleSync(info.account, info.userId, reason, info.provider, extras,
-                        0 /* no flex */,
+                scheduleSync(info.account, info.userId, reason, info.provider, extras,
+                        0 /* no flexMillis */,
                         0 /* run immediately */,
                         false);
-                } else if (info.target_service) {
-                    scheduleSync(info.service, info.userId, reason, extras,
-                            0 /* no flex */,
-                            0 /* run immediately */);
-                }
+            }
+        });
+
+        mSyncStorageEngine.setPeriodicSyncAddedListener(
+                new SyncStorageEngine.PeriodicSyncAddedListener() {
+            @Override
+            public void onPeriodicSyncAdded(EndPoint target, Bundle extras, long pollFrequency,
+                                            long flex) {
+                updateOrAddPeriodicSync(target, pollFrequency, flex, extras);
+            }
+        });
+
+        mSyncStorageEngine.setOnAuthorityRemovedListener(new SyncStorageEngine.OnAuthorityRemovedListener() {
+            @Override
+            public void onAuthorityRemoved(EndPoint removedAuthority) {
+                removeSyncsForAuthority(removedAuthority);
             }
         });
 
         mSyncAdapters = new SyncAdaptersCache(mContext);
-        mSyncQueue = new SyncQueue(mContext.getPackageManager(), mSyncStorageEngine, mSyncAdapters);
 
         mSyncHandler = new SyncHandler(BackgroundThread.get().getLooper());
 
@@ -473,10 +509,7 @@
             }
         }, mSyncHandler);
 
-        mSyncAlarmIntent = PendingIntent.getBroadcast(
-                mContext, 0 /* ignored */, new Intent(ACTION_SYNC_ALARM), 0);
-
-        mAppIdleMonitor = new AppIdleMonitor(this);
+        mRand = new Random(System.currentTimeMillis());
 
         IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
         context.registerReceiver(mConnectivityIntentReceiver, intentFilter);
@@ -491,10 +524,6 @@
         intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
         context.registerReceiver(mStorageIntentReceiver, intentFilter);
 
-        intentFilter = new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
-        intentFilter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
-        context.registerReceiver(mDeviceIdleReceiver, intentFilter);
-
         intentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
         intentFilter.setPriority(100);
         context.registerReceiver(mShutdownIntentReceiver, intentFilter);
@@ -506,18 +535,9 @@
         mContext.registerReceiverAsUser(
                 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
 
-        try {
-            ActivityManagerNative.getDefault().registerUidObserver(mUidObserver,
-                    ActivityManager.UID_OBSERVER_IDLE);
-        } catch (RemoteException e) {
-            // ignored; both services live in system_server
-        }
-
         if (!factoryTest) {
             mNotificationMgr = (NotificationManager)
-                context.getSystemService(Context.NOTIFICATION_SERVICE);
-            context.registerReceiver(new SyncAlarmIntentReceiver(),
-                    new IntentFilter(ACTION_SYNC_ALARM));
+                    context.getSystemService(Context.NOTIFICATION_SERVICE);
         } else {
             mNotificationMgr = null;
         }
@@ -543,15 +563,6 @@
                 SYNC_LOOP_WAKE_LOCK);
         mSyncManagerWakeLock.setReferenceCounted(false);
 
-        mSyncStorageEngine.addStatusChangeListener(
-                ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, new ISyncStatusObserver.Stub() {
-                    @Override
-                    public void onStatusChanged(int which) {
-                        // force the sync loop to run if the settings change
-                        sendCheckAlarmsMessage();
-                    }
-                });
-
         mProvisioned = isDeviceProvisioned();
         if (!mProvisioned) {
             final ContentResolver resolver = context.getContentResolver();
@@ -589,8 +600,18 @@
                     null, null);
         }
 
-        // Pick a random second in a day to seed all periodic syncs
-        mSyncRandomOffsetMillis = mSyncStorageEngine.getSyncRandomOffset() * 1000;
+        // Set up the communication channel between the scheduled job and the sync manager.
+        // This is posted to the *main* looper intentionally, to defer calling startService()
+        // until after the lengthy primary boot sequence completes on that thread, to avoid
+        // spurious ANR triggering.
+        final Intent startServiceIntent = new Intent(mContext, SyncJobService.class);
+        startServiceIntent.putExtra(SyncJobService.EXTRA_MESSENGER, new Messenger(mSyncHandler));
+        new Handler(mContext.getMainLooper()).post(new Runnable() {
+            @Override
+            public void run() {
+                mContext.startService(startServiceIntent);
+            }
+        });
     }
 
     private boolean isDeviceProvisioned() {
@@ -619,22 +640,22 @@
         int isSyncable = mSyncStorageEngine.getIsSyncable(account, userId, providerName);
         UserInfo userInfo = UserManager.get(mContext).getUserInfo(userId);
 
-        // If it's not a restricted user, return isSyncable
+        // If it's not a restricted user, return isSyncable.
         if (userInfo == null || !userInfo.isRestricted()) return isSyncable;
 
-        // Else check if the sync adapter has opted-in or not
+        // Else check if the sync adapter has opted-in or not.
         RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
                 mSyncAdapters.getServiceInfo(
-                SyncAdapterType.newKey(providerName, account.type), userId);
+                        SyncAdapterType.newKey(providerName, account.type), userId);
         if (syncAdapterInfo == null) return isSyncable;
 
         PackageInfo pInfo = null;
         try {
             pInfo = AppGlobals.getPackageManager().getPackageInfo(
-                syncAdapterInfo.componentName.getPackageName(), 0, userId);
+                    syncAdapterInfo.componentName.getPackageName(), 0, userId);
             if (pInfo == null) return isSyncable;
         } catch (RemoteException re) {
-            // Shouldn't happen
+            // Shouldn't happen.
             return isSyncable;
         }
         if (pInfo.restrictedAccountType != null
@@ -645,97 +666,15 @@
         }
     }
 
-    private void ensureAlarmService() {
-        if (mAlarmService == null) {
-            mAlarmService = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-        }
-    }
-
-    /**
-     * Initiate a sync using the new anonymous service API.
-     * @param cname SyncService component bound to in order to perform the sync. 
-     * @param userId the id of the user whose accounts are to be synced. If userId is USER_ALL,
-     *          then all users' accounts are considered.
-     * @param uid Linux uid of the application that is performing the sync. 
-     * @param extras a Map of SyncAdapter-specific information to control
-     *          syncs of a specific provider. Cannot be null.
-     * @param beforeRunTimeMillis milliseconds before <code>runtimeMillis</code> that this sync may
-     * be run.
-     * @param runtimeMillis milliseconds from now by which this sync must be run.
-     */
-    public void scheduleSync(ComponentName cname, int userId, int uid, Bundle extras,
-            long beforeRunTimeMillis, long runtimeMillis) {
-        boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
-        if (isLoggable) {
-            Log.d(TAG, "one off sync for: " + cname + " " + extras.toString());
-        }
-
-        final android.content.pm.ServiceInfo sinfo;
-        try {
-            sinfo = mContext.getPackageManager().getServiceInfo(cname, userId);
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.w(TAG, "Not scheduling sync " + cname
-                    + " -- can't find service for user " + userId);
-            return;
-        }
-        final int sUid = sinfo.applicationInfo.uid;
-
-        try {
-            if (ActivityManagerNative.getDefault().getAppStartMode(sUid, cname.getPackageName())
-                    == ActivityManager.APP_START_MODE_DISABLED) {
-                Slog.w(TAG, "Not scheduling sync " + sUid + ":" + cname
-                        + " -- package not allowed to start");
+    private void setAuthorityPendingState(EndPoint info) {
+        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        for (SyncOperation op: ops) {
+            if (!op.isPeriodic && op.target.matchesSpec(info)) {
+                getSyncStorageEngine().markPending(info, true);
                 return;
             }
-        } catch (RemoteException e) {
         }
-
-        Boolean expedited = extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
-        if (expedited) {
-            runtimeMillis = -1; // this means schedule at the front of the queue
-        }
-
-        final boolean ignoreSettings =
-                extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
-        int source = SyncStorageEngine.SOURCE_SERVICE;
-        boolean isEnabled = mSyncStorageEngine.getIsTargetServiceActive(cname, userId);
-        // Only schedule this sync if
-        //   - we've explicitly been told to ignore settings.
-        //   - global sync is enabled for this user.
-        boolean syncAllowed =
-                ignoreSettings
-                || mSyncStorageEngine.getMasterSyncAutomatically(userId);
-        if (!syncAllowed) {
-            if (isLoggable) {
-                Log.d(TAG, "scheduleSync: sync of " + cname + " not allowed, dropping request.");
-            }
-            return;
-        }
-        if (!isEnabled) {
-            if (isLoggable) {
-                Log.d(TAG, "scheduleSync: " + cname + " is not enabled, dropping request");
-            }
-            return;
-        }
-        SyncStorageEngine.EndPoint info = new SyncStorageEngine.EndPoint(cname, userId, sUid);
-        Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(info);
-        long delayUntil = mSyncStorageEngine.getDelayUntilTime(info);
-        final long backoffTime = backoff != null ? backoff.first : 0;
-        if (isLoggable) {
-                Log.v(TAG, "schedule Sync:"
-                        + ", delay until " + delayUntil
-                        + ", run by " + runtimeMillis
-                        + ", flex " + beforeRunTimeMillis
-                        + ", source " + source
-                        + ", sync service " + cname
-                        + ", extras " + extras);
-        }
-        scheduleSyncOperation(
-                new SyncOperation(cname, userId, sUid, cname.getPackageName(), uid, source, extras,
-                        runtimeMillis /* runtime */,
-                        beforeRunTimeMillis /* flextime */,
-                        backoffTime,
-                        delayUntil));
+        getSyncStorageEngine().markPending(info, false);
     }
 
     /**
@@ -780,10 +719,10 @@
      * @param onlyThoseWithUnkownSyncableState Only sync authorities that have unknown state.
      */
     public void scheduleSync(Account requestedAccount, int userId, int reason,
-            String requestedAuthority, Bundle extras, long beforeRuntimeMillis,
-            long runtimeMillis, boolean onlyThoseWithUnkownSyncableState) {
-        boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
-
+                             String requestedAuthority, Bundle extras, long beforeRuntimeMillis,
+                             long runtimeMillis, boolean onlyThoseWithUnkownSyncableState) {
+        final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
+        EndPoint ep = new EndPoint(requestedAccount,requestedAuthority, userId);
         if (extras == null) {
             extras = new Bundle();
         }
@@ -791,10 +730,6 @@
             Log.d(TAG, "one-time sync for: " + requestedAccount + " " + extras.toString() + " "
                     + requestedAuthority);
         }
-        Boolean expedited = extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
-        if (expedited) {
-            runtimeMillis = -1; // this means schedule at the front of the queue
-        }
 
         AccountAndUser[] accounts;
         if (requestedAccount != null && userId != UserHandle.USER_ALL) {
@@ -803,7 +738,7 @@
             accounts = mRunningAccounts;
             if (accounts.length == 0) {
                 if (isLoggable) {
-                    Log.v(TAG, "scheduleSync: no accounts configured, dropping");
+                    Slog.v(TAG, "scheduleSync: no accounts configured, dropping");
                 }
                 return;
             }
@@ -826,8 +761,8 @@
         } else if (requestedAuthority == null) {
             source = SyncStorageEngine.SOURCE_POLL;
         } else {
-            // this isn't strictly server, since arbitrary callers can (and do) request
-            // a non-forced two-way sync on a specific url
+            // This isn't strictly server, since arbitrary callers can (and do) request
+            // a non-forced two-way sync on a specific url.
             source = SyncStorageEngine.SOURCE_SERVER;
         }
 
@@ -845,9 +780,9 @@
                 syncableAuthorities.add(syncAdapter.type.authority);
             }
 
-            // if the url was specified then replace the list of authorities
+            // If the url was specified then replace the list of authorities
             // with just this authority or clear it if this authority isn't
-            // syncable
+            // syncable.
             if (requestedAuthority != null) {
                 final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority);
                 syncableAuthorities.clear();
@@ -874,7 +809,7 @@
                         Slog.w(TAG, "Not scheduling job " + syncAdapterInfo.uid + ":"
                                 + syncAdapterInfo.componentName
                                 + " -- package not allowed to start");
-                        return;
+                        continue;
                     }
                 } catch (RemoteException e) {
                 }
@@ -893,11 +828,11 @@
                 }
 
                 boolean syncAllowed =
-                        (isSyncable < 0) // always allow if the isSyncable state is unknown
-                        || ignoreSettings
-                        || (mSyncStorageEngine.getMasterSyncAutomatically(account.userId)
+                        (isSyncable < 0) // Always allow if the isSyncable state is unknown.
+                                || ignoreSettings
+                                || (mSyncStorageEngine.getMasterSyncAutomatically(account.userId)
                                 && mSyncStorageEngine.getSyncAutomatically(account.account,
-                                        account.userId, authority));
+                                account.userId, authority));
                 if (!syncAllowed) {
                     if (isLoggable) {
                         Log.d(TAG, "scheduleSync: sync of " + account + ", " + authority
@@ -908,51 +843,98 @@
                 SyncStorageEngine.EndPoint info =
                         new SyncStorageEngine.EndPoint(
                                 account.account, authority, account.userId);
-                Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(info);
                 long delayUntil =
                         mSyncStorageEngine.getDelayUntilTime(info);
-                final long backoffTime = backoff != null ? backoff.first : 0;
                 if (isSyncable < 0) {
                     // Initialisation sync.
                     Bundle newExtras = new Bundle();
                     newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
                     if (isLoggable) {
-                        Log.v(TAG, "schedule initialisation Sync:"
+                        Slog.v(TAG, "schedule initialisation Sync:"
                                 + ", delay until " + delayUntil
                                 + ", run by " + 0
-                                + ", flex " + 0
+                                + ", flexMillis " + 0
                                 + ", source " + source
                                 + ", account " + account
                                 + ", authority " + authority
                                 + ", extras " + newExtras);
                     }
-                    scheduleSyncOperation(
+                    postScheduleSyncMessage(
                             new SyncOperation(account.account, account.userId,
                                     owningUid, owningPackage, reason, source,
-                                    authority, newExtras, 0 /* immediate */, 0 /* No flex time*/,
-                                    backoffTime, delayUntil, allowParallelSyncs));
+                                    authority, newExtras, allowParallelSyncs)
+                    );
                 }
                 if (!onlyThoseWithUnkownSyncableState) {
                     if (isLoggable) {
-                        Log.v(TAG, "scheduleSync:"
+                        Slog.v(TAG, "scheduleSync:"
                                 + " delay until " + delayUntil
                                 + " run by " + runtimeMillis
-                                + " flex " + beforeRuntimeMillis
+                                + " flexMillis " + beforeRuntimeMillis
                                 + ", source " + source
                                 + ", account " + account
                                 + ", authority " + authority
                                 + ", extras " + extras);
                     }
-                    scheduleSyncOperation(
+                    postScheduleSyncMessage(
                             new SyncOperation(account.account, account.userId,
                                     owningUid, owningPackage, reason, source,
-                                    authority, extras, runtimeMillis, beforeRuntimeMillis,
-                                    backoffTime, delayUntil, allowParallelSyncs));
+                                    authority, extras, allowParallelSyncs)
+                    );
                 }
             }
         }
     }
 
+    private void removeSyncsForAuthority(EndPoint info) {
+        verifyJobScheduler();
+        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        for (SyncOperation op: ops) {
+            if (op.target.matchesSpec(info)) {
+                removeSyncOperationFromCache(op.jobId);
+                getJobScheduler().cancel(op.jobId);
+            }
+        }
+    }
+
+    /**
+     * Remove a specific periodic sync identified by its target and extras.
+     */
+    public void removePeriodicSync(EndPoint target, Bundle extras) {
+        Message m = mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_REMOVE_PERIODIC_SYNC, target);
+        m.setData(extras);
+        m.sendToTarget();
+    }
+
+    /**
+     * Add a periodic sync. If a sync with same target and extras exists, its period and
+     * flexMillis will be updated.
+     */
+    public void updateOrAddPeriodicSync(EndPoint target, long pollFrequency, long flex,
+                                        Bundle extras) {
+        UpdatePeriodicSyncMessagePayload payload = new UpdatePeriodicSyncMessagePayload(target,
+                pollFrequency, flex, extras);
+        mSyncHandler.obtainMessage(SyncHandler.MESSAGE_UPDATE_PERIODIC_SYNC, payload)
+                .sendToTarget();
+    }
+
+    /**
+     * Get a list of periodic syncs corresponding to the given target.
+     */
+    public List<PeriodicSync> getPeriodicSyncs(EndPoint target) {
+        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<PeriodicSync> periodicSyncs = new ArrayList<PeriodicSync>();
+
+        for (SyncOperation op: ops) {
+            if (op.isPeriodic && op.target.matchesSpec(target)) {
+                periodicSyncs.add(new PeriodicSync(op.target.account, op.target.provider,
+                        op.extras, op.periodMillis / 1000, op.flexMillis / 1000));
+            }
+        }
+
+        return periodicSyncs;
+    }
+
     /**
      * Schedule sync based on local changes to a provider. Occurs within interval
      * [LOCAL_SYNC_DELAY, 2*LOCAL_SYNC_DELAY].
@@ -982,28 +964,17 @@
         return mSyncAdapters.getSyncAdapterPackagesForAuthority(authority, userId);
     }
 
-    private void sendSyncAlarmMessage() {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_SYNC_ALARM");
-        mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_SYNC_ALARM);
-    }
-
-    private void sendCheckAlarmsMessage() {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_CHECK_ALARMS");
-        mSyncHandler.removeMessages(SyncHandler.MESSAGE_CHECK_ALARMS);
-        mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_CHECK_ALARMS);
-    }
-
     private void sendSyncFinishedOrCanceledMessage(ActiveSyncContext syncContext,
-            SyncResult syncResult) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_SYNC_FINISHED");
+                                                   SyncResult syncResult) {
+        if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "sending MESSAGE_SYNC_FINISHED");
         Message msg = mSyncHandler.obtainMessage();
         msg.what = SyncHandler.MESSAGE_SYNC_FINISHED;
-        msg.obj = new SyncHandlerMessagePayload(syncContext, syncResult);
+        msg.obj = new SyncFinishedOrCancelledMessagePayload(syncContext, syncResult);
         mSyncHandler.sendMessage(msg);
     }
 
     private void sendCancelSyncsMessage(final SyncStorageEngine.EndPoint info, Bundle extras) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_CANCEL");
+        if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "sending MESSAGE_CANCEL");
         Message msg = mSyncHandler.obtainMessage();
         msg.what = SyncHandler.MESSAGE_CANCEL;
         msg.setData(extras);
@@ -1012,27 +983,12 @@
     }
 
     /**
-     * Post a delayed message to the handler that will result in the cancellation of the provided
-     * running sync's context.
-     */
-    private void postSyncExpiryMessage(ActiveSyncContext activeSyncContext) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "posting MESSAGE_SYNC_EXPIRED in " +
-                    (ACTIVE_SYNC_TIMEOUT_MILLIS/1000) + "s");
-        }
-        Message msg = mSyncHandler.obtainMessage();
-        msg.what = SyncHandler.MESSAGE_SYNC_EXPIRED;
-        msg.obj = activeSyncContext;
-        mSyncHandler.sendMessageDelayed(msg, ACTIVE_SYNC_TIMEOUT_MILLIS);
-    }
-
-    /**
      * Post a delayed message that will monitor the given sync context by periodically checking how
      * much network has been used by the uid.
      */
     private void postMonitorSyncProgressMessage(ActiveSyncContext activeSyncContext) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "posting MESSAGE_SYNC_MONITOR in " +
+            Slog.v(TAG, "posting MESSAGE_SYNC_MONITOR in " +
                     (SYNC_MONITOR_WINDOW_LENGTH_MILLIS/1000) + "s");
         }
 
@@ -1046,6 +1002,11 @@
         mSyncHandler.sendMessageDelayed(monitorMessage, SYNC_MONITOR_WINDOW_LENGTH_MILLIS);
     }
 
+    private void postScheduleSyncMessage(SyncOperation syncOperation) {
+        mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_SCHEDULE_SYNC, syncOperation)
+                .sendToTarget();
+    }
+
     /**
      * Monitor sync progress by calculating how many bytes it is managing to send to and fro.
      */
@@ -1057,62 +1018,74 @@
      * Convenience class for passing parameters for a finished or cancelled sync to the handler
      * to be processed.
      */
-    class SyncHandlerMessagePayload {
+    private class SyncFinishedOrCancelledMessagePayload {
         public final ActiveSyncContext activeSyncContext;
         public final SyncResult syncResult;
 
-        SyncHandlerMessagePayload(ActiveSyncContext syncContext,
-                                  SyncResult syncResult) {
+        SyncFinishedOrCancelledMessagePayload(ActiveSyncContext syncContext,
+                                              SyncResult syncResult) {
             this.activeSyncContext = syncContext;
             this.syncResult = syncResult;
         }
     }
 
-    class SyncAlarmIntentReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            mHandleAlarmWakeLock.acquire();
-            sendSyncAlarmMessage();
+    private class UpdatePeriodicSyncMessagePayload {
+        public final EndPoint target;
+        public final long pollFrequency;
+        public final long flex;
+        public final Bundle extras;
+
+        UpdatePeriodicSyncMessagePayload(EndPoint target, long pollFrequency, long flex,
+                                         Bundle extras) {
+            this.target = target;
+            this.pollFrequency = pollFrequency;
+            this.flex = flex;
+            this.extras = extras;
         }
     }
 
-    private void clearBackoffSetting(SyncOperation op) {
-        mSyncStorageEngine.setBackoff(op.target,
+    private void clearBackoffSetting(EndPoint target) {
+        Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(target);
+        if (backoff != null && backoff.first == SyncStorageEngine.NOT_IN_BACKOFF_MODE &&
+                backoff.second == SyncStorageEngine.NOT_IN_BACKOFF_MODE) {
+            return;
+        }
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Slog.v(TAG, "Clearing backoffs for " + target);
+        }
+        mSyncStorageEngine.setBackoff(target,
                 SyncStorageEngine.NOT_IN_BACKOFF_MODE,
                 SyncStorageEngine.NOT_IN_BACKOFF_MODE);
-        synchronized (mSyncQueue) {
-            mSyncQueue.onBackoffChanged(op.target, 0);
-        }
+
+        rescheduleSyncs(target);
     }
 
-    private void increaseBackoffSetting(SyncOperation op) {
-        // TODO: Use this function to align it to an already scheduled sync
-        //       operation in the specified window
+    private void increaseBackoffSetting(EndPoint target) {
         final long now = SystemClock.elapsedRealtime();
 
         final Pair<Long, Long> previousSettings =
-                mSyncStorageEngine.getBackoff(op.target);
+                mSyncStorageEngine.getBackoff(target);
         long newDelayInMs = -1;
         if (previousSettings != null) {
-            // don't increase backoff before current backoff is expired. This will happen for op's
+            // Don't increase backoff before current backoff is expired. This will happen for op's
             // with ignoreBackoff set.
             if (now < previousSettings.first) {
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "Still in backoff, do not increase it. "
-                        + "Remaining: " + ((previousSettings.first - now) / 1000) + " seconds.");
+                    Slog.v(TAG, "Still in backoff, do not increase it. "
+                            + "Remaining: " + ((previousSettings.first - now) / 1000) + " seconds.");
                 }
                 return;
             }
-            // Subsequent delays are the double of the previous delay
+            // Subsequent delays are the double of the previous delay.
             newDelayInMs = previousSettings.second * 2;
         }
         if (newDelayInMs <= 0) {
-            // The initial delay is the jitterized INITIAL_SYNC_RETRY_TIME_IN_MS
+            // The initial delay is the jitterized INITIAL_SYNC_RETRY_TIME_IN_MS.
             newDelayInMs = jitterize(INITIAL_SYNC_RETRY_TIME_IN_MS,
                     (long)(INITIAL_SYNC_RETRY_TIME_IN_MS * 1.1));
         }
 
-        // Cap the delay
+        // Cap the delay.
         long maxSyncRetryTimeInSeconds = Settings.Global.getLong(mContext.getContentResolver(),
                 Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
                 DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS);
@@ -1121,17 +1094,34 @@
         }
 
         final long backoff = now + newDelayInMs;
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Slog.v(TAG, "Backoff until: " + backoff + ", delayTime: " + newDelayInMs);
+        }
+        mSyncStorageEngine.setBackoff(target, backoff, newDelayInMs);
+        rescheduleSyncs(target);
+    }
 
-        mSyncStorageEngine.setBackoff(op.target, backoff, newDelayInMs);
-        op.backoff = backoff;
-        op.updateEffectiveRunTime();
-
-        synchronized (mSyncQueue) {
-            mSyncQueue.onBackoffChanged(op.target, backoff);
+    /**
+     * Reschedule all scheduled syncs for this EndPoint. The syncs will be scheduled according
+     * to current backoff and delayUntil values of this EndPoint.
+     */
+    private void rescheduleSyncs(EndPoint target) {
+        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        int count = 0;
+        for (SyncOperation op: ops) {
+            if (!op.isPeriodic && op.target.matchesSpec(target)) {
+                count++;
+                removeSyncOperationFromCache(op.jobId);
+                getJobScheduler().cancel(op.jobId);
+                postScheduleSyncMessage(op);
+            }
+        }
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Slog.v(TAG, "Rescheduled " + count + " syncs for " + target);
         }
     }
 
-    private void setDelayUntilTime(SyncOperation op, long delayUntilSeconds) {
+    private void setDelayUntilTime(EndPoint target, long delayUntilSeconds) {
         final long delayUntil = delayUntilSeconds * 1000;
         final long absoluteNow = System.currentTimeMillis();
         long newDelayUntilTime;
@@ -1140,10 +1130,24 @@
         } else {
             newDelayUntilTime = 0;
         }
-        mSyncStorageEngine.setDelayUntilTime(op.target, newDelayUntilTime);
-        synchronized (mSyncQueue) {
-            mSyncQueue.onDelayUntilTimeChanged(op.target, newDelayUntilTime);
+        mSyncStorageEngine.setDelayUntilTime(target, newDelayUntilTime);
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Slog.v(TAG, "Delay Until time set to " + newDelayUntilTime + " for " + target);
         }
+        rescheduleSyncs(target);
+    }
+
+    private boolean isAdapterDelayed(EndPoint target) {
+        long now = SystemClock.elapsedRealtime();
+        Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(target);
+        if (backoff != null && backoff.first != SyncStorageEngine.NOT_IN_BACKOFF_MODE
+                && backoff.first > now) {
+            return true;
+        }
+        if (mSyncStorageEngine.getDelayUntilTime(target) > now) {
+            return true;
+        }
+        return false;
     }
 
     /**
@@ -1157,27 +1161,120 @@
     }
 
     /**
-     * Create and schedule a SyncOperation.
-     *
-     * @param syncOperation the SyncOperation to schedule
+     * Schedule a sync operation with JobScheduler.
      */
-    public void scheduleSyncOperation(SyncOperation syncOperation) {
-        boolean queueChanged;
-        synchronized (mSyncQueue) {
-            queueChanged = mSyncQueue.add(syncOperation);
+    private void scheduleSyncOperationH(SyncOperation syncOperation) {
+        scheduleSyncOperationH(syncOperation, 0L);
+    }
+
+    private void scheduleSyncOperationH(SyncOperation syncOperation, long minDelay) {
+        final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
+        if (syncOperation == null) {
+            Slog.e(TAG, "Can't schedule null sync operation.");
+            return;
+        }
+        if (!syncOperation.ignoreBackoff()) {
+            Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(syncOperation.target);
+            if (backoff == null) {
+                Slog.e(TAG, "Couldn't find backoff values for " + syncOperation.target);
+                backoff = new Pair<Long, Long>(SyncStorageEngine.NOT_IN_BACKOFF_MODE,
+                        SyncStorageEngine.NOT_IN_BACKOFF_MODE);
+            }
+            long now = SystemClock.elapsedRealtime();
+            long backoffDelay = backoff.first == SyncStorageEngine.NOT_IN_BACKOFF_MODE ? 0
+                    : backoff.first - now;
+            long delayUntil = mSyncStorageEngine.getDelayUntilTime(syncOperation.target);
+            long delayUntilDelay = delayUntil > now ? delayUntil - now : 0;
+            if (isLoggable) {
+                Slog.v(TAG, "backoff delay:" + backoffDelay
+                        + " delayUntil delay:" + delayUntilDelay);
+            }
+            minDelay = Math.max(minDelay, Math.max(backoffDelay, delayUntilDelay));
         }
 
-        if (queueChanged) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "scheduleSyncOperation: enqueued " + syncOperation);
+        if (minDelay < 0) {
+            minDelay = 0;
+        }
+
+        // Check if duplicate syncs are pending. If found, keep one with least expected run time.
+        if (!syncOperation.isReasonPeriodic()) {
+            int duplicatesCount = 0;
+            long now = SystemClock.elapsedRealtime();
+            syncOperation.expectedRuntime = now + minDelay;
+            List<SyncOperation> pending = getAllPendingSyncsFromCache();
+            SyncOperation opWithLeastExpectedRuntime = syncOperation;
+            for (SyncOperation op : pending) {
+                if (op.isPeriodic) {
+                    continue;
+                }
+                if (op.key.equals(syncOperation.key)) {
+                    if (opWithLeastExpectedRuntime.expectedRuntime > op.expectedRuntime) {
+                        opWithLeastExpectedRuntime = op;
+                    }
+                    duplicatesCount++;
+                }
             }
-            sendCheckAlarmsMessage();
-        } else {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "scheduleSyncOperation: dropping duplicate sync operation "
-                        + syncOperation);
+            if (duplicatesCount > 1) {
+                Slog.e(TAG, "FATAL ERROR! File a bug if you see this.");
+            }
+            for (SyncOperation op : pending) {
+                if (op.isPeriodic) {
+                    continue;
+                }
+                if (op.key.equals(syncOperation.key)) {
+                    if (op != opWithLeastExpectedRuntime) {
+                        if (isLoggable) {
+                            Slog.v(TAG, "Cancelling duplicate sync " + op);
+                        }
+                        removeSyncOperationFromCache(op.jobId);
+                        getJobScheduler().cancel(op.jobId);
+                    }
+                }
+            }
+            if (opWithLeastExpectedRuntime != syncOperation) {
+                // Don't schedule because a duplicate sync with earlier expected runtime exists.
+                if (isLoggable) {
+                    Slog.v(TAG, "Not scheduling because a duplicate exists.");
+                }
+                return;
             }
         }
+
+        syncOperation.jobId = getUnusedJobId();
+        addSyncOperationToCache(syncOperation);
+
+        if (isLoggable) {
+            Slog.v(TAG, "scheduling sync operation " + syncOperation.target.toString());
+        }
+
+        // This is done to give preference to syncs that are not pushed back.
+        int priority = syncOperation.findPriority();
+
+        final int networkType = syncOperation.isNotAllowedOnMetered() ?
+                JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY;
+
+        JobInfo.Builder b = new JobInfo.Builder(syncOperation.jobId,
+                    new ComponentName(mContext, SyncJobService.class))
+                .setExtras(syncOperation.toJobInfoExtras())
+                .setRequiredNetworkType(networkType)
+                .setPersisted(true)
+                .setPriority(priority);
+
+        if (syncOperation.isPeriodic) {
+            b.setPeriodic(syncOperation.periodMillis, syncOperation.flexMillis);
+        } else {
+            if (minDelay > 0) {
+                b.setMinimumLatency(minDelay);
+            }
+            getSyncStorageEngine().markPending(syncOperation.target, true);
+        }
+
+        if (syncOperation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING)) {
+            b.setRequiresCharging(true);
+        }
+
+        getJobScheduler().scheduleAsPackage(b.build(), syncOperation.owningPackage,
+                syncOperation.target.userId);
     }
 
     /**
@@ -1186,8 +1283,13 @@
      * have null account/provider info to specify all accounts/providers.
      */
     public void clearScheduledSyncOperations(SyncStorageEngine.EndPoint info) {
-        synchronized (mSyncQueue) {
-            mSyncQueue.remove(info, null /* all operations */);
+        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        for (SyncOperation op: ops) {
+            if (!op.isPeriodic && op.target.matchesSpec(info)) {
+                removeSyncOperationFromCache(op.jobId);
+                getJobScheduler().cancel(op.jobId);
+                getSyncStorageEngine().markPending(op.target, false);
+            }
         }
         mSyncStorageEngine.setBackoff(info,
                 SyncStorageEngine.NOT_IN_BACKOFF_MODE, SyncStorageEngine.NOT_IN_BACKOFF_MODE);
@@ -1199,9 +1301,15 @@
      * @param extras extras bundle to uniquely identify sync.
      */
     public void cancelScheduledSyncOperation(SyncStorageEngine.EndPoint info, Bundle extras) {
-        synchronized (mSyncQueue) {
-            mSyncQueue.remove(info, extras);
+        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        for (SyncOperation op: ops) {
+            if (!op.isPeriodic && op.target.matchesSpec(info)
+                    && syncExtrasEquals(extras, op.extras, false)) {
+                removeSyncOperationFromCache(op.jobId);
+                getJobScheduler().cancel(op.jobId);
+            }
         }
+        setAuthorityPendingState(info);
         // Reset the back-off if there are no more syncs pending.
         if (!mSyncStorageEngine.isSyncPending(info)) {
             mSyncStorageEngine.setBackoff(info,
@@ -1209,14 +1317,12 @@
         }
     }
 
-    void maybeRescheduleSync(SyncResult syncResult, SyncOperation operation) {
-        boolean isLoggable = Log.isLoggable(TAG, Log.DEBUG);
+    private void maybeRescheduleSync(SyncResult syncResult, SyncOperation operation) {
+        final boolean isLoggable = Log.isLoggable(TAG, Log.DEBUG);
         if (isLoggable) {
             Log.d(TAG, "encountered error(s) during the sync: " + syncResult + ", " + operation);
         }
 
-        operation = new SyncOperation(operation, 0L /* newRunTimeFromNow */);
-
         // The SYNC_EXTRAS_IGNORE_BACKOFF only applies to the first attempt to sync a given
         // request. Retries of the request will always honor the backoff, so clear the
         // flag in case we retry this request.
@@ -1237,7 +1343,7 @@
                 Log.d(TAG, "retrying sync operation as a two-way sync because an upload-only sync "
                         + "encountered an error: " + operation);
             }
-            scheduleSyncOperation(operation);
+            scheduleSyncOperationH(operation, 0 /* immediately */);
         } else if (syncResult.tooManyRetries) {
             // If this sync aborted because the internal sync loop retried too many times then
             //   don't reschedule. Otherwise we risk getting into a retry loop.
@@ -1251,24 +1357,20 @@
                 Log.d(TAG, "retrying sync operation because even though it had an error "
                         + "it achieved some success");
             }
-            scheduleSyncOperation(operation);
+            scheduleSyncOperationH(operation, 0 /* immediately */);
         } else if (syncResult.syncAlreadyInProgress) {
             if (isLoggable) {
                 Log.d(TAG, "retrying sync operation that failed because there was already a "
                         + "sync in progress: " + operation);
             }
-            scheduleSyncOperation(
-                new SyncOperation(
-                        operation,
-                        DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS * 1000 /* newRunTimeFromNow */)
-                );
+            scheduleSyncOperationH(operation, DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS * 1000);
         } else if (syncResult.hasSoftError()) {
             // If this was a two-way sync then retry soft errors with an exponential backoff.
             if (isLoggable) {
                 Log.d(TAG, "retrying sync operation because it encountered a soft error: "
                         + operation);
             }
-            scheduleSyncOperation(operation);
+            scheduleSyncOperationH(operation);
         } else {
             // Otherwise do not reschedule.
             Log.d(TAG, "not retrying sync operation because the error is a hard error: "
@@ -1277,85 +1379,46 @@
     }
 
     private void onUserUnlocked(int userId) {
-        // Make sure that accounts we're about to use are valid
+        // Make sure that accounts we're about to use are valid.
         AccountManagerService.getSingleton().validateAccounts(userId);
 
         mSyncAdapters.invalidateCache(userId);
 
-        updateRunningAccounts();
+        EndPoint target = new EndPoint(null, null, userId);
+        updateRunningAccounts(target);
 
-        synchronized (mSyncQueue) {
-            mSyncQueue.addPendingOperations(userId);
-        }
-
-        // Schedule sync for any accounts under started user
+        // Schedule sync for any accounts under started user.
         final Account[] accounts = AccountManagerService.getSingleton().getAccounts(userId,
                 mContext.getOpPackageName());
         for (Account account : accounts) {
             scheduleSync(account, userId, SyncOperation.REASON_USER_START, null, null,
-                    0 /* no delay */, 0 /* No flex */,
+                    0 /* no delay */, 0 /* No flexMillis */,
                     true /* onlyThoseWithUnknownSyncableState */);
         }
-
-        sendCheckAlarmsMessage();
     }
 
     private void onUserStopping(int userId) {
-        updateRunningAccounts();
+        updateRunningAccounts(null /* Don't sync any target */);
 
         cancelActiveSync(
                 new SyncStorageEngine.EndPoint(
                         null /* any account */,
                         null /* any authority */,
                         userId),
-                        null /* any sync. */
-                );
+                null /* any sync. */
+        );
     }
 
     private void onUserRemoved(int userId) {
-        updateRunningAccounts();
+        updateRunningAccounts(null /* Don't sync any target */);
 
         // Clean up the storage engine database
         mSyncStorageEngine.doDatabaseCleanup(new Account[0], userId);
-        synchronized (mSyncQueue) {
-            mSyncQueue.removeUserLocked(userId);
-        }
-    }
-
-    /**
-     * Clear backoff on operations in the sync queue that match the packageName and userId.
-     * @param packageName The package that just became active. Can be null to indicate that all
-     * packages are now considered active due to being plugged in.
-     * @param userId The user for which the package has become active. Can be USER_ALL if
-     * the device just plugged in.
-     */
-    void onAppNotIdle(@Nullable String packageName, int userId) {
-        synchronized (mSyncQueue) {
-            // For all sync operations in sync queue, if marked as idle, compare with package name
-            // and unmark. And clear backoff for the operation.
-            final Iterator<SyncOperation> operationIterator =
-                    mSyncQueue.getOperations().iterator();
-            boolean changed = false;
-            while (operationIterator.hasNext()) {
-                final SyncOperation op = operationIterator.next();
-                if (op.appIdle
-                        && (packageName == null || getPackageName(op.target).equals(packageName))
-                        && (userId == UserHandle.USER_ALL || op.target.userId == userId)) {
-                    op.appIdle = false;
-                    clearBackoffSetting(op);
-                    changed = true;
-                }
-            }
-            if (changed) {
-                sendCheckAlarmsMessage();
-            }
-        }
-    }
-
-    void cancelSyncsForUid(int uid) {
-        synchronized (mSyncQueue) {
-            if (mSyncQueue.removeUidIfNeededLocked(uid)) {
-                sendCheckAlarmsMessage();
+        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        for (SyncOperation op: ops) {
+            if (op.target.userId == userId) {
+                removeSyncOperationFromCache(op.jobId);
+                getJobScheduler().cancel(op.jobId);
             }
         }
     }
@@ -1368,7 +1431,6 @@
         final SyncOperation mSyncOperation;
         final long mHistoryRowId;
         ISyncAdapter mSyncAdapter;
-        ISyncServiceAdapter mSyncServiceAdapter;
         final long mStartTime;
         long mTimeoutStartTime;
         boolean mBound;
@@ -1397,13 +1459,12 @@
          * for this sync. This is used to attribute the wakelock hold to that application.
          */
         public ActiveSyncContext(SyncOperation syncOperation, long historyRowId,
-                int syncAdapterUid) {
+                                 int syncAdapterUid) {
             super();
             mSyncAdapterUid = syncAdapterUid;
             mSyncOperation = syncOperation;
             mHistoryRowId = historyRowId;
             mSyncAdapter = null;
-            mSyncServiceAdapter = null;
             mStartTime = SystemClock.elapsedRealtime();
             mTimeoutStartTime = mStartTime;
             mSyncWakeLock = mSyncHandler.getSyncWakeLock(mSyncOperation);
@@ -1412,14 +1473,14 @@
         }
 
         public void sendHeartbeat() {
-            // heartbeats are no longer used
+            // Heartbeats are no longer used.
         }
 
         public void onFinished(SyncResult result) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "onFinished: " + this);
-            // include "this" in the message so that the handler can ignore it if this
+            if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "onFinished: " + this);
+            // Include "this" in the message so that the handler can ignore it if this
             // ActiveSyncContext is no longer the mActiveSyncContext at message handling
-            // time
+            // time.
             sendSyncFinishedOrCanceledMessage(this, result);
         }
 
@@ -1459,7 +1520,7 @@
             mBound = true;
             final boolean bindResult = mContext.bindServiceAsUser(intent, this,
                     Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
-                    | Context.BIND_ALLOW_OOM_MANAGEMENT,
+                            | Context.BIND_ALLOW_OOM_MANAGEMENT,
                     new UserHandle(mSyncOperation.target.userId));
             if (!bindResult) {
                 mBound = false;
@@ -1507,6 +1568,8 @@
 
     protected void dump(FileDescriptor fd, PrintWriter pw) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+        dumpPendingSyncs(pw);
+        dumpPeriodicSyncs(pw);
         dumpSyncState(ipw);
         dumpSyncHistory(ipw);
         dumpSyncAdapters(ipw);
@@ -1518,6 +1581,34 @@
         return tobj.format("%Y-%m-%d %H:%M:%S");
     }
 
+    protected void dumpPendingSyncs(PrintWriter pw) {
+        pw.println("Pending Syncs:");
+        List<SyncOperation> pendingSyncs = getAllPendingSyncsFromCache();
+        int count = 0;
+        for (SyncOperation op: pendingSyncs) {
+            if (!op.isPeriodic) {
+                pw.println(op.dump(null, false));
+                count++;
+            }
+        }
+        pw.println("Total: " + count);
+        pw.println();
+    }
+
+    protected void dumpPeriodicSyncs(PrintWriter pw) {
+        pw.println("Periodic Syncs:");
+        List<SyncOperation> pendingSyncs = getAllPendingSyncsFromCache();
+        int count = 0;
+        for (SyncOperation op: pendingSyncs) {
+            if (op.isPeriodic) {
+                pw.println(op.dump(null, false));
+                count++;
+            }
+        }
+        pw.println("Total: " + count);
+        pw.println();
+    }
+
     protected void dumpSyncState(PrintWriter pw) {
         pw.print("data connected: "); pw.println(mDataConnectionIsConnected);
         pw.print("auto sync: ");
@@ -1544,24 +1635,15 @@
         final long now = SystemClock.elapsedRealtime();
         pw.print("now: "); pw.print(now);
         pw.println(" (" + formatTime(System.currentTimeMillis()) + ")");
-        pw.print("offset: "); pw.print(DateUtils.formatElapsedTime(mSyncRandomOffsetMillis / 1000));
         pw.println(" (HH:MM:SS)");
         pw.print("uptime: "); pw.print(DateUtils.formatElapsedTime(now / 1000));
-                pw.println(" (HH:MM:SS)");
+        pw.println(" (HH:MM:SS)");
         pw.print("time spent syncing: ");
-                pw.print(DateUtils.formatElapsedTime(
-                        mSyncHandler.mSyncTimeTracker.timeSpentSyncing() / 1000));
-                pw.print(" (HH:MM:SS), sync ");
-                pw.print(mSyncHandler.mSyncTimeTracker.mLastWasSyncing ? "" : "not ");
-                pw.println("in progress");
-        if (mSyncHandler.mAlarmScheduleTime != null) {
-            pw.print("next alarm time: "); pw.print(mSyncHandler.mAlarmScheduleTime);
-                    pw.print(" (");
-                    pw.print(DateUtils.formatElapsedTime((mSyncHandler.mAlarmScheduleTime-now)/1000));
-                    pw.println(" (HH:MM:SS) from now)");
-        } else {
-            pw.println("no alarm is scheduled (there had better not be any pending syncs)");
-        }
+        pw.print(DateUtils.formatElapsedTime(
+                mSyncHandler.mSyncTimeTracker.timeSpentSyncing() / 1000));
+        pw.print(" (HH:MM:SS), sync ");
+        pw.print(mSyncHandler.mSyncTimeTracker.mLastWasSyncing ? "" : "not ");
+        pw.println("in progress");
 
         pw.println();
         pw.println("Active Syncs: " + mActiveSyncContexts.size());
@@ -1575,17 +1657,7 @@
             pw.println();
         }
 
-        final StringBuilder sb = new StringBuilder();
-        synchronized (mSyncQueue) {
-            mSyncQueue.dump(sb);
-            // Dump Pending Operations.
-            getSyncStorageEngine().dumpPendingOperations(sb);
-        }
-
-        pw.println();
-        pw.print(sb.toString());
-
-        // join the installed sync adapter with the accounts list and emit for everything
+        // Join the installed sync adapter with the accounts list and emit for everything.
         pw.println();
         pw.println("Sync Status");
         for (AccountAndUser account : accounts) {
@@ -1593,7 +1665,7 @@
                     account.account.name, account.userId, account.account.type);
 
             pw.println("=======================================================================");
-            final PrintTable table = new PrintTable(13);
+            final PrintTable table = new PrintTable(12);
             table.set(0, 0,
                     "Authority", // 0
                     "Syncable",  // 1
@@ -1606,8 +1678,7 @@
                     "User",      // 8
                     "Tot",       // 9
                     "Time",      // 10
-                    "Last Sync", // 11
-                    "Periodic"   // 12
+                    "Last Sync" // 11
             );
 
             final List<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> sorted =
@@ -1615,18 +1686,18 @@
             sorted.addAll(mSyncAdapters.getAllServices(account.userId));
             Collections.sort(sorted,
                     new Comparator<RegisteredServicesCache.ServiceInfo<SyncAdapterType>>() {
-                @Override
-                public int compare(RegisteredServicesCache.ServiceInfo<SyncAdapterType> lhs,
-                        RegisteredServicesCache.ServiceInfo<SyncAdapterType> rhs) {
-                    return lhs.type.authority.compareTo(rhs.type.authority);
-                }
-            });
+                        @Override
+                        public int compare(RegisteredServicesCache.ServiceInfo<SyncAdapterType> lhs,
+                                           RegisteredServicesCache.ServiceInfo<SyncAdapterType> rhs) {
+                            return lhs.type.authority.compareTo(rhs.type.authority);
+                        }
+                    });
             for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterType : sorted) {
                 if (!syncAdapterType.type.accountType.equals(account.account.type)) {
                     continue;
                 }
                 int row = table.getNumRows();
-                Pair<AuthorityInfo, SyncStatusInfo> syncAuthoritySyncStatus = 
+                Pair<AuthorityInfo, SyncStatusInfo> syncAuthoritySyncStatus =
                         mSyncStorageEngine.getCopyOfAuthorityWithSyncStatus(
                                 new SyncStorageEngine.EndPoint(
                                         account.account,
@@ -1648,20 +1719,6 @@
                         status.numSyncs,
                         DateUtils.formatElapsedTime(status.totalElapsedTime / 1000));
 
-
-                for (int i = 0; i < settings.periodicSyncs.size(); i++) {
-                    final PeriodicSync sync = settings.periodicSyncs.get(i);
-                    final String period =
-                            String.format("[p:%d s, f: %d s]", sync.period, sync.flexTime);
-                    final String extras =
-                            sync.extras.size() > 0 ?
-                                    sync.extras.toString() : "Bundle[]";
-                    final String next = "Next sync: " + formatTime(status.getPeriodicSyncTime(i)
-                            + sync.period * 1000);
-                    table.set(row + i * 2, 12, period + " " + extras);
-                    table.set(row + i * 2 + 1, 12, next);
-                }
-
                 int row1 = row;
                 if (settings.delayUntil > now) {
                     table.set(row1++, 12, "D: " + (settings.delayUntil - now) / 1000);
@@ -1688,37 +1745,6 @@
         }
     }
 
-    private String getLastFailureMessage(int code) {
-        switch (code) {
-            case ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS:
-                return "sync already in progress";
-
-            case ContentResolver.SYNC_ERROR_AUTHENTICATION:
-                return "authentication error";
-
-            case ContentResolver.SYNC_ERROR_IO:
-                return "I/O error";
-
-            case ContentResolver.SYNC_ERROR_PARSE:
-                return "parse error";
-
-            case ContentResolver.SYNC_ERROR_CONFLICT:
-                return "conflict error";
-
-            case ContentResolver.SYNC_ERROR_TOO_MANY_DELETIONS:
-                return "too many deletions error";
-
-            case ContentResolver.SYNC_ERROR_TOO_MANY_RETRIES:
-                return "too many retries error";
-
-            case ContentResolver.SYNC_ERROR_INTERNAL:
-                return "internal error";
-
-            default:
-                return "unknown";
-        }
-    }
-
     private void dumpTimeSec(PrintWriter pw, long time) {
         pw.print(time/1000); pw.print('.'); pw.print((time/100)%10);
         pw.print('s');
@@ -1760,20 +1786,10 @@
                 final String authorityName;
                 final String accountKey;
                 if (authorityInfo != null) {
-                    if (authorityInfo.target.target_provider) {
-                        authorityName = authorityInfo.target.provider;
-                        accountKey = authorityInfo.target.account.name + "/"
-                                + authorityInfo.target.account.type
-                                + " u" + authorityInfo.target.userId;
-                    } else if (authorityInfo.target.target_service) {
-                        authorityName = authorityInfo.target.service.getPackageName() + "/"
-                                + authorityInfo.target.service.getClassName()
-                                + " u" + authorityInfo.target.userId;
-                        accountKey = "no account";
-                    } else {
-                        authorityName = "Unknown";
-                        accountKey = "Unknown";
-                    }
+                    authorityName = authorityInfo.target.provider;
+                    accountKey = authorityInfo.target.account.name + "/"
+                            + authorityInfo.target.account.type
+                            + " u" + authorityInfo.target.userId;
                 } else {
                     authorityName = "Unknown";
                     accountKey = "Unknown";
@@ -1812,7 +1828,7 @@
             if (totalElapsedTime > 0) {
                 pw.println();
                 pw.printf("Detailed Statistics (Recent history):  "
-                        + "%d (# of times) %ds (sync time)\n",
+                                + "%d (# of times) %ds (sync time)\n",
                         totalTimes, totalElapsedTime / 1000);
 
                 final List<AuthoritySyncStats> sortedAuthorities =
@@ -1899,20 +1915,10 @@
                 final String authorityName;
                 final String accountKey;
                 if (authorityInfo != null) {
-                    if (authorityInfo.target.target_provider) {
-                        authorityName = authorityInfo.target.provider;
-                        accountKey = authorityInfo.target.account.name + "/"
-                                + authorityInfo.target.account.type
-                                + " u" + authorityInfo.target.userId;
-                    } else if (authorityInfo.target.target_service) {
-                        authorityName = authorityInfo.target.service.getPackageName() + "/"
-                                + authorityInfo.target.service.getClassName()
-                                + " u" + authorityInfo.target.userId;
-                        accountKey = "none";
-                    } else {
-                        authorityName = "Unknown";
-                        accountKey = "Unknown";
-                    }
+                    authorityName = authorityInfo.target.provider;
+                    accountKey = authorityInfo.target.account.name + "/"
+                            + authorityInfo.target.account.type
+                            + " u" + authorityInfo.target.userId;
                 } else {
                     authorityName = "Unknown";
                     accountKey = "Unknown";
@@ -1976,20 +1982,10 @@
                 final String authorityName;
                 final String accountKey;
                 if (authorityInfo != null) {
-                    if (authorityInfo.target.target_provider) {
-                        authorityName = authorityInfo.target.provider;
-                        accountKey = authorityInfo.target.account.name + "/"
-                                + authorityInfo.target.account.type
-                                + " u" + authorityInfo.target.userId;
-                    } else if (authorityInfo.target.target_service) {
-                        authorityName = authorityInfo.target.service.getPackageName() + "/"
-                                + authorityInfo.target.service.getClassName()
-                                + " u" + authorityInfo.target.userId;
-                        accountKey = "none";
-                    } else {
-                        authorityName = "Unknown";
-                        accountKey = "Unknown";
-                    }
+                    authorityName = authorityInfo.target.provider;
+                    accountKey = authorityInfo.target.account.name + "/"
+                            + authorityInfo.target.account.type
+                            + " u" + authorityInfo.target.userId;
                 } else {
                     authorityName = "Unknown";
                     accountKey = "Unknown";
@@ -2146,13 +2142,18 @@
      * HandlerThread.
      */
     class SyncHandler extends Handler {
-        // Messages that can be sent on mHandler
+        // Messages that can be sent on mHandler.
         private static final int MESSAGE_SYNC_FINISHED = 1;
-        private static final int MESSAGE_SYNC_ALARM = 2;
-        private static final int MESSAGE_CHECK_ALARMS = 3;
+        private static final int MESSAGE_RELEASE_MESSAGES_FROM_QUEUE = 2;
         private static final int MESSAGE_SERVICE_CONNECTED = 4;
         private static final int MESSAGE_SERVICE_DISCONNECTED = 5;
         private static final int MESSAGE_CANCEL = 6;
+        static final int MESSAGE_JOBSERVICE_OBJECT = 7;
+        static final int MESSAGE_START_SYNC = 10;
+        static final int MESSAGE_STOP_SYNC = 11;
+        static final int MESSAGE_SCHEDULE_SYNC = 12;
+        static final int MESSAGE_UPDATE_PERIODIC_SYNC = 13;
+        static final int MESSAGE_REMOVE_PERIODIC_SYNC = 14;
         /**
          * Posted delayed in order to expire syncs that are long-running.
          * obj: {@link com.android.server.content.SyncManager.ActiveSyncContext}
@@ -2165,8 +2166,6 @@
         private static final int MESSAGE_MONITOR_SYNC = 8;
         private static final int MESSAGE_ACCOUNTS_UPDATED = 9;
 
-        public final SyncNotificationInfo mSyncNotificationInfo = new SyncNotificationInfo();
-        private Long mAlarmScheduleTime = null;
         public final SyncTimeTracker mSyncTimeTracker = new SyncTimeTracker();
         private final HashMap<String, PowerManager.WakeLock> mWakeLocks = Maps.newHashMap();
 
@@ -2174,32 +2173,230 @@
 
         void onBootCompleted() {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "Boot completed, clearing boot queue.");
+                Slog.v(TAG, "Boot completed.");
             }
-            doDatabaseCleanup();
-            synchronized(this) {
-                // Dispatch any stashed messages.
-                maybeEmptyUnreadyQueueLocked();
-            }
+            checkIfDeviceReady();
         }
 
         void onDeviceProvisioned() {
             if (Log.isLoggable(TAG, Log.DEBUG)) {
                 Log.d(TAG, "mProvisioned=" + mProvisioned);
             }
-            synchronized (this) {
-                maybeEmptyUnreadyQueueLocked();
+            checkIfDeviceReady();
+        }
+
+        void checkIfDeviceReady() {
+            if (mProvisioned && mBootCompleted) {
+                synchronized(this) {
+                    // Dispatch any stashed messages.
+                    obtainMessage(MESSAGE_RELEASE_MESSAGES_FROM_QUEUE).sendToTarget();
+                }
             }
         }
 
-        private void maybeEmptyUnreadyQueueLocked() {
-            if (mProvisioned && mBootCompleted) {
-                // Dispatch any stashed messages.
-                for (int i=0; i<mUnreadyQueue.size(); i++) {
-                    sendMessageDelayed(mUnreadyQueue.get(i),
-                            Math.max(PER_SYNC_BOOT_DELAY_MILLIS * i, MAX_SYNC_BOOT_DELAY_MILLIS));
+        /**
+         * Stash any messages that come to the handler before boot is complete or before the device
+         * is properly provisioned (i.e. out of set-up wizard).
+         * {@link #onBootCompleted()} and {@link SyncHandler#onDeviceProvisioned} both
+         * need to come in before we start syncing.
+         * @param msg Message to dispatch at a later point.
+         * @return true if a message was enqueued, false otherwise. This is to avoid losing the
+         * message if we manage to acquire the lock but by the time we do boot has completed.
+         */
+        private boolean tryEnqueueMessageUntilReadyToRun(Message msg) {
+            synchronized (this) {
+                if (!mBootCompleted || !mProvisioned) {
+                    if (msg.what == MESSAGE_START_SYNC) {
+                        deferSyncH((SyncOperation) msg.obj, 60*1000 /* 1 minute */);
+                    }
+                    // Need to copy the message bc looper will recycle it.
+                    Message m = Message.obtain(msg);
+                    mUnreadyQueue.add(m);
+                    return true;
+                } else {
+                    return false;
                 }
-                mUnreadyQueue = null;
+            }
+        }
+
+        public SyncHandler(Looper looper) {
+            super(looper);
+        }
+
+        public void handleMessage(Message msg) {
+            try {
+                mSyncManagerWakeLock.acquire();
+                // We only want to enqueue sync related messages until device is ready.
+                // Other messages are handled without enqueuing.
+                if (msg.what == MESSAGE_JOBSERVICE_OBJECT) {
+                    Slog.i(TAG, "Got SyncJobService instance.");
+                    mSyncJobService = (SyncJobService) msg.obj;
+                } else if (msg.what == SyncHandler.MESSAGE_ACCOUNTS_UPDATED) {
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Slog.v(TAG, "handleSyncHandlerMessage: MESSAGE_ACCOUNTS_UPDATED");
+                    }
+                    EndPoint targets = (EndPoint) msg.obj;
+                    updateRunningAccountsH(targets);
+                } else if (msg.what == MESSAGE_RELEASE_MESSAGES_FROM_QUEUE) {
+                    if (mUnreadyQueue != null) {
+                        for (Message m : mUnreadyQueue) {
+                            handleSyncMessage(m);
+                        }
+                        mUnreadyQueue = null;
+                    }
+                } else if (tryEnqueueMessageUntilReadyToRun(msg)) {
+                    // No work to be done.
+                } else {
+                    handleSyncMessage(msg);
+                }
+            } finally {
+                mSyncManagerWakeLock.release();
+            }
+        }
+
+        private void handleSyncMessage(Message msg) {
+            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
+
+            try {
+                mDataConnectionIsConnected = readDataConnectionState();
+                switch (msg.what) {
+                    case MESSAGE_SCHEDULE_SYNC:
+                        SyncOperation op = (SyncOperation) msg.obj;
+                        scheduleSyncOperationH(op);
+                        break;
+
+                    case MESSAGE_START_SYNC:
+                        op = (SyncOperation) msg.obj;
+                        startSyncH(op);
+                        break;
+
+                    case MESSAGE_STOP_SYNC:
+                        op = (SyncOperation) msg.obj;
+                        boolean reschedule = msg.arg1 != 0;
+                        boolean applyBackoff = msg.arg2 != 0;
+                        if (isLoggable) {
+                            Slog.v(TAG, "Stop sync received. Reschedule: " + reschedule
+                                    + "Backoff: " + applyBackoff);
+                        }
+                        if (applyBackoff) {
+                            increaseBackoffSetting(op.target);
+                        }
+                        if (reschedule) {
+                            scheduleSyncOperationH(op);
+                        }
+                        ActiveSyncContext asc = findActiveSyncContextH(op.jobId);
+                        if (asc != null) {
+                            runSyncFinishedOrCanceledH(null /* no result */, asc);
+                        }
+                        break;
+
+                    case MESSAGE_UPDATE_PERIODIC_SYNC:
+                        UpdatePeriodicSyncMessagePayload data =
+                                (UpdatePeriodicSyncMessagePayload) msg.obj;
+                        updateOrAddPeriodicSyncH(data.target, data.pollFrequency,
+                                data.flex, data.extras);
+                        break;
+                    case MESSAGE_REMOVE_PERIODIC_SYNC:
+                        removePeriodicSyncH((EndPoint)msg.obj, msg.getData());
+                        break;
+
+                    case SyncHandler.MESSAGE_CANCEL:
+                        SyncStorageEngine.EndPoint endpoint = (SyncStorageEngine.EndPoint) msg.obj;
+                        Bundle extras = msg.peekData();
+                        if (Log.isLoggable(TAG, Log.DEBUG)) {
+                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_CANCEL: "
+                                    + endpoint + " bundle: " + extras);
+                        }
+                        cancelActiveSyncH(endpoint, extras);
+                        break;
+
+                    case SyncHandler.MESSAGE_SYNC_FINISHED:
+                        SyncFinishedOrCancelledMessagePayload payload =
+                                (SyncFinishedOrCancelledMessagePayload) msg.obj;
+                        if (!isSyncStillActiveH(payload.activeSyncContext)) {
+                            Log.d(TAG, "handleSyncHandlerMessage: dropping since the "
+                                    + "sync is no longer active: "
+                                    + payload.activeSyncContext);
+                            break;
+                        }
+                        if (isLoggable) {
+                            Slog.v(TAG, "syncFinished" + payload.activeSyncContext.mSyncOperation);
+                        }
+                        mSyncJobService.callJobFinished(
+                                payload.activeSyncContext.mSyncOperation.jobId, false);
+                        runSyncFinishedOrCanceledH(payload.syncResult,
+                                payload.activeSyncContext);
+                        break;
+
+                    case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
+                        ServiceConnectionData msgData = (ServiceConnectionData) msg.obj;
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CONNECTED: "
+                                    + msgData.activeSyncContext);
+                        }
+                        // Check that this isn't an old message.
+                        if (isSyncStillActiveH(msgData.activeSyncContext)) {
+                            runBoundToAdapterH(
+                                    msgData.activeSyncContext,
+                                    msgData.adapter);
+                        }
+                        break;
+                    }
+
+                    case SyncHandler.MESSAGE_SERVICE_DISCONNECTED: {
+                        final ActiveSyncContext currentSyncContext =
+                                ((ServiceConnectionData) msg.obj).activeSyncContext;
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_DISCONNECTED: "
+                                    + currentSyncContext);
+                        }
+                        // Check that this isn't an old message.
+                        if (isSyncStillActiveH(currentSyncContext)) {
+                            // cancel the sync if we have a syncadapter, which means one is
+                            // outstanding
+                            try {
+                                if (currentSyncContext.mSyncAdapter != null) {
+                                    currentSyncContext.mSyncAdapter.cancelSync(currentSyncContext);
+                                }
+                            } catch (RemoteException e) {
+                                // We don't need to retry this in this case.
+                            }
+
+                            // Pretend that the sync failed with an IOException,
+                            // which is a soft error.
+                            SyncResult syncResult = new SyncResult();
+                            syncResult.stats.numIoExceptions++;
+                            mSyncJobService.callJobFinished(
+                                    currentSyncContext.mSyncOperation.jobId, false);
+                            runSyncFinishedOrCanceledH(syncResult, currentSyncContext);
+                        }
+                        break;
+                    }
+
+                    case SyncHandler.MESSAGE_MONITOR_SYNC:
+                        ActiveSyncContext monitoredSyncContext = (ActiveSyncContext) msg.obj;
+                        if (Log.isLoggable(TAG, Log.DEBUG)) {
+                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_MONITOR_SYNC: " +
+                                    monitoredSyncContext.mSyncOperation.target);
+                        }
+
+                        if (isSyncNotUsingNetworkH(monitoredSyncContext)) {
+                            Log.w(TAG, String.format(
+                                    "Detected sync making no progress for %s. cancelling.",
+                                    monitoredSyncContext));
+                            mSyncJobService.callJobFinished(
+                                    monitoredSyncContext.mSyncOperation.jobId, false);
+                            runSyncFinishedOrCanceledH(
+                                    null /* cancel => no result */, monitoredSyncContext);
+                        } else {
+                            // Repost message to check again.
+                            postMonitorSyncProgressMessage(monitoredSyncContext);
+                        }
+                        break;
+
+                }
+            } finally {
+                mSyncTimeTracker.update();
             }
         }
 
@@ -2216,664 +2413,117 @@
         }
 
         /**
-         * Stash any messages that come to the handler before boot is complete or before the device
-         * is properly provisioned (i.e. out of set-up wizard).
-         * {@link #onBootCompleted()} and {@link SyncHandler#onDeviceProvisioned} both
-         * need to come in before we start syncing.
-         * @param msg Message to dispatch at a later point.
-         * @return true if a message was enqueued, false otherwise. This is to avoid losing the
-         * message if we manage to acquire the lock but by the time we do boot has completed.
+         * Defer the specified SyncOperation by rescheduling it on the JobScheduler with some
+         * delay.
          */
-        private boolean tryEnqueueMessageUntilReadyToRun(Message msg) {
-            synchronized (this) {
-                if (!mBootCompleted || !mProvisioned) {
-                    // Need to copy the message bc looper will recycle it.
-                    mUnreadyQueue.add(Message.obtain(msg));
-                    return true;
-                } else {
-                    return false;
-                }
+        private void deferSyncH(SyncOperation op, long delay) {
+            mSyncJobService.callJobFinished(op.jobId, false);
+            if (op.isPeriodic) {
+                scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
+            } else {
+                removeSyncOperationFromCache(op.jobId);
+                scheduleSyncOperationH(op, delay);
             }
         }
 
         /**
-         * Used to keep track of whether a sync notification is active and who it is for.
+         * Cancel an active sync and reschedule it on the JobScheduler with some delay.
          */
-        class SyncNotificationInfo {
-            // true iff the notification manager has been asked to send the notification
-            public boolean isActive = false;
+        private void deferActiveSyncH(ActiveSyncContext asc) {
+            SyncOperation op = asc.mSyncOperation;
 
-            // Set when we transition from not running a sync to running a sync, and cleared on
-            // the opposite transition.
-            public Long startTime = null;
-
-            public void toString(StringBuilder sb) {
-                sb.append("isActive ").append(isActive).append(", startTime ").append(startTime);
-            }
-
-            @Override
-            public String toString() {
-                StringBuilder sb = new StringBuilder();
-                toString(sb);
-                return sb.toString();
-            }
+            mSyncHandler.obtainMessage(MESSAGE_STOP_SYNC, 0 /* no reschedule */,
+                    0 /* no backoff */, op).sendToTarget();
+            deferSyncH(op, SYNC_DELAY_ON_CONFLICT);
         }
 
-        public SyncHandler(Looper looper) {
-            super(looper);
-        }
+        private void startSyncH(SyncOperation op) {
+            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
+            if (isLoggable) Slog.v(TAG, op.toString());
 
-        public void handleMessage(Message msg) {
-            if (tryEnqueueMessageUntilReadyToRun(msg)) {
+            if (mStorageIsLow) {
+                deferSyncH(op, SYNC_DELAY_ON_LOW_STORAGE);
                 return;
             }
 
-            long earliestFuturePollTime = Long.MAX_VALUE;
-            long nextPendingSyncTime = Long.MAX_VALUE;
-            // Setting the value here instead of a method because we want the dumpsys logs
-            // to have the most recent value used.
-            try {
-                mDataConnectionIsConnected = readDataConnectionState();
-                mSyncManagerWakeLock.acquire();
-                // Always do this first so that we be sure that any periodic syncs that
-                // are ready to run have been converted into pending syncs. This allows the
-                // logic that considers the next steps to take based on the set of pending syncs
-                // to also take into account the periodic syncs.
-                earliestFuturePollTime = scheduleReadyPeriodicSyncs();
-                switch (msg.what) {
-                    case SyncHandler.MESSAGE_ACCOUNTS_UPDATED:
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_ACCOUNTS_UPDATED");
-                        }
-                        updateRunningAccountsH();
-                        break;
-
-                    case SyncHandler.MESSAGE_CANCEL:
-                        SyncStorageEngine.EndPoint endpoint = (SyncStorageEngine.EndPoint) msg.obj;
-                        Bundle extras = msg.peekData();
-                        if (Log.isLoggable(TAG, Log.DEBUG)) {
-                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_CANCEL: "
-                                    + endpoint + " bundle: " + extras);
-                        }
-                        cancelActiveSyncH(endpoint, extras);
-                        nextPendingSyncTime = maybeStartNextSyncH();
-                        break;
-
-                    case SyncHandler.MESSAGE_SYNC_FINISHED:
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_FINISHED");
-                        }
-                        SyncHandlerMessagePayload payload = (SyncHandlerMessagePayload) msg.obj;
-                        if (!isSyncStillActiveH(payload.activeSyncContext)) {
-                            Log.d(TAG, "handleSyncHandlerMessage: dropping since the "
-                                    + "sync is no longer active: "
-                                    + payload.activeSyncContext);
-                            break;
-                        }
-                        runSyncFinishedOrCanceledH(payload.syncResult,
-                                payload.activeSyncContext);
-
-                        // since a sync just finished check if it is time to start a new sync
-                        nextPendingSyncTime = maybeStartNextSyncH();
-                        break;
-
-                    case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
-                        ServiceConnectionData msgData = (ServiceConnectionData) msg.obj;
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CONNECTED: "
-                                    + msgData.activeSyncContext);
-                        }
-                        // check that this isn't an old message
-                        if (isSyncStillActiveH(msgData.activeSyncContext)) {
-                            runBoundToAdapter(
-                                    msgData.activeSyncContext,
-                                    msgData.adapter);
-                        }
-                        break;
+            if (op.isPeriodic) {
+                // Don't allow this periodic to run if a previous instance failed and is currently
+                // scheduled according to some backoff criteria.
+                List<SyncOperation> ops = getAllPendingSyncsFromCache();
+                for (SyncOperation syncOperation: ops) {
+                    if (syncOperation.sourcePeriodicId == op.jobId) {
+                        mSyncJobService.callJobFinished(op.jobId, false);
+                        return;
                     }
-
-                    case SyncHandler.MESSAGE_SERVICE_DISCONNECTED: {
-                        final ActiveSyncContext currentSyncContext =
-                                ((ServiceConnectionData) msg.obj).activeSyncContext;
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_DISCONNECTED: "
-                                    + currentSyncContext);
-                        }
-                        // check that this isn't an old message
-                        if (isSyncStillActiveH(currentSyncContext)) {
-                            // cancel the sync if we have a syncadapter, which means one is
-                            // outstanding
-                            try {
-                                if (currentSyncContext.mSyncAdapter != null) {
-                                    currentSyncContext.mSyncAdapter.cancelSync(currentSyncContext);
-                                } else if (currentSyncContext.mSyncServiceAdapter != null) {
-                                    currentSyncContext.mSyncServiceAdapter
-                                        .cancelSync(currentSyncContext);
-                                }
-                            } catch (RemoteException e) {
-                                // We don't need to retry this in this case.
-                            }
-
-                            // pretend that the sync failed with an IOException,
-                            // which is a soft error
-                            SyncResult syncResult = new SyncResult();
-                            syncResult.stats.numIoExceptions++;
-                            runSyncFinishedOrCanceledH(syncResult, currentSyncContext);
-
-                            // since a sync just finished check if it is time to start a new sync
-                            nextPendingSyncTime = maybeStartNextSyncH();
-                        }
-                        break;
+                }
+                // Don't allow this periodic to run if a previous instance failed and is currently
+                // executing according to some backoff criteria.
+                for (ActiveSyncContext asc: mActiveSyncContexts) {
+                    if (asc.mSyncOperation.sourcePeriodicId == op.jobId) {
+                        mSyncJobService.callJobFinished(op.jobId, false);
+                        return;
                     }
+                }
+                // Check for adapter delays.
+                if (isAdapterDelayed(op.target)) {
+                    deferSyncH(op, 0 /* No minimum delay */);
+                }
+            } else {
+                // Remove SyncOperation entry from mScheduledSyncs cache for non periodic jobs.
+                removeSyncOperationFromCache(op.jobId);
+            }
 
-                    case SyncHandler.MESSAGE_SYNC_ALARM: {
-                        boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
+            // Check for conflicting syncs.
+            for (ActiveSyncContext asc: mActiveSyncContexts) {
+                if (asc.mSyncOperation.isConflict(op)) {
+                    // If the provided SyncOperation conflicts with a running one, the lower
+                    // priority sync is pre-empted.
+                    if (asc.mSyncOperation.findPriority() >= op.findPriority()) {
                         if (isLoggable) {
-                            Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_ALARM");
+                            Slog.v(TAG, "Rescheduling sync due to conflict " + op.toString());
                         }
-                        mAlarmScheduleTime = null;
-                        try {
-                            nextPendingSyncTime = maybeStartNextSyncH();
-                        } finally {
-                            mHandleAlarmWakeLock.release();
-                        }
-                        break;
-                    }
-
-                    case SyncHandler.MESSAGE_CHECK_ALARMS:
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_CHECK_ALARMS");
-                        }
-                        nextPendingSyncTime = maybeStartNextSyncH();
-                        break;
-                    case SyncHandler.MESSAGE_SYNC_EXPIRED:
-                        ActiveSyncContext expiredContext = (ActiveSyncContext) msg.obj;
-                        if (Log.isLoggable(TAG, Log.DEBUG)) {
-                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_EXPIRED:" +
-                                    " cancelling " + expiredContext);
-                        }
-                        runSyncFinishedOrCanceledH(
-                                null /* cancel => no result */,
-                                expiredContext);
-                        nextPendingSyncTime = maybeStartNextSyncH();
-                        break;
-                    case SyncHandler.MESSAGE_MONITOR_SYNC:
-                        ActiveSyncContext monitoredSyncContext = (ActiveSyncContext) msg.obj;
-                        if (Log.isLoggable(TAG, Log.DEBUG)) {
-                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_MONITOR_SYNC: " +
-                                    monitoredSyncContext.mSyncOperation.target);
-                        }
-
-                        if (isSyncNotUsingNetworkH(monitoredSyncContext)) {
-                            Log.w(TAG, String.format(
-                                    "Detected sync making no progress for %s. cancelling.",
-                                    monitoredSyncContext));
-                            runSyncFinishedOrCanceledH(
-                                    null /* cancel => no result */, monitoredSyncContext);
-                        } else {
-                            // Repost message to check again.
-                            postMonitorSyncProgressMessage(monitoredSyncContext);
-                        }
-                    break;
-
-                }
-            } finally {
-                manageSyncAlarmLocked(earliestFuturePollTime, nextPendingSyncTime);
-                mSyncTimeTracker.update();
-                mSyncManagerWakeLock.release();
-            }
-        }
-
-        private boolean isDispatchable(SyncStorageEngine.EndPoint target) {
-            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
-            if (target.target_provider) {
-                // skip the sync if the account of this operation no longer exists
-                AccountAndUser[] accounts = mRunningAccounts;
-                if (!containsAccountAndUser(
-                        accounts, target.account, target.userId)) {
-                    return false;
-                }
-                if (!mSyncStorageEngine.getMasterSyncAutomatically(target.userId)
-                        || !mSyncStorageEngine.getSyncAutomatically(
-                                target.account,
-                                target.userId,
-                                target.provider)) {
-                    if (isLoggable) {
-                        Log.v(TAG, "    Not scheduling periodic operation: sync turned off.");
-                    }
-                    return false;
-                }
-                if (getIsSyncable(target.account, target.userId, target.provider)
-                        == 0) {
-                    if (isLoggable) {
-                        Log.v(TAG, "    Not scheduling periodic operation: isSyncable == 0.");
-                    }
-                    return false;
-                }
-            } else if (target.target_service) {
-                if (mSyncStorageEngine.getIsTargetServiceActive(target.service, target.userId)) {
-                    if (isLoggable) {
-                        Log.v(TAG, "   Not scheduling periodic operation: isEnabled == 0.");
-                    }
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        /**
-         * Turn any periodic sync operations that are ready to run into pending sync operations.
-         * @return the desired start time of the earliest future periodic sync operation,
-         * in milliseconds since boot
-         */
-        private long scheduleReadyPeriodicSyncs() {
-            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
-            if (isLoggable) {
-                Log.v(TAG, "scheduleReadyPeriodicSyncs");
-            }
-            long earliestFuturePollTime = Long.MAX_VALUE;
-
-            final long nowAbsolute = System.currentTimeMillis();
-            final long shiftedNowAbsolute = (0 < nowAbsolute - mSyncRandomOffsetMillis)
-                    ? (nowAbsolute - mSyncRandomOffsetMillis) : 0;
-
-            ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> infos = mSyncStorageEngine
-                    .getCopyOfAllAuthoritiesWithSyncStatus();
-            for (Pair<AuthorityInfo, SyncStatusInfo> info : infos) {
-                final AuthorityInfo authorityInfo = info.first;
-                final SyncStatusInfo status = info.second;
-
-                if (TextUtils.isEmpty(authorityInfo.target.provider)) {
-                    Log.e(TAG, "Got an empty provider string. Skipping: "
-                        + authorityInfo.target.provider);
-                    continue;
-                }
-
-                if (!isDispatchable(authorityInfo.target)) {
-                    continue;
-                }
-
-                for (int i = 0, N = authorityInfo.periodicSyncs.size(); i < N; i++) {
-                    final PeriodicSync sync = authorityInfo.periodicSyncs.get(i);
-                    final Bundle extras = sync.extras;
-                    final Long periodInMillis = sync.period * 1000;
-                    final Long flexInMillis = sync.flexTime * 1000;
-                    // Skip if the period is invalid.
-                    if (periodInMillis <= 0) {
-                        continue;
-                    }
-                    // Find when this periodic sync was last scheduled to run.
-                    final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i);
-                    final long shiftedLastPollTimeAbsolute =
-                            (0 < lastPollTimeAbsolute - mSyncRandomOffsetMillis) ?
-                                    (lastPollTimeAbsolute - mSyncRandomOffsetMillis) : 0;
-                    long remainingMillis
-                        = periodInMillis - (shiftedNowAbsolute % periodInMillis);
-                    long timeSinceLastRunMillis
-                        = (nowAbsolute - lastPollTimeAbsolute);
-                    // Schedule this periodic sync to run early if it's close enough to its next
-                    // runtime, and far enough from its last run time.
-                    // If we are early, there will still be time remaining in this period.
-                    boolean runEarly = remainingMillis <= flexInMillis
-                            && timeSinceLastRunMillis > periodInMillis - flexInMillis;
-                    if (isLoggable) {
-                        Log.v(TAG, "sync: " + i + " for " + authorityInfo.target + "."
-                        + " period: " + (periodInMillis)
-                        + " flex: " + (flexInMillis)
-                        + " remaining: " + (remainingMillis)
-                        + " time_since_last: " + timeSinceLastRunMillis
-                        + " last poll absol: " + lastPollTimeAbsolute
-                        + " last poll shifed: " + shiftedLastPollTimeAbsolute
-                        + " shifted now: " + shiftedNowAbsolute
-                        + " run_early: " + runEarly);
-                    }
-                    /*
-                     * Sync scheduling strategy: Set the next periodic sync
-                     * based on a random offset (in seconds). Also sync right
-                     * now if any of the following cases hold and mark it as
-                     * having been scheduled
-                     * Case 1: This sync is ready to run now.
-                     * Case 2: If the lastPollTimeAbsolute is in the
-                     * future, sync now and reinitialize. This can happen for
-                     * example if the user changed the time, synced and changed
-                     * back.
-                     * Case 3: If we failed to sync at the last scheduled time.
-                     * Case 4: This sync is close enough to the time that we can schedule it.
-                     */
-                    if (remainingMillis == periodInMillis // Case 1
-                            || lastPollTimeAbsolute > nowAbsolute // Case 2
-                            || timeSinceLastRunMillis >= periodInMillis // Case 3
-                            || runEarly) { // Case 4
-                        // Sync now
-                        SyncStorageEngine.EndPoint target = authorityInfo.target;
-                        final Pair<Long, Long> backoff =
-                                mSyncStorageEngine.getBackoff(target);
-                        mSyncStorageEngine.setPeriodicSyncTime(authorityInfo.ident,
-                                authorityInfo.periodicSyncs.get(i), nowAbsolute);
-
-                        if (target.target_provider) {
-                            final RegisteredServicesCache.ServiceInfo<SyncAdapterType>
-                                syncAdapterInfo = mSyncAdapters.getServiceInfo(
-                                    SyncAdapterType.newKey(
-                                            target.provider, target.account.type),
-                                    target.userId);
-                            if (syncAdapterInfo == null) {
-                                continue;
-                            }
-                            scheduleSyncOperation(
-                                    new SyncOperation(target.account, target.userId,
-                                            syncAdapterInfo.uid,
-                                            syncAdapterInfo.componentName.getPackageName(),
-                                            SyncOperation.REASON_PERIODIC,
-                                            SyncStorageEngine.SOURCE_PERIODIC,
-                                            target.provider, extras,
-                                            0 /* runtime */, 0 /* flex */,
-                                            backoff != null ? backoff.first : 0,
-                                            mSyncStorageEngine.getDelayUntilTime(target),
-                                            syncAdapterInfo.type.allowParallelSyncs()));
-                        } else if (target.target_service) {
-                            scheduleSyncOperation(
-                                    new SyncOperation(target.service, target.userId,
-                                            target.serviceUid, target.service.getPackageName(),
-                                            SyncOperation.REASON_PERIODIC,
-                                            SyncStorageEngine.SOURCE_PERIODIC,
-                                            extras,
-                                            0 /* runtime */,
-                                            0 /* flex */,
-                                            backoff != null ? backoff.first : 0,
-                                            mSyncStorageEngine.getDelayUntilTime(target)));
-                        }
-                    }
-                    // Compute when this periodic sync should next run.
-                    long nextPollTimeAbsolute;
-                    if (runEarly) {
-                        // Add the time remaining so we don't get out of phase.
-                        nextPollTimeAbsolute = nowAbsolute + periodInMillis + remainingMillis;
+                        deferSyncH(op, SYNC_DELAY_ON_CONFLICT);
+                        return;
                     } else {
-                        nextPollTimeAbsolute = nowAbsolute + remainingMillis;
-                    }
-                    if (nextPollTimeAbsolute < earliestFuturePollTime) {
-                        earliestFuturePollTime = nextPollTimeAbsolute;
-                    }
-                }
-            }
-
-            if (earliestFuturePollTime == Long.MAX_VALUE) {
-                return Long.MAX_VALUE;
-            }
-
-            // convert absolute time to elapsed time
-            return SystemClock.elapsedRealtime() +
-                ((earliestFuturePollTime < nowAbsolute) ?
-                    0 : (earliestFuturePollTime - nowAbsolute));
-        }
-
-        private long maybeStartNextSyncH() {
-            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
-            if (isLoggable) Log.v(TAG, "maybeStartNextSync");
-
-            // If we aren't ready to run (e.g. the data connection is down), get out.
-            if (!mDataConnectionIsConnected) {
-                if (isLoggable) {
-                    Log.v(TAG, "maybeStartNextSync: no data connection, skipping");
-                }
-                setSyncActive(false);
-                return Long.MAX_VALUE;
-            }
-
-            if (mStorageIsLow) {
-                if (isLoggable) {
-                    Log.v(TAG, "maybeStartNextSync: memory low, skipping");
-                }
-                setSyncActive(false);
-                return Long.MAX_VALUE;
-            }
-
-            if (mDeviceIsIdle) {
-                if (isLoggable) {
-                    Log.v(TAG, "maybeStartNextSync: device idle, skipping");
-                }
-                setSyncActive(false);
-                return Long.MAX_VALUE;
-            }
-
-            // If the accounts aren't known yet then we aren't ready to run. We will be kicked
-            // when the account lookup request does complete.
-            if (mRunningAccounts == INITIAL_ACCOUNTS_ARRAY) {
-                if (isLoggable) {
-                    Log.v(TAG, "maybeStartNextSync: accounts not known, skipping");
-                }
-                setSyncActive(false);
-                return Long.MAX_VALUE;
-            }
-
-            // Otherwise consume SyncOperations from the head of the SyncQueue until one is
-            // found that is runnable (not disabled, etc). If that one is ready to run then
-            // start it, otherwise just get out.
-            final long now = SystemClock.elapsedRealtime();
-
-            // will be set to the next time that a sync should be considered for running
-            long nextReadyToRunTime = Long.MAX_VALUE;
-
-            // order the sync queue, dropping syncs that are not allowed
-            ArrayList<SyncOperation> operations = new ArrayList<SyncOperation>();
-            synchronized (mSyncQueue) {
-                if (isLoggable) {
-                    Log.v(TAG, "build the operation array, syncQueue size is "
-                        + mSyncQueue.getOperations().size());
-                }
-                final Iterator<SyncOperation> operationIterator =
-                        mSyncQueue.getOperations().iterator();
-
-                final ActivityManager am = mContext.getSystemService(ActivityManager.class);
-                final Set<Integer> removedUsers = Sets.newHashSet();
-                while (operationIterator.hasNext()) {
-                    final SyncOperation op = operationIterator.next();
-
-                    // If the user is not running unlocked, skip the request.
-                    if (!am.isUserRunningAndUnlocked(op.target.userId)) {
-                        final UserInfo userInfo = mUserManager.getUserInfo(op.target.userId);
-                        if (userInfo == null) {
-                            removedUsers.add(op.target.userId);
-                        }
                         if (isLoggable) {
-                            Log.v(TAG, "    Dropping all sync operations for + "
-                                    + op.target.userId + ": user not running unlocked.");
+                            Slog.v(TAG, "Pushing back running sync due to a higher priority sync");
                         }
-                        continue;
-                    }
-                    String packageName = getPackageName(op.target);
-                    ApplicationInfo ai = null;
-                    if (packageName != null) {
-                        try {
-                            ai = mContext.getPackageManager().getApplicationInfo(packageName,
-                                    PackageManager.GET_UNINSTALLED_PACKAGES
-                                            | PackageManager.GET_DISABLED_COMPONENTS);
-                        } catch (NameNotFoundException e) {
-                            operationIterator.remove();
-                            mSyncStorageEngine.deleteFromPending(op.pendingOperation);
-                            continue;
-                        }
-                    }
-                    // If app is considered idle, then skip for now and backoff
-                    if (ai != null
-                            && mAppIdleMonitor.isAppIdle(packageName, ai.uid, op.target.userId)) {
-                        increaseBackoffSetting(op);
-                        op.appIdle = true;
-                        if (isLoggable) {
-                            Log.v(TAG, "Sync backing off idle app " + packageName);
-                        }
-                        continue;
-                    } else {
-                        op.appIdle = false;
-                    }
-                    if (!isOperationValidLocked(op)) {
-                        operationIterator.remove();
-                        mSyncStorageEngine.deleteFromPending(op.pendingOperation);
-                        continue;
-                    }
-                    // If the next run time is in the future, even given the flexible scheduling,
-                    // return the time.
-                    if (op.effectiveRunTime - op.flexTime > now) {
-                        if (nextReadyToRunTime > op.effectiveRunTime) {
-                            nextReadyToRunTime = op.effectiveRunTime;
-                        }
-                        if (isLoggable) {
-                            Log.v(TAG, "    Not running sync operation: Sync too far in future."
-                                    + "effective: " + op.effectiveRunTime + " flex: " + op.flexTime
-                                    + " now: " + now);
-                        }
-                        continue;
-                    }
-                    // Add this sync to be run.
-                    operations.add(op);
-                }
-
-                for (Integer user : removedUsers) {
-                    // if it's still removed
-                    if (mUserManager.getUserInfo(user) == null) {
-                        onUserRemoved(user);
+                        deferActiveSyncH(asc);
                     }
                 }
             }
 
-            // find the next operation to dispatch, if one is ready
-            // iterate from the top, keep issuing (while potentially canceling existing syncs)
-            // until the quotas are filled.
-            // once the quotas are filled iterate once more to find when the next one would be
-            // (also considering pre-emption reasons).
-            if (isLoggable) Log.v(TAG, "sort the candidate operations, size " + operations.size());
-            Collections.sort(operations);
-            if (isLoggable) Log.v(TAG, "dispatch all ready sync operations");
-            for (int i = 0, N = operations.size(); i < N; i++) {
-                final SyncOperation candidate = operations.get(i);
-                final boolean candidateIsInitialization = candidate.isInitialization();
-
-                int numInit = 0;
-                int numRegular = 0;
-                ActiveSyncContext conflict = null;
-                ActiveSyncContext longRunning = null;
-                ActiveSyncContext toReschedule = null;
-                ActiveSyncContext oldestNonExpeditedRegular = null;
-
-                for (ActiveSyncContext activeSyncContext : mActiveSyncContexts) {
-                    final SyncOperation activeOp = activeSyncContext.mSyncOperation;
-                    if (activeOp.isInitialization()) {
-                        numInit++;
-                    } else {
-                        numRegular++;
-                        if (!activeOp.isExpedited()) {
-                            if (oldestNonExpeditedRegular == null
-                                || (oldestNonExpeditedRegular.mStartTime
-                                    > activeSyncContext.mStartTime)) {
-                                oldestNonExpeditedRegular = activeSyncContext;
-                            }
-                        }
-                    }
-                    if (activeOp.isConflict(candidate)) {
-                        conflict = activeSyncContext;
-                        // don't break out since we want to do a full count of the varieties.
-                    } else {
-                        if (candidateIsInitialization == activeOp.isInitialization()
-                                && activeSyncContext.mStartTime + MAX_TIME_PER_SYNC < now) {
-                            longRunning = activeSyncContext;
-                            // don't break out since we want to do a full count of the varieties
-                        }
-                    }
+            if (isOperationValid(op)) {
+                if (!dispatchSyncOperation(op)) {
+                    mSyncJobService.callJobFinished(op.jobId, false);
                 }
-
-                if (isLoggable) {
-                    Log.v(TAG, "candidate " + (i + 1) + " of " + N + ": " + candidate);
-                    Log.v(TAG, "  numActiveInit=" + numInit + ", numActiveRegular=" + numRegular);
-                    Log.v(TAG, "  longRunning: " + longRunning);
-                    Log.v(TAG, "  conflict: " + conflict);
-                    Log.v(TAG, "  oldestNonExpeditedRegular: " + oldestNonExpeditedRegular);
-                }
-
-                final boolean roomAvailable = candidateIsInitialization
-                        ? numInit < MAX_SIMULTANEOUS_INITIALIZATION_SYNCS
-                        : numRegular < MAX_SIMULTANEOUS_REGULAR_SYNCS;
-
-                if (conflict != null) {
-                    if (candidateIsInitialization && !conflict.mSyncOperation.isInitialization()
-                            && numInit < MAX_SIMULTANEOUS_INITIALIZATION_SYNCS) {
-                        toReschedule = conflict;
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "canceling and rescheduling sync since an initialization "
-                                    + "takes higher priority, " + conflict);
-                        }
-                    } else if (candidate.isExpedited() && !conflict.mSyncOperation.isExpedited()
-                            && (candidateIsInitialization
-                                == conflict.mSyncOperation.isInitialization())) {
-                        toReschedule = conflict;
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                            Log.v(TAG, "canceling and rescheduling sync since an expedited "
-                                    + "takes higher priority, " + conflict);
-                        }
-                    } else {
-                        continue;
-                    }
-                } else if (roomAvailable) {
-                    // dispatch candidate
-                } else if (candidate.isExpedited() && oldestNonExpeditedRegular != null
-                           && !candidateIsInitialization) {
-                    // We found an active, non-expedited regular sync. We also know that the
-                    // candidate doesn't conflict with this active sync since conflict
-                    // is null. Reschedule the active sync and start the candidate.
-                    toReschedule = oldestNonExpeditedRegular;
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "canceling and rescheduling sync since an expedited is ready to"
-                                + " run, " + oldestNonExpeditedRegular);
-                    }
-                } else if (longRunning != null
-                        && (candidateIsInitialization
-                            == longRunning.mSyncOperation.isInitialization())) {
-                    // We found an active, long-running sync. Reschedule the active
-                    // sync and start the candidate.
-                    toReschedule = longRunning;
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "canceling and rescheduling sync since it ran roo long, "
-                              + longRunning);
-                    }
-                } else {
-                    // we were unable to find or make space to run this candidate, go on to
-                    // the next one
-                    continue;
-                }
-
-                if (toReschedule != null) {
-                    runSyncFinishedOrCanceledH(null, toReschedule);
-                    scheduleSyncOperation(toReschedule.mSyncOperation);
-                }
-                synchronized (mSyncQueue) {
-                    mSyncQueue.remove(candidate);
-                }
-                dispatchSyncOperation(candidate);
+            } else {
+                mSyncJobService.callJobFinished(op.jobId, false);
             }
-
-            setSyncActive(mActiveSyncContexts.size() > 0);
-
-            return nextReadyToRunTime;
+            setAuthorityPendingState(op.target);
         }
 
-        void setSyncActive(boolean active) {
-            if (mLocalDeviceIdleController == null) {
-                mLocalDeviceIdleController
-                        = LocalServices.getService(DeviceIdleController.LocalService.class);
-            }
-            if (mLocalDeviceIdleController != null) {
-                if (mReportedSyncActive != active) {
-                    mReportedSyncActive = active;
-                    mLocalDeviceIdleController.setSyncActive(active);
+        private ActiveSyncContext findActiveSyncContextH(int jobId) {
+            for (ActiveSyncContext asc: mActiveSyncContexts) {
+                SyncOperation op = asc.mSyncOperation;
+                if (op != null && op.jobId == jobId) {
+                    return asc;
                 }
             }
+            return null;
         }
 
-        private void updateRunningAccountsH() {
+        private void updateRunningAccountsH(EndPoint syncTargets) {
             mRunningAccounts = AccountManagerService.getSingleton().getRunningAccounts();
-
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Slog.v(TAG, "Accounts list: ");
+                for (AccountAndUser acc : mRunningAccounts) {
+                    Slog.v(TAG, acc.toString());
+                }
+            }
             if (mBootCompleted) {
                 doDatabaseCleanup();
+                mSyncStorageEngine.restoreAllPeriodicSyncs();
             }
 
             AccountAndUser[] accounts = mRunningAccounts;
@@ -2886,9 +2536,119 @@
                             null /* no result since this is a cancel */);
                 }
             }
-            // we must do this since we don't bother scheduling alarms when
-            // the accounts are not set yet
-            sendCheckAlarmsMessage();
+
+            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            for (SyncOperation op: ops) {
+                if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) {
+                    removeSyncOperationFromCache(op.jobId);
+                    getJobScheduler().cancel(op.jobId);
+                }
+            }
+
+            if (syncTargets != null) {
+                scheduleSync(syncTargets.account, syncTargets.userId,
+                        SyncOperation.REASON_ACCOUNTS_UPDATED, syncTargets.provider, null, 0, 0,
+                        true);
+            }
+        }
+
+        /**
+         * The given SyncOperation will be removed and a new one scheduled in its place if
+         * an updated period or flex is specified.
+         * @param syncOperation SyncOperation whose period and flex is to be updated.
+         * @param pollFrequencyMillis new period in milliseconds.
+         * @param flexMillis new flex time in milliseconds.
+         */
+        private void maybeUpdateSyncPeriodH(SyncOperation syncOperation, long pollFrequencyMillis,
+                                            long flexMillis) {
+            if (!(pollFrequencyMillis == syncOperation.periodMillis
+                    && flexMillis == syncOperation.flexMillis)) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Slog.v(TAG, "updating period " + syncOperation + " to " + pollFrequencyMillis
+                            + " and flex to " + flexMillis);
+                }
+                removePeriodicSyncInternalH(syncOperation);
+                syncOperation.periodMillis = pollFrequencyMillis;
+                syncOperation.flexMillis = flexMillis;
+                scheduleSyncOperationH(syncOperation);
+            }
+        }
+
+        private void updateOrAddPeriodicSyncH(EndPoint target, long pollFrequency, long flex,
+                                              Bundle extras) {
+            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
+            verifyJobScheduler();  // Will fill in mScheduledSyncs cache if it is not already filled.
+            final long pollFrequencyMillis = pollFrequency * 1000L;
+            final long flexMillis = flex * 1000L;
+            if (isLoggable) {
+                Slog.v(TAG, "Addition to periodic syncs requested: " + target
+                        + " period: " + pollFrequency
+                        + " flexMillis: " + flex
+                        + " extras: " + extras.toString());
+            }
+            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            for (SyncOperation op: ops) {
+                if (op.isPeriodic && op.target.matchesSpec(target)
+                        && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
+                    maybeUpdateSyncPeriodH(op, pollFrequencyMillis, flexMillis);
+                    return;
+                }
+            }
+
+            if (isLoggable) {
+                Slog.v(TAG, "Adding new periodic sync: " + target
+                        + " period: " + pollFrequency
+                        + " flexMillis: " + flex
+                        + " extras: " + extras.toString());
+            }
+
+            final RegisteredServicesCache.ServiceInfo<SyncAdapterType>
+                    syncAdapterInfo = mSyncAdapters.getServiceInfo(
+                    SyncAdapterType.newKey(
+                            target.provider, target.account.type),
+                    target.userId);
+            if (syncAdapterInfo == null) {
+                return;
+            }
+
+            SyncOperation op = new SyncOperation(target, syncAdapterInfo.uid,
+                    syncAdapterInfo.componentName.getPackageName(), SyncOperation.REASON_PERIODIC,
+                    SyncStorageEngine.SOURCE_PERIODIC, extras,
+                    syncAdapterInfo.type.allowParallelSyncs(), true, SyncOperation.NO_JOB_ID);
+            op.periodMillis = pollFrequencyMillis;
+            op.flexMillis = flexMillis;
+            scheduleSyncOperationH(op);
+            mSyncStorageEngine.reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+        }
+
+        /**
+         * Remove this periodic sync operation and all one-off operations initiated by it.
+         */
+        private void removePeriodicSyncInternalH(SyncOperation syncOperation) {
+            // Remove this periodic sync and all one-off syncs initiated by it.
+            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            for (SyncOperation op: ops) {
+                if (op.sourcePeriodicId == syncOperation.jobId || op.jobId == syncOperation.jobId) {
+                    ActiveSyncContext asc = findActiveSyncContextH(syncOperation.jobId);
+                    if (asc != null) {
+                        mSyncJobService.callJobFinished(syncOperation.jobId, false);
+                        runSyncFinishedOrCanceledH(null, asc);
+                    }
+                    removeSyncOperationFromCache(op.jobId);
+                    getJobScheduler().cancel(op.jobId);
+                }
+            }
+        }
+
+        private void removePeriodicSyncH(EndPoint target, Bundle extras) {
+            verifyJobScheduler();
+            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            for (SyncOperation op: ops) {
+                if (op.isPeriodic && op.target.matchesSpec(target)
+                        && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
+                    removePeriodicSyncInternalH(op);
+                }
+            }
         }
 
         private boolean isSyncNotUsingNetworkH(ActiveSyncContext activeSyncContext) {
@@ -2906,116 +2666,52 @@
                 remainder %= 1024;
                 long b = remainder;
                 Log.d(TAG, String.format(
-                                "Time since last update: %ds. Delta transferred: %dMBs,%dKBs,%dBs",
-                                (SystemClock.elapsedRealtime()
-                                        - activeSyncContext.mLastPolledTimeElapsed)/1000,
-                                mb, kb, b)
+                        "Time since last update: %ds. Delta transferred: %dMBs,%dKBs,%dBs",
+                        (SystemClock.elapsedRealtime()
+                                - activeSyncContext.mLastPolledTimeElapsed)/1000,
+                        mb, kb, b)
                 );
             }
             return (deltaBytesTransferred <= SYNC_MONITOR_PROGRESS_THRESHOLD_BYTES);
         }
 
         /**
-         * Determine if a sync is no longer valid and should be dropped from the sync queue and its
-         * pending op deleted.
-         * @param op operation for which the sync is to be scheduled.
+         * Determine if a sync is no longer valid and should be dropped.
          */
-        private boolean isOperationValidLocked(SyncOperation op) {
+        private boolean isOperationValid(SyncOperation op) {
             final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
-            int targetUid;
             int state;
-            final SyncStorageEngine.EndPoint target = op.target;
+            final EndPoint target = op.target;
             boolean syncEnabled = mSyncStorageEngine.getMasterSyncAutomatically(target.userId);
-            if (target.target_provider) {
-                // Drop the sync if the account of this operation no longer exists.
-                AccountAndUser[] accounts = mRunningAccounts;
-                if (!containsAccountAndUser(accounts, target.account, target.userId)) {
-                    if (isLoggable) {
-                        Log.v(TAG, "    Dropping sync operation: account doesn't exist.");
-                    }
-                    return false;
+            // Drop the sync if the account of this operation no longer exists.
+            AccountAndUser[] accounts = mRunningAccounts;
+            if (!containsAccountAndUser(accounts, target.account, target.userId)) {
+                if (isLoggable) {
+                    Slog.v(TAG, "    Dropping sync operation: account doesn't exist.");
                 }
-                // Drop this sync request if it isn't syncable.
-                state = getIsSyncable(target.account, target.userId, target.provider);
-                if (state == 0) {
-                    if (isLoggable) {
-                        Log.v(TAG, "    Dropping sync operation: isSyncable == 0.");
-                    }
-                    return false;
-                }
-                syncEnabled = syncEnabled && mSyncStorageEngine.getSyncAutomatically(
-                        target.account, target.userId, target.provider);
-
-                final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
-                syncAdapterInfo = mSyncAdapters.getServiceInfo(
-                        SyncAdapterType.newKey(
-                                target.provider, target.account.type), target.userId);
-                if (syncAdapterInfo != null) {
-                    targetUid = syncAdapterInfo.uid;
-                } else {
-                    if (isLoggable) {
-                        Log.v(TAG, "    Dropping sync operation: No sync adapter registered"
-                                + "for: " + target);
-                    }
-                    return false;
-                }
-            } else if (target.target_service) {
-                state = mSyncStorageEngine.getIsTargetServiceActive(target.service, target.userId)
-                            ? 1 : 0;
-                if (state == 0) {
-                    // TODO: Change this to not drop disabled syncs - keep them in the pending queue.
-                    if (isLoggable) {
-                        Log.v(TAG, "    Dropping sync operation: isActive == 0.");
-                    }
-                    return false;
-                }
-                try {
-                    targetUid = mContext.getPackageManager()
-                            .getServiceInfo(target.service, 0)
-                            .applicationInfo
-                            .uid;
-                } catch (PackageManager.NameNotFoundException e) {
-                    if (isLoggable) {
-                        Log.v(TAG, "    Dropping sync operation: No service registered for: "
-                                + target.service);
-                    }
-                    return false;
-                }
-            } else {
-                Log.e(TAG, "Unknown target for Sync Op: " + target);
                 return false;
             }
+            // Drop this sync request if it isn't syncable.
+            state = getIsSyncable(target.account, target.userId, target.provider);
+            if (state == 0) {
+                if (isLoggable) {
+                    Slog.v(TAG, "    Dropping sync operation: isSyncable == 0.");
+                }
+                return false;
+            }
+            syncEnabled = syncEnabled && mSyncStorageEngine.getSyncAutomatically(
+                    target.account, target.userId, target.provider);
 
             // We ignore system settings that specify the sync is invalid if:
             // 1) It's manual - we try it anyway. When/if it fails it will be rescheduled.
             //      or
             // 2) it's an initialisation sync - we just need to connect to it.
-            final boolean ignoreSystemConfiguration =
-                    op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false)
-                    || (state < 0);
+            final boolean ignoreSystemConfiguration = op.isIgnoreSettings() || (state < 0);
 
             // Sync not enabled.
             if (!syncEnabled && !ignoreSystemConfiguration) {
                 if (isLoggable) {
-                    Log.v(TAG, "    Dropping sync operation: disallowed by settings/network.");
-                }
-                return false;
-            }
-            // Network down.
-            final NetworkInfo networkInfo = getConnectivityManager()
-                    .getActiveNetworkInfoForUid(targetUid);
-            final boolean uidNetworkConnected = networkInfo != null && networkInfo.isConnected();
-            if (!uidNetworkConnected && !ignoreSystemConfiguration) {
-                if (isLoggable) {
-                    Log.v(TAG, "    Dropping sync operation: disallowed by settings/network.");
-                }
-                return false;
-            }
-            // Metered network.
-            if (op.isNotAllowedOnMetered() && getConnectivityManager().isActiveNetworkMetered()
-                    && !ignoreSystemConfiguration) {
-                if (isLoggable) {
-                    Log.v(TAG, "    Dropping sync operation: not allowed on metered network.");
+                    Slog.v(TAG, "    Dropping sync operation: disallowed by settings/network.");
                 }
                 return false;
             }
@@ -3024,65 +2720,42 @@
 
         private boolean dispatchSyncOperation(SyncOperation op) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "dispatchSyncOperation: we are going to sync " + op);
-                Log.v(TAG, "num active syncs: " + mActiveSyncContexts.size());
+                Slog.v(TAG, "dispatchSyncOperation: we are going to sync " + op);
+                Slog.v(TAG, "num active syncs: " + mActiveSyncContexts.size());
                 for (ActiveSyncContext syncContext : mActiveSyncContexts) {
-                    Log.v(TAG, syncContext.toString());
+                    Slog.v(TAG, syncContext.toString());
                 }
             }
             // Connect to the sync adapter.
             int targetUid;
             ComponentName targetComponent;
             final SyncStorageEngine.EndPoint info = op.target;
-            if (info.target_provider) {
-                SyncAdapterType syncAdapterType =
-                        SyncAdapterType.newKey(info.provider, info.account.type);
-                final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
-                syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, info.userId);
-                if (syncAdapterInfo == null) {
-                    Log.d(TAG, "can't find a sync adapter for " + syncAdapterType
-                            + ", removing settings for it");
-                    mSyncStorageEngine.removeAuthority(info);
-                    return false;
-                }
-                targetUid = syncAdapterInfo.uid;
-                targetComponent = syncAdapterInfo.componentName;
-            } else {
-                // TODO: Store the uid of the service as part of the authority info in order to
-                // avoid this call?
-                try {
-                    targetUid = mContext.getPackageManager()
-                            .getServiceInfo(info.service, 0)
-                            .applicationInfo
-                            .uid;
-                    targetComponent = info.service;
-                } catch(PackageManager.NameNotFoundException e) {
-                    Log.d(TAG, "Can't find a service for " + info.service
-                            + ", removing settings for it");
-                    mSyncStorageEngine.removeAuthority(info);
-                    return false;
-                }
+            SyncAdapterType syncAdapterType =
+                    SyncAdapterType.newKey(info.provider, info.account.type);
+            final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
+            syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, info.userId);
+            if (syncAdapterInfo == null) {
+                Log.d(TAG, "can't find a sync adapter for " + syncAdapterType
+                        + ", removing settings for it");
+                mSyncStorageEngine.removeAuthority(info);
+                return false;
             }
+            targetUid = syncAdapterInfo.uid;
+            targetComponent = syncAdapterInfo.componentName;
             ActiveSyncContext activeSyncContext =
                     new ActiveSyncContext(op, insertStartSyncEvent(op), targetUid);
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "dispatchSyncOperation: starting " + activeSyncContext);
+                Slog.v(TAG, "dispatchSyncOperation: starting " + activeSyncContext);
             }
 
             activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext);
             mActiveSyncContexts.add(activeSyncContext);
-            // Post message to cancel this sync if it runs for too long.
-            if (!activeSyncContext.mSyncOperation.isExpedited() &&
-                    !activeSyncContext.mSyncOperation.isManual() &&
-                    !activeSyncContext.mSyncOperation.isIgnoreSettings()) {
-                postSyncExpiryMessage(activeSyncContext);
-            }
 
             // Post message to begin monitoring this sync's progress.
             postMonitorSyncProgressMessage(activeSyncContext);
 
             if (!activeSyncContext.bindToSyncAdapter(targetComponent, info.userId)) {
-                Log.e(TAG, "Bind attempt failed - target: " + targetComponent);
+                Slog.e(TAG, "Bind attempt failed - target: " + targetComponent);
                 closeActiveSyncContext(activeSyncContext);
                 return false;
             }
@@ -3090,33 +2763,25 @@
             return true;
         }
 
-        private void runBoundToAdapter(final ActiveSyncContext activeSyncContext,
-                IBinder syncAdapter) {
+        private void runBoundToAdapterH(final ActiveSyncContext activeSyncContext,
+                                        IBinder syncAdapter) {
             final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
             try {
                 activeSyncContext.mIsLinkedToDeath = true;
                 syncAdapter.linkToDeath(activeSyncContext, 0);
 
-                if (syncOperation.target.target_provider) {
-                    activeSyncContext.mSyncAdapter = ISyncAdapter.Stub.asInterface(syncAdapter);
-                    activeSyncContext.mSyncAdapter
+                activeSyncContext.mSyncAdapter = ISyncAdapter.Stub.asInterface(syncAdapter);
+                activeSyncContext.mSyncAdapter
                         .startSync(activeSyncContext, syncOperation.target.provider,
                                 syncOperation.target.account, syncOperation.extras);
-                } else if (syncOperation.target.target_service) {
-                    activeSyncContext.mSyncServiceAdapter =
-                            ISyncServiceAdapter.Stub.asInterface(syncAdapter);
-                    activeSyncContext.mSyncServiceAdapter
-                        .startSync(activeSyncContext, syncOperation.extras);
-                }
             } catch (RemoteException remoteExc) {
                 Log.d(TAG, "maybeStartNextSync: caught a RemoteException, rescheduling", remoteExc);
                 closeActiveSyncContext(activeSyncContext);
-                increaseBackoffSetting(syncOperation);
-                scheduleSyncOperation(
-                        new SyncOperation(syncOperation, 0L /* newRunTimeFromNow */));
+                increaseBackoffSetting(syncOperation.target);
+                scheduleSyncOperationH(syncOperation);
             } catch (RuntimeException exc) {
                 closeActiveSyncContext(activeSyncContext);
-                Log.e(TAG, "Caught RuntimeException while starting the sync " + syncOperation, exc);
+                Slog.e(TAG, "Caught RuntimeException while starting the sync " + syncOperation, exc);
             }
         }
 
@@ -3141,25 +2806,31 @@
                                     false /* no config settings */)) {
                         continue;
                     }
+                    mSyncJobService.callJobFinished(activeSyncContext.mSyncOperation.jobId, false);
                     runSyncFinishedOrCanceledH(null /* cancel => no result */, activeSyncContext);
                 }
             }
         }
 
+        /**
+         * Should be called when a one-off instance of a periodic sync completes successfully.
+         */
+        private void reschedulePeriodicSyncH(SyncOperation syncOperation) {
+            removeSyncOperationFromCache(syncOperation.sourcePeriodicId);
+            getJobScheduler().cancel(syncOperation.sourcePeriodicId);
+            SyncOperation periodic = syncOperation.createPeriodicSyncOperation();
+            scheduleSyncOperationH(periodic);
+        }
+
         private void runSyncFinishedOrCanceledH(SyncResult syncResult,
                                                 ActiveSyncContext activeSyncContext) {
-            boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
+            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
 
             final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
             final SyncStorageEngine.EndPoint info = syncOperation.target;
 
             if (activeSyncContext.mIsLinkedToDeath) {
-                if (info.target_provider) {
-                    activeSyncContext.mSyncAdapter.asBinder().unlinkToDeath(activeSyncContext, 0);
-                } else {
-                    activeSyncContext.mSyncServiceAdapter.asBinder()
-                        .unlinkToDeath(activeSyncContext, 0);
-                }
+                activeSyncContext.mSyncAdapter.asBinder().unlinkToDeath(activeSyncContext, 0);
                 activeSyncContext.mIsLinkedToDeath = false;
             }
             closeActiveSyncContext(activeSyncContext);
@@ -3169,7 +2840,7 @@
             int upstreamActivity;
             if (syncResult != null) {
                 if (isLoggable) {
-                    Log.v(TAG, "runSyncFinishedOrCanceled [finished]: "
+                    Slog.v(TAG, "runSyncFinishedOrCanceled [finished]: "
                             + syncOperation + ", result " + syncResult);
                 }
 
@@ -3178,23 +2849,35 @@
                     // TODO: set these correctly when the SyncResult is extended to include it
                     downstreamActivity = 0;
                     upstreamActivity = 0;
-                    clearBackoffSetting(syncOperation);
+                    clearBackoffSetting(syncOperation.target);
+
+                    // If the operation completes successfully and it was scheduled due to
+                    // a periodic operation failing, we reschedule the periodic operation to
+                    // start from now.
+                    if (syncOperation.isDerivedFromFailedPeriodicSync()) {
+                        reschedulePeriodicSyncH(syncOperation);
+                    }
                 } else {
                     Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
                     // the operation failed so increase the backoff time
-                    increaseBackoffSetting(syncOperation);
-                    // reschedule the sync if so indicated by the syncResult
-                    maybeRescheduleSync(syncResult, syncOperation);
+                    increaseBackoffSetting(syncOperation.target);
+                    if (!syncOperation.isPeriodic) {
+                        // reschedule the sync if so indicated by the syncResult
+                        maybeRescheduleSync(syncResult, syncOperation);
+                    } else {
+                        // create a normal sync instance that will respect adapter backoffs
+                        postScheduleSyncMessage(syncOperation.createOneTimeSyncOperation());
+                    }
                     historyMessage = ContentResolver.syncErrorToString(
                             syncResultToErrorNumber(syncResult));
                     // TODO: set these correctly when the SyncResult is extended to include it
                     downstreamActivity = 0;
                     upstreamActivity = 0;
                 }
-                setDelayUntilTime(syncOperation, syncResult.delayUntil);
+                setDelayUntilTime(syncOperation.target, syncResult.delayUntil);
             } else {
                 if (isLoggable) {
-                    Log.v(TAG, "runSyncFinishedOrCanceled [canceled]: " + syncOperation);
+                    Slog.v(TAG, "runSyncFinishedOrCanceled [canceled]: " + syncOperation);
                 }
                 if (activeSyncContext.mSyncAdapter != null) {
                     try {
@@ -3202,12 +2885,6 @@
                     } catch (RemoteException e) {
                         // we don't need to retry this in this case
                     }
-                } else if (activeSyncContext.mSyncServiceAdapter != null) {
-                    try {
-                        activeSyncContext.mSyncServiceAdapter.cancelSync(activeSyncContext);
-                    } catch (RemoteException e) {
-                        // we don't need to retry this in this case
-                    }
                 }
                 historyMessage = SyncStorageEngine.MESG_CANCELED;
                 downstreamActivity = 0;
@@ -3217,38 +2894,23 @@
             stopSyncEvent(activeSyncContext.mHistoryRowId, syncOperation, historyMessage,
                     upstreamActivity, downstreamActivity, elapsedTime);
             // Check for full-resync and schedule it after closing off the last sync.
-            if (info.target_provider) {
-                if (syncResult != null && syncResult.tooManyDeletions) {
-                    installHandleTooManyDeletesNotification(info.account,
-                            info.provider, syncResult.stats.numDeletes,
-                            info.userId);
-                } else {
-                    mNotificationMgr.cancelAsUser(null,
-                            info.account.hashCode() ^ info.provider.hashCode(),
-                            new UserHandle(info.userId));
-                }
-                if (syncResult != null && syncResult.fullSyncRequested) {
-                    scheduleSyncOperation(
-                            new SyncOperation(info.account, info.userId,
-                                    syncOperation.owningUid, syncOperation.owningPackage,
+            if (syncResult != null && syncResult.tooManyDeletions) {
+                installHandleTooManyDeletesNotification(info.account,
+                        info.provider, syncResult.stats.numDeletes,
+                        info.userId);
+            } else {
+                mNotificationMgr.cancelAsUser(null,
+                        info.account.hashCode() ^ info.provider.hashCode(),
+                        new UserHandle(info.userId));
+            }
+            if (syncResult != null && syncResult.fullSyncRequested) {
+                scheduleSyncOperationH(
+                        new SyncOperation(info.account, info.userId,
+                                syncOperation.owningUid, syncOperation.owningPackage,
                                 syncOperation.reason,
                                 syncOperation.syncSource, info.provider, new Bundle(),
-                                0 /* delay */, 0 /* flex */,
-                                syncOperation.backoff, syncOperation.delayUntil,
                                 syncOperation.allowParallelSyncs));
-                }
-            } else {
-                if (syncResult != null && syncResult.fullSyncRequested) {
-                    scheduleSyncOperation(
-                            new SyncOperation(info.service, info.userId,
-                                    syncOperation.owningUid, syncOperation.owningPackage,
-                                syncOperation.reason,
-                                syncOperation.syncSource, new Bundle(),
-                                0 /* delay */, 0 /* flex */,
-                                syncOperation.backoff, syncOperation.delayUntil));
-                }
             }
-            // no need to schedule an alarm, as that will be done by our caller.
         }
 
         private void closeActiveSyncContext(ActiveSyncContext activeSyncContext) {
@@ -3258,7 +2920,7 @@
                     activeSyncContext.mSyncOperation.target.userId);
 
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "removing all MESSAGE_MONITOR_SYNC & MESSAGE_SYNC_EXPIRED for "
+                Slog.v(TAG, "removing all MESSAGE_MONITOR_SYNC & MESSAGE_SYNC_EXPIRED for "
                         + activeSyncContext.toString());
             }
             mSyncHandler.removeMessages(SyncHandler.MESSAGE_SYNC_EXPIRED, activeSyncContext);
@@ -3294,82 +2956,8 @@
             throw new IllegalStateException("we are not in an error state, " + syncResult);
         }
 
-        private void manageSyncAlarmLocked(long nextPeriodicEventElapsedTime,
-                long nextPendingEventElapsedTime) {
-            // in each of these cases the sync loop will be kicked, which will cause this
-            // method to be called again
-            if (!mDataConnectionIsConnected) return;
-            if (mStorageIsLow) return;
-            if (mDeviceIsIdle) return;
-
-            // When we should consider canceling an active sync
-            long earliestTimeoutTime = Long.MAX_VALUE;
-            for (ActiveSyncContext currentSyncContext : mActiveSyncContexts) {
-                final long currentSyncTimeoutTime =
-                        currentSyncContext.mTimeoutStartTime + MAX_TIME_PER_SYNC;
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "manageSyncAlarm: active sync, mTimeoutStartTime + MAX is "
-                            + currentSyncTimeoutTime);
-                }
-                if (earliestTimeoutTime > currentSyncTimeoutTime) {
-                    earliestTimeoutTime = currentSyncTimeoutTime;
-                }
-            }
-
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "manageSyncAlarm: earliestTimeoutTime is " + earliestTimeoutTime);
-                Log.v(TAG, "manageSyncAlarm: nextPeriodicEventElapsedTime is "
-                        + nextPeriodicEventElapsedTime);
-                Log.v(TAG, "manageSyncAlarm: nextPendingEventElapsedTime is "
-                        + nextPendingEventElapsedTime);
-            }
-
-            long alarmTime = Math.min(earliestTimeoutTime, nextPeriodicEventElapsedTime);
-            alarmTime = Math.min(alarmTime, nextPendingEventElapsedTime);
-
-            // Bound the alarm time.
-            final long now = SystemClock.elapsedRealtime();
-            if (alarmTime < now + SYNC_ALARM_TIMEOUT_MIN) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "manageSyncAlarm: the alarmTime is too small, "
-                            + alarmTime + ", setting to " + (now + SYNC_ALARM_TIMEOUT_MIN));
-                }
-                alarmTime = now + SYNC_ALARM_TIMEOUT_MIN;
-            }
-
-            // Determine if we need to set or cancel the alarm
-            boolean shouldSet = false;
-            boolean shouldCancel = false;
-            final boolean alarmIsActive = (mAlarmScheduleTime != null) && (now < mAlarmScheduleTime);
-
-            if (alarmTime != Long.MAX_VALUE) {
-                // Need the alarm if it isn't set or has changed.
-                if (!alarmIsActive || alarmTime != mAlarmScheduleTime) {
-                    shouldSet = true;
-                }
-            } else {
-                shouldCancel = alarmIsActive;
-            }
-
-            // Set or cancel the alarm as directed.
-            ensureAlarmService();
-            if (shouldSet) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "requesting that the alarm manager wake us up at elapsed time "
-                            + alarmTime + ", now is " + now + ", " + ((alarmTime - now) / 1000)
-                            + " secs from now");
-                }
-                mAlarmScheduleTime = alarmTime;
-                mAlarmService.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime,
-                        mSyncAlarmIntent);
-            } else if (shouldCancel) {
-                mAlarmScheduleTime = null;
-                mAlarmService.cancel(mSyncAlarmIntent);
-            }
-        }
-
         private void installHandleTooManyDeletesNotification(Account account, String authority,
-                long numDeletes, int userId) {
+                                                             long numDeletes, int userId) {
             if (mNotificationMgr == null) return;
 
             final ProviderInfo providerInfo = mContext.getPackageManager().resolveContentProvider(
@@ -3445,7 +3033,7 @@
         }
 
         public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage,
-                int upstreamActivity, int downstreamActivity, long elapsedTime) {
+                                  int upstreamActivity, int downstreamActivity, long elapsedTime) {
             EventLog.writeEvent(2720,
                     syncOperation.toEventLog(SyncStorageEngine.EVENT_STOP));
             mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime,
@@ -3453,21 +3041,6 @@
         }
     }
 
-    String getPackageName(EndPoint endpoint) {
-        if (endpoint.target_service) {
-            return endpoint.service.getPackageName();
-        } else {
-            SyncAdapterType syncAdapterType =
-                    SyncAdapterType.newKey(endpoint.provider, endpoint.account.type);
-            final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
-            syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, endpoint.userId);
-            if (syncAdapterInfo == null) {
-                return null;
-            }
-            return syncAdapterInfo.componentName.getPackageName();
-        }
-    }
-
     private boolean isSyncStillActiveH(ActiveSyncContext activeSyncContext) {
         for (ActiveSyncContext sync : mActiveSyncContexts) {
             if (sync == activeSyncContext) {
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index ab777ae..4fb31c0 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -18,22 +18,27 @@
 
 import android.accounts.Account;
 import android.content.pm.PackageManager;
-import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.os.Bundle;
-import android.os.SystemClock;
+import android.os.PersistableBundle;
 import android.os.UserHandle;
-import android.util.Log;
+import android.util.Slog;
 
 /**
  * Value type that represents a sync operation.
- * TODO: This is the class to flesh out with all the scheduling data - metered/unmetered,
- * transfer-size, etc.
+ * This holds all information related to a sync operation - both one off and periodic.
+ * Data stored in this is used to schedule a job with the JobScheduler.
  * {@hide}
  */
-public class SyncOperation implements Comparable {
+public class SyncOperation {
     public static final String TAG = "SyncManager";
 
+    /**
+     * This is used in the {@link #sourcePeriodicId} field if the operation is not initiated by a failed
+     * periodic sync.
+     */
+    public static final int NO_JOB_ID = -1;
+
     public static final int REASON_BACKGROUND_DATA_SETTINGS_CHANGED = -1;
     public static final int REASON_ACCOUNTS_UPDATED = -2;
     public static final int REASON_SERVICE_CHANGED = -3;
@@ -57,10 +62,6 @@
             "UserStart",
     };
 
-    public static final int SYNC_TARGET_UNKNOWN = 0;
-    public static final int SYNC_TARGET_ADAPTER = 1;
-    public static final int SYNC_TARGET_SERVICE = 2;
-
     /** Identifying info for the target for this operation. */
     public final SyncStorageEngine.EndPoint target;
     public final int owningUid;
@@ -70,51 +71,44 @@
     /** Where this sync was initiated. */
     public final int syncSource;
     public final boolean allowParallelSyncs;
+    public final Bundle extras;
+    public final boolean isPeriodic;
+    /** jobId of the periodic SyncOperation that initiated this one */
+    public final int sourcePeriodicId;
+    /** Operations are considered duplicates if keys are equal */
     public final String key;
-    /** Internal boolean to avoid reading a bundle everytime we want to compare operations. */
-    private final boolean expedited;
-    public Bundle extras;
-    /** Bare-bones version of this operation that is persisted across reboots. */
-    public SyncStorageEngine.PendingOperation pendingOperation;
-    /** Elapsed real time in millis at which to run this sync. */
-    public long latestRunTime;
-    /** Set by the SyncManager in order to delay retries. */
-    public long backoff;
-    /** Specified by the adapter to delay subsequent sync operations. */
-    public long delayUntil;
-    /**
-     * Elapsed real time in millis when this sync will be run.
-     * Depends on max(backoff, latestRunTime, and delayUntil).
-     */
-    public long effectiveRunTime;
-    /** Amount of time before {@link #effectiveRunTime} from which this sync can run. */
-    public long flexTime;
 
+    /** Poll frequency of periodic sync in milliseconds */
+    public long periodMillis;
+    /** Flex time of periodic sync in milliseconds */
+    public long flexMillis;
     /** Descriptive string key for this operation */
     public String wakeLockName;
+    /**
+     * Used when duplicate pending syncs are present. The one with the lowest expectedRuntime
+     * is kept, others are discarded.
+     */
+    public long expectedRuntime;
 
-    /** Whether this sync op was recently skipped due to the app being idle */
-    public boolean appIdle;
+    /** jobId of the JobScheduler job corresponding to this sync */
+    public int jobId;
 
     public SyncOperation(Account account, int userId, int owningUid, String owningPackage,
-            int reason, int source, String provider, Bundle extras, long runTimeFromNow,
-            long flexTime, long backoff, long delayUntil, boolean allowParallelSyncs) {
+                         int reason, int source, String provider, Bundle extras,
+                         boolean allowParallelSyncs) {
         this(new SyncStorageEngine.EndPoint(account, provider, userId), owningUid, owningPackage,
-                reason, source, extras, runTimeFromNow, flexTime, backoff, delayUntil,
-                allowParallelSyncs);
-    }
-
-    public SyncOperation(ComponentName service, int userId, int owningUid, String owningPackage,
-            int reason, int source, Bundle extras, long runTimeFromNow, long flexTime, long backoff,
-            long delayUntil) {
-        this(new SyncStorageEngine.EndPoint(service, userId, owningUid), owningUid, owningPackage,
-                reason, source, extras, runTimeFromNow, flexTime, backoff, delayUntil,
-                true /* allowParallelSyncs */);
+                reason, source, extras, allowParallelSyncs);
     }
 
     private SyncOperation(SyncStorageEngine.EndPoint info, int owningUid, String owningPackage,
-            int reason, int source, Bundle extras, long runTimeFromNow, long flexTime,
-            long backoff, long delayUntil, boolean allowParallelSyncs) {
+                          int reason, int source, Bundle extras, boolean allowParallelSyncs) {
+        this(info, owningUid, owningPackage, reason, source, extras, allowParallelSyncs, false,
+                NO_JOB_ID);
+    }
+
+    public SyncOperation(SyncStorageEngine.EndPoint info, int owningUid, String owningPackage,
+                         int reason, int source, Bundle extras, boolean allowParallelSyncs,
+                         boolean isPeriodic, int sourcePeriodicId) {
         this.target = info;
         this.owningUid = owningUid;
         this.owningPackage = owningPackage;
@@ -122,43 +116,173 @@
         this.syncSource = source;
         this.extras = new Bundle(extras);
         cleanBundle(this.extras);
-        this.delayUntil = delayUntil;
-        this.backoff = backoff;
         this.allowParallelSyncs = allowParallelSyncs;
-        final long now = SystemClock.elapsedRealtime();
-        // Set expedited based on runTimeFromNow. The SyncManager specifies whether the op is
-        // expedited (Not done solely based on bundle).
-        if (runTimeFromNow < 0) {
-            this.expedited = true;
-            // Sanity check: Will always be true.
-            if (!this.extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
-                this.extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
-            }
-            this.latestRunTime = now;
-            this.flexTime = 0;
-        } else {
-            this.expedited = false;
-            this.extras.remove(ContentResolver.SYNC_EXTRAS_EXPEDITED);
-            this.latestRunTime = now + runTimeFromNow;
-            this.flexTime = flexTime;
+        this.isPeriodic = isPeriodic;
+        this.sourcePeriodicId = sourcePeriodicId;
+        this.key = toKey(target, extras);
+    }
+
+    /* Get a one off sync operation instance from a periodic sync. */
+    public SyncOperation createOneTimeSyncOperation() {
+        if (!isPeriodic) {
+            return null;
         }
-        updateEffectiveRunTime();
-        this.key = toKey(info, this.extras);
+        SyncOperation op = new SyncOperation(target, owningUid, owningPackage, reason, syncSource,
+                new Bundle(extras), allowParallelSyncs, false, jobId /* sourcePeriodicId */);
+        // Copied to help us recreate the periodic sync from this one off sync.
+        op.periodMillis = periodMillis;
+        op.flexMillis = flexMillis;
+        return op;
     }
 
-    /** Used to reschedule a sync at a new point in time. */
-    public SyncOperation(SyncOperation other, long newRunTimeFromNow) {
-        this(other.target, other.owningUid, other.owningPackage, other.reason, other.syncSource,
-                new Bundle(other.extras),
-                newRunTimeFromNow,
-                0L /* In back-off so no flex */,
-                other.backoff,
-                other.delayUntil,
-                other.allowParallelSyncs);
+    public SyncOperation createPeriodicSyncOperation() {
+        SyncOperation op = new SyncOperation(target, owningUid, owningPackage, reason, syncSource,
+                new Bundle(extras), allowParallelSyncs, true, NO_JOB_ID);
+        op.periodMillis = periodMillis;
+        op.flexMillis = flexMillis;
+        return op;
     }
 
-    public boolean matchesAuthority(SyncOperation other) {
-        return this.target.matchesSpec(other.target);
+    public SyncOperation(SyncOperation other) {
+        target = other.target;
+        owningUid = other.owningUid;
+        owningPackage = other.owningPackage;
+        reason = other.reason;
+        syncSource = other.syncSource;
+        allowParallelSyncs = other.allowParallelSyncs;
+        extras = new Bundle(other.extras);
+        wakeLockName = other.wakeLockName();
+        isPeriodic = other.isPeriodic;
+        sourcePeriodicId = other.sourcePeriodicId;
+        periodMillis = other.periodMillis;
+        flexMillis = other.flexMillis;
+        this.key = other.key;
+    }
+
+    /**
+     * All fields are stored in a corresponding key in the persistable bundle.
+     *
+     * {@link #extras} is a Bundle and can contain parcelable objects. But only the type Account
+     * is allowed {@link ContentResolver#validateSyncExtrasBundle(Bundle)} that can't be stored in
+     * a PersistableBundle. For every value of type Account with key 'key', we store a
+     * PersistableBundle containing account information at key 'ACCOUNT:key'. The Account object
+     * can be reconstructed using this.
+     *
+     * We put a flag with key 'SyncManagerJob', to identify while reconstructing a sync operation
+     * from a bundle whether the bundle actually contains information about a sync.
+     * @return A persistable bundle containing all information to re-construct the sync operation.
+     */
+    PersistableBundle toJobInfoExtras() {
+        // This will be passed as extras bundle to a JobScheduler job.
+        PersistableBundle jobInfoExtras = new PersistableBundle();
+
+        PersistableBundle syncExtrasBundle = new PersistableBundle();
+        for (String key: extras.keySet()) {
+            Object value = extras.get(key);
+            if (value instanceof Account) {
+                Account account = (Account) value;
+                PersistableBundle accountBundle = new PersistableBundle();
+                accountBundle.putString("accountName", account.name);
+                accountBundle.putString("accountType", account.type);
+                // This is stored in jobInfoExtras so that we don't override a user specified
+                // sync extra with the same key.
+                jobInfoExtras.putPersistableBundle("ACCOUNT:" + key, accountBundle);
+            } else if (value instanceof Long) {
+                syncExtrasBundle.putLong(key, (Long) value);
+            } else if (value instanceof Integer) {
+                syncExtrasBundle.putInt(key, (Integer) value);
+            } else if (value instanceof Boolean) {
+                syncExtrasBundle.putBoolean(key, (Boolean) value);
+            } else if (value instanceof Float) {
+                syncExtrasBundle.putDouble(key, (Double) value);
+            } else if (value instanceof Double) {
+                syncExtrasBundle.putDouble(key, (Double) value);
+            } else if (value instanceof String) {
+                syncExtrasBundle.putString(key, (String) value);
+            } else if (value == null) {
+                syncExtrasBundle.putString(key, null);
+            } else {
+                Slog.e(TAG, "Unknown extra type.");
+            }
+        }
+        jobInfoExtras.putPersistableBundle("syncExtras", syncExtrasBundle);
+
+        jobInfoExtras.putBoolean("SyncManagerJob", true);
+
+        jobInfoExtras.putString("provider", target.provider);
+        jobInfoExtras.putString("accountName", target.account.name);
+        jobInfoExtras.putString("accountType", target.account.type);
+        jobInfoExtras.putInt("userId", target.userId);
+        jobInfoExtras.putInt("owningUid", owningUid);
+        jobInfoExtras.putString("owningPackage", owningPackage);
+        jobInfoExtras.putInt("reason", reason);
+        jobInfoExtras.putInt("source", syncSource);
+        jobInfoExtras.putBoolean("allowParallelSyncs", allowParallelSyncs);
+        jobInfoExtras.putInt("jobId", jobId);
+        jobInfoExtras.putBoolean("isPeriodic", isPeriodic);
+        jobInfoExtras.putInt("sourcePeriodicId", sourcePeriodicId);
+        jobInfoExtras.putLong("periodMillis", periodMillis);
+        jobInfoExtras.putLong("flexMillis", flexMillis);
+        jobInfoExtras.putLong("expectedRuntime", expectedRuntime);
+        return jobInfoExtras;
+    }
+
+    /**
+     * Reconstructs a sync operation from an extras Bundle. Returns null if the bundle doesn't
+     * contain a valid sync operation.
+     */
+    static SyncOperation maybeCreateFromJobExtras(PersistableBundle jobExtras) {
+        String accountName, accountType;
+        String provider;
+        int userId, owningUid;
+        String owningPackage;
+        int reason, source;
+        int initiatedBy;
+        Bundle extras;
+        boolean allowParallelSyncs, isPeriodic;
+
+        if (!jobExtras.getBoolean("SyncManagerJob", false)) {
+            return null;
+        }
+
+        accountName = jobExtras.getString("accountName");
+        accountType = jobExtras.getString("accountType");
+        provider = jobExtras.getString("provider");
+        userId = jobExtras.getInt("userId", Integer.MAX_VALUE);
+        owningUid = jobExtras.getInt("owningUid");
+        owningPackage = jobExtras.getString("owningPackage");
+        reason = jobExtras.getInt("reason", Integer.MAX_VALUE);
+        source = jobExtras.getInt("source", Integer.MAX_VALUE);
+        allowParallelSyncs = jobExtras.getBoolean("allowParallelSyncs", false);
+        isPeriodic = jobExtras.getBoolean("isPeriodic", false);
+        initiatedBy = jobExtras.getInt("sourcePeriodicId", NO_JOB_ID);
+        extras = new Bundle();
+
+        PersistableBundle syncExtras = jobExtras.getPersistableBundle("syncExtras");
+        if (syncExtras != null) {
+            extras.putAll(syncExtras);
+        }
+
+        for (String key: jobExtras.keySet()) {
+            if (key!= null && key.startsWith("ACCOUNT:")) {
+                String newKey = key.substring(8); // Strip off the 'ACCOUNT:' prefix.
+                PersistableBundle accountsBundle = jobExtras.getPersistableBundle(key);
+                Account account = new Account(accountsBundle.getString("accountName"),
+                        accountsBundle.getString("accountType"));
+                extras.putParcelable(newKey, account);
+            }
+        }
+
+        Account account = new Account(accountName, accountType);
+        SyncStorageEngine.EndPoint target =
+                new SyncStorageEngine.EndPoint(account, provider, userId);
+        SyncOperation op = new SyncOperation(target, owningUid, owningPackage, reason, source,
+                extras, allowParallelSyncs, isPeriodic, initiatedBy);
+        op.jobId = jobExtras.getInt("jobId");
+        op.periodMillis = jobExtras.getLong("periodMillis");
+        op.flexMillis = jobExtras.getLong("flexMillis");
+        op.expectedRuntime = jobExtras.getLong("expectedRuntime");
+        return op;
     }
 
     /**
@@ -187,21 +311,46 @@
     /**
      * Determine whether if this sync operation is running, the provided operation would conflict
      * with it.
-     * Parallel syncs allow multiple accounts to be synced at the same time. 
+     * Parallel syncs allow multiple accounts to be synced at the same time.
      */
-    public boolean isConflict(SyncOperation toRun) {
+    boolean isConflict(SyncOperation toRun) {
         final SyncStorageEngine.EndPoint other = toRun.target;
-        if (target.target_provider) {
-            return target.account.type.equals(other.account.type)
-                    && target.provider.equals(other.provider)
-                    && target.userId == other.userId
-                    && (!allowParallelSyncs
-                            || target.account.name.equals(other.account.name));
-        } else {
-            // Ops that target a service default to allow parallel syncs, which is handled by the
-            // service returning SYNC_IN_PROGRESS if they don't.
-            return target.service.equals(other.service) && !allowParallelSyncs;
+        return target.account.type.equals(other.account.type)
+                && target.provider.equals(other.provider)
+                && target.userId == other.userId
+                && (!allowParallelSyncs
+                || target.account.name.equals(other.account.name));
+    }
+
+    boolean isReasonPeriodic() {
+        return reason == REASON_PERIODIC;
+    }
+
+    boolean isDerivedFromFailedPeriodicSync() {
+        return sourcePeriodicId != NO_JOB_ID;
+    }
+
+    int findPriority() {
+        if (isInitialization()) {
+            return 2;
+        } else if (isExpedited()) {
+            return 1;
         }
+        return 0;
+    }
+
+    static String toKey(SyncStorageEngine.EndPoint info, Bundle extras) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("provider: ").append(info.provider);
+        sb.append(" account {name=" + info.account.name
+                + ", user="
+                + info.userId
+                + ", type="
+                + info.account.type
+                + "}");
+        sb.append(" extras: ");
+        extrasToStringBuilder(extras, sb);
+        return sb.toString();
     }
 
     @Override
@@ -209,10 +358,9 @@
         return dump(null, true);
     }
 
-    public String dump(PackageManager pm, boolean useOneLine) {
+    String dump(PackageManager pm, boolean useOneLine) {
         StringBuilder sb = new StringBuilder();
-        if (target.target_provider) {
-            sb.append(target.account.name)
+        sb.append(target.account.name)
                 .append(" u")
                 .append(target.userId).append(" (")
                 .append(target.account.type)
@@ -220,21 +368,15 @@
                 .append(", ")
                 .append(target.provider)
                 .append(", ");
-        } else if (target.target_service) {
-            sb.append(target.service.getPackageName())
-                .append(" u")
-                .append(target.userId).append(" (")
-                .append(target.service.getClassName()).append(")")
-                .append(", ");
-        }
-        sb.append(SyncStorageEngine.SOURCES[syncSource])
-            .append(", currentRunTime ")
-            .append(effectiveRunTime);
-        if (expedited) {
+        sb.append(SyncStorageEngine.SOURCES[syncSource]);
+        if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
             sb.append(", EXPEDITED");
         }
         sb.append(", reason: ");
         sb.append(reasonToString(pm, reason));
+        if (isPeriodic) {
+            sb.append(", period: " + periodMillis).append(", flexMillis: " + flexMillis);
+        }
         if (!useOneLine) {
             sb.append("\n    ");
             sb.append("owningUid=");
@@ -249,7 +391,7 @@
         return sb.toString();
     }
 
-    public static String reasonToString(PackageManager pm, int reason) {
+    static String reasonToString(PackageManager pm, int reason) {
         if (reason >= 0) {
             if (pm != null) {
                 final String[] packages = pm.getPackagesForUid(reason);
@@ -274,58 +416,30 @@
         }
     }
 
-    public boolean isInitialization() {
+    boolean isInitialization() {
         return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
     }
 
-    public boolean isExpedited() {
-        return expedited;
+    boolean isExpedited() {
+        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
     }
 
-    public boolean ignoreBackoff() {
+    boolean ignoreBackoff() {
         return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false);
     }
 
-    public boolean isNotAllowedOnMetered() {
+    boolean isNotAllowedOnMetered() {
         return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
     }
 
-    public boolean isManual() {
+    boolean isManual() {
         return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
     }
 
-    public boolean isIgnoreSettings() {
+    boolean isIgnoreSettings() {
         return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
     }
 
-    /** Changed in V3. */
-    public static String toKey(SyncStorageEngine.EndPoint info, Bundle extras) {
-        StringBuilder sb = new StringBuilder();
-        if (info.target_provider) {
-            sb.append("provider: ").append(info.provider);
-            sb.append(" account {name=" + info.account.name
-                    + ", user="
-                    + info.userId
-                    + ", type="
-                    + info.account.type
-                    + "}");
-        } else if (info.target_service) {
-            sb.append("service {package=" )
-                .append(info.service.getPackageName())
-                .append(" user=")
-                .append(info.userId)
-                .append(", class=")
-                .append(info.service.getClassName())
-                .append("}");
-        } else {
-            Log.v(TAG, "Converting SyncOperaton to key, invalid target: " + info.toString());
-            return "";
-        }
-        sb.append(" extras: ");
-        extrasToStringBuilder(extras, sb);
-        return sb.toString();
-    }
-
     private static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
         sb.append("[");
         for (String key : bundle.keySet()) {
@@ -334,57 +448,13 @@
         sb.append("]");
     }
 
-    public String wakeLockName() {
+    String wakeLockName() {
         if (wakeLockName != null) {
             return wakeLockName;
         }
-        if (target.target_provider) {
-            return (wakeLockName = target.provider
-                    + "/" + target.account.type
-                    + "/" + target.account.name);
-        } else if (target.target_service) {
-            return (wakeLockName = target.service.getPackageName()
-                    + "/" + target.service.getClassName());
-        } else {
-            Log.wtf(TAG, "Invalid target getting wakelock name for operation - " + key);
-            return null;
-        }
-    }
-
-    /**
-     * Update the effective run time of this Operation based on latestRunTime (specified at
-     * creation time of sync), delayUntil (specified by SyncAdapter), or backoff (specified by
-     * SyncManager on soft failures).
-     */
-    public void updateEffectiveRunTime() {
-        // Regardless of whether we're in backoff or honouring a delayUntil, we still incorporate
-        // the flex time provided by the developer.
-        effectiveRunTime = ignoreBackoff() ?
-                latestRunTime :
-                    Math.max(Math.max(latestRunTime, delayUntil), backoff);
-    }
-
-    /**
-     * SyncOperations are sorted based on their earliest effective run time.
-     * This comparator is used to sort the SyncOps at a given time when
-     * deciding which to run, so earliest run time is the best criteria.
-     */
-    @Override
-    public int compareTo(Object o) {
-        SyncOperation other = (SyncOperation) o;
-        if (expedited != other.expedited) {
-            return expedited ? -1 : 1;
-        }
-        long thisIntervalStart = Math.max(effectiveRunTime - flexTime, 0);
-        long otherIntervalStart = Math.max(
-            other.effectiveRunTime - other.flexTime, 0);
-        if (thisIntervalStart < otherIntervalStart) {
-            return -1;
-        } else if (otherIntervalStart < thisIntervalStart) {
-            return 1;
-        } else {
-            return 0;
-        }
+        return (wakeLockName = target.provider
+                + "/" + target.account.type
+                + "/" + target.account.name);
     }
 
     // TODO: Test this to make sure that casting to object doesn't lose the type info for EventLog.
@@ -392,15 +462,8 @@
         Object[] logArray = new Object[4];
         logArray[1] = event;
         logArray[2] = syncSource;
-        if (target.target_provider) {
-            logArray[0] = target.provider;
-            logArray[3] = target.account.name.hashCode();
-        } else if (target.target_service) {
-            logArray[0] = target.service.getPackageName();
-            logArray[3] = target.service.hashCode();
-        } else {
-            Log.wtf(TAG, "sync op with invalid target: " + key);
-        }
+        logArray[0] = target.provider;
+        logArray[3] = target.account.name.hashCode();
         return logArray;
     }
 }
diff --git a/services/core/java/com/android/server/content/SyncQueue.java b/services/core/java/com/android/server/content/SyncQueue.java
deleted file mode 100644
index b15d0d8..0000000
--- a/services/core/java/com/android/server/content/SyncQueue.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.content;
-
-import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
-import android.content.pm.PackageManager;
-import android.content.SyncAdapterType;
-import android.content.SyncAdaptersCache;
-import android.content.pm.RegisteredServicesCache.ServiceInfo;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.text.format.DateUtils;
-import android.util.Log;
-import android.util.Pair;
-
-import android.util.Slog;
-import com.google.android.collect.Maps;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * Queue of pending sync operations. Not inherently thread safe, external
- * callers are responsible for locking.
- *
- * @hide
- */
-public class SyncQueue {
-    private static final String TAG = "SyncManager";
-    private final SyncStorageEngine mSyncStorageEngine;
-    private final SyncAdaptersCache mSyncAdapters;
-    private final PackageManager mPackageManager;
-
-    // A Map of SyncOperations operationKey -> SyncOperation that is designed for
-    // quick lookup of an enqueued SyncOperation.
-    private final HashMap<String, SyncOperation> mOperationsMap = Maps.newHashMap();
-
-    public SyncQueue(PackageManager packageManager, SyncStorageEngine syncStorageEngine,
-            final SyncAdaptersCache syncAdapters) {
-        mPackageManager = packageManager;
-        mSyncStorageEngine = syncStorageEngine;
-        mSyncAdapters = syncAdapters;
-    }
-
-    public void addPendingOperations(int userId) {
-        for (SyncStorageEngine.PendingOperation op : mSyncStorageEngine.getPendingOperations()) {
-            final SyncStorageEngine.EndPoint info = op.target;
-            if (info.userId != userId) continue;
-
-            final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(info);
-            SyncOperation operationToAdd;
-            if (info.target_provider) {
-                final ServiceInfo<SyncAdapterType> syncAdapterInfo = mSyncAdapters.getServiceInfo(
-                        SyncAdapterType.newKey(info.provider, info.account.type), info.userId);
-                if (syncAdapterInfo == null) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "Missing sync adapter info for authority " + op.target);
-                    }
-                    continue;
-                }
-                operationToAdd = new SyncOperation(
-                        info.account, info.userId, syncAdapterInfo.uid,
-                        syncAdapterInfo.componentName.getPackageName(), op.reason,
-                        op.syncSource, info.provider, op.extras,
-                        op.expedited ? -1 : 0 /* delay */,
-                        0 /* flex */,
-                        backoff != null ? backoff.first : 0L,
-                        mSyncStorageEngine.getDelayUntilTime(info),
-                        syncAdapterInfo.type.allowParallelSyncs());
-                operationToAdd.pendingOperation = op;
-                add(operationToAdd, op);
-            } else if (info.target_service) {
-                android.content.pm.ServiceInfo sinfo;
-                try {
-                    sinfo = mPackageManager.getServiceInfo(info.service, info.userId);
-                } catch (PackageManager.NameNotFoundException e) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.w(TAG, "Missing sync service for authority " + op.target);
-                    }
-                    continue;
-                }
-                if (sinfo == null) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.w(TAG, "Missing sync service for authority " + op.target);
-                    }
-                    continue;
-                }
-                operationToAdd = new SyncOperation(
-                        info.service, info.userId, sinfo.applicationInfo.uid,
-                        info.service.getPackageName(), op.reason, op.syncSource,
-                        op.extras,
-                        op.expedited ? -1 : 0 /* delay */,
-                        0 /* flex */,
-                        backoff != null ? backoff.first : 0,
-                        mSyncStorageEngine.getDelayUntilTime(info));
-                operationToAdd.pendingOperation = op;
-                add(operationToAdd, op);
-            }
-        }
-    }
-
-    public boolean add(SyncOperation operation) {
-        return add(operation, null /* this is not coming from the database */);
-    }
-
-    /**
-     * Adds a SyncOperation to the queue and creates a PendingOperation object to track that sync.
-     * If an operation is added that already exists, the existing operation is updated if the newly
-     * added operation occurs before (or the interval overlaps).
-     */
-    private boolean add(SyncOperation operation,
-            SyncStorageEngine.PendingOperation pop) {
-        // If an operation with the same key exists and this one should run sooner/overlaps,
-        // replace the run interval of the existing operation with this new one.
-        // Complications: what if the existing operation is expedited but the new operation has an
-        // earlier run time? Will not be a problem for periodic syncs (no expedited flag), and for
-        // one-off syncs we only change it if the new sync is sooner.
-        final String operationKey = operation.key;
-        final SyncOperation existingOperation = mOperationsMap.get(operationKey);
-
-        if (existingOperation != null) {
-            boolean changed = false;
-            if (operation.compareTo(existingOperation) <= 0 ) {
-                long newRunTime =
-                        Math.min(existingOperation.latestRunTime, operation.latestRunTime);
-                // Take smaller runtime.
-                existingOperation.latestRunTime = newRunTime;
-                // Take newer flextime.
-                existingOperation.flexTime = operation.flexTime;
-                changed = true;
-            }
-            return changed;
-        }
-
-        operation.pendingOperation = pop;
-        // Don't update the PendingOp if one already exists. This really is just a placeholder,
-        // no actual scheduling info is placed here.
-        if (operation.pendingOperation == null) {
-            pop = mSyncStorageEngine.insertIntoPending(operation);
-            if (pop == null) {
-                throw new IllegalStateException("error adding pending sync operation "
-                        + operation);
-            }
-            operation.pendingOperation = pop;
-        }
-
-        mOperationsMap.put(operationKey, operation);
-        return true;
-    }
-
-    public void removeUserLocked(int userId) {
-        ArrayList<SyncOperation> opsToRemove = new ArrayList<SyncOperation>();
-        for (SyncOperation op : mOperationsMap.values()) {
-            if (op.target.userId == userId) {
-                opsToRemove.add(op);
-            }
-        }
-        for (SyncOperation op : opsToRemove) {
-            remove(op);
-        }
-    }
-
-    public boolean removeUidIfNeededLocked(int uid) {
-        ArrayList<SyncOperation> opsToRemove = null;
-        for (SyncOperation op : mOperationsMap.values()) {
-            if (op.owningUid != uid) {
-                continue;
-            }
-            try {
-                if (ActivityManagerNative.getDefault().getAppStartMode(op.owningUid,
-                        op.owningPackage) == ActivityManager.APP_START_MODE_DISABLED) {
-                    Slog.w(TAG, "Removing sync " + op.owningUid + ":" + op
-                            + " -- package not allowed to start");
-                    continue;
-                }
-            } catch (RemoteException e) {
-            }
-            if (opsToRemove == null) {
-                opsToRemove = new ArrayList<SyncOperation>();
-            }
-            opsToRemove.add(op);
-        }
-        if (opsToRemove == null) {
-            return false;
-        }
-        for (SyncOperation op : opsToRemove) {
-            remove(op);
-        }
-        return true;
-    }
-
-    /**
-     * Remove the specified operation if it is in the queue.
-     * @param operation the operation to remove
-     */
-    public void remove(SyncOperation operation) {
-        boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
-        SyncOperation operationToRemove = mOperationsMap.remove(operation.key);
-        if (isLoggable) {
-            Log.v(TAG, "Attempting to remove: " + operation.key);
-        }
-        if (operationToRemove == null) {
-            if (isLoggable) {
-                Log.v(TAG, "Could not find: " + operation.key);
-            }
-            return;
-        }
-        if (!mSyncStorageEngine.deleteFromPending(operationToRemove.pendingOperation)) {
-            final String errorMessage = "unable to find pending row for " + operationToRemove;
-            Log.e(TAG, errorMessage, new IllegalStateException(errorMessage));
-        }
-    }
-
-    /** Reset backoffs for all operations in the queue. */
-    public void clearBackoffs() {
-        for (SyncOperation op : mOperationsMap.values()) {
-            op.backoff = 0L;
-            op.updateEffectiveRunTime();
-        }
-    }
-
-    public void onBackoffChanged(SyncStorageEngine.EndPoint target, long backoff) {
-        // For each op that matches the target of the changed op, update its
-        // backoff and effectiveStartTime
-        for (SyncOperation op : mOperationsMap.values()) {
-            if (op.target.matchesSpec(target)) {
-                op.backoff = backoff;
-                op.updateEffectiveRunTime();
-            }
-        }
-    }
-
-    public void onDelayUntilTimeChanged(SyncStorageEngine.EndPoint target, long delayUntil) {
-        // for each op that matches the target info of the provided op, change the delay time.
-        for (SyncOperation op : mOperationsMap.values()) {
-            if (op.target.matchesSpec(target)) {
-                op.delayUntil = delayUntil;
-                op.updateEffectiveRunTime();
-            }
-        }
-    }
-
-    /**
-     * Remove all of the SyncOperations associated with a given target.
-     *
-     * @param info target object provided here can have null Account/provider. This is the case
-     * where you want to remove all ops associated with a provider (null Account) or all ops
-     * associated with an account (null provider).
-     * @param extras option bundle to include to further specify which operation to remove. If this
-     * bundle contains sync settings flags, they are ignored.
-     */
-    public void remove(final SyncStorageEngine.EndPoint info, Bundle extras) {
-        Iterator<Map.Entry<String, SyncOperation>> entries = mOperationsMap.entrySet().iterator();
-        while (entries.hasNext()) {
-            Map.Entry<String, SyncOperation> entry = entries.next();
-            SyncOperation syncOperation = entry.getValue();
-            final SyncStorageEngine.EndPoint opInfo = syncOperation.target;
-            if (!opInfo.matchesSpec(info)) {
-                continue;
-            }
-            if (extras != null
-                    && !SyncManager.syncExtrasEquals(
-                        syncOperation.extras,
-                        extras,
-                        false /* no config flags*/)) {
-                continue;
-            }
-            entries.remove();
-            if (!mSyncStorageEngine.deleteFromPending(syncOperation.pendingOperation)) {
-                final String errorMessage = "unable to find pending row for " + syncOperation;
-                Log.e(TAG, errorMessage, new IllegalStateException(errorMessage));
-            }
-        }
-    }
-
-    public Collection<SyncOperation> getOperations() {
-        return mOperationsMap.values();
-    }
-
-    public void dump(StringBuilder sb) {
-        final long now = SystemClock.elapsedRealtime();
-        sb.append("SyncQueue: ").append(mOperationsMap.size()).append(" operation(s)\n");
-        for (SyncOperation operation : mOperationsMap.values()) {
-            sb.append("  ");
-            if (operation.effectiveRunTime <= now) {
-                sb.append("READY");
-            } else {
-                sb.append(DateUtils.formatElapsedTime((operation.effectiveRunTime - now) / 1000));
-            }
-            sb.append(" - ");
-            sb.append(operation.dump(mPackageManager, false)).append("\n");
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index c13518b..f8e3e48 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -27,7 +27,6 @@
 import android.content.SyncInfo;
 import android.content.SyncRequest;
 import android.content.SyncStatusInfo;
-import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
@@ -40,13 +39,7 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.util.AtomicFile;
-import android.util.Log;
-import android.util.Pair;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.ArrayMap;
-import android.util.Xml;
+import android.util.*;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
@@ -59,7 +52,6 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
-import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -90,7 +82,7 @@
     /** Default time for a periodic sync. */
     private static final long DEFAULT_POLL_FREQUENCY_SECONDS = 60 * 60 * 24; // One day
 
-    /** Percentage of period that is flex by default, if no flex is set. */
+    /** Percentage of period that is flex by default, if no flexMillis is set. */
     private static final double DEFAULT_FLEX_PERCENT_SYNC = 0.04;
 
     /** Lower bound on sync time from which we assign a default flex time. */
@@ -105,10 +97,6 @@
     /** Enum value for a sync stop event. */
     public static final int EVENT_STOP = 1;
 
-    // TODO: i18n -- grab these out of resources.
-    /** String names for the sync event types. */
-    public static final String[] EVENTS = { "START", "STOP" };
-
     /** Enum value for a server-initiated sync. */
     public static final int SOURCE_SERVER = 0;
 
@@ -122,20 +110,17 @@
 
     /** Enum value for a periodic sync. */
     public static final int SOURCE_PERIODIC = 4;
-    
-    /** Enum value for a sync started for a service. */
-    public static final int SOURCE_SERVICE = 5;
 
     public static final long NOT_IN_BACKOFF_MODE = -1;
 
     // TODO: i18n -- grab these out of resources.
     /** String names for the sync source types. */
     public static final String[] SOURCES = { "SERVER",
-                                             "LOCAL",
-                                             "POLL",
-                                             "USER",
-                                             "PERIODIC",
-                                             "SERVICE"};
+            "LOCAL",
+            "POLL",
+            "USER",
+            "PERIODIC",
+            "SERVICE"};
 
     // The MESG column will contain one of these or one of the Error types.
     public static final String MESG_SUCCESS = "success";
@@ -155,6 +140,7 @@
     private static final int ACCOUNTS_VERSION = 2;
 
     private static HashMap<String, String> sAuthorityRenames;
+    private static PeriodicSyncAddedListener mPeriodicSyncAddedListener;
 
     static {
         sAuthorityRenames = new HashMap<String, String>();
@@ -162,58 +148,6 @@
         sAuthorityRenames.put("calendar", "com.android.calendar");
     }
 
-    public static class PendingOperation {
-        final EndPoint target;
-        final int reason;
-        final int syncSource;
-        final Bundle extras;        // note: read-only.
-        final boolean expedited;
-
-        final int authorityId;
-        // No longer used.
-        // Keep around for sake up updating from pending.bin to pending.xml
-        byte[] flatExtras;
-
-        PendingOperation(AuthorityInfo authority, int reason, int source,
-                 Bundle extras, boolean expedited) {
-            this.target = authority.target;
-            this.syncSource = source;
-            this.reason = reason;
-            this.extras = extras != null ? new Bundle(extras) : extras;
-            this.expedited = expedited;
-            this.authorityId = authority.ident;
-        }
-
-        PendingOperation(PendingOperation other) {
-            this.reason = other.reason;
-            this.syncSource = other.syncSource;
-            this.target = other.target;
-            this.extras = other.extras;
-            this.authorityId = other.authorityId;
-            this.expedited = other.expedited;
-        }
-
-        /**
-         * Considered equal if they target the same sync adapter (A
-         * {@link android.content.SyncService}
-         * is considered an adapter), for the same userId.
-         * @param other PendingOperation to compare.
-         * @return true if the two pending ops are the same.
-         */
-        public boolean equals(PendingOperation other) {
-            return target.matchesSpec(other.target);
-        }
-
-        public String toString() {
-            return "service=" + target.service
-                        + " user=" + target.userId
-                        + " auth=" + target
-                        + " account=" + target.account
-                        + " src=" + syncSource
-                        + " extras=" + extras;
-        }
-    }
-
     static class AccountInfo {
         final AccountAndUser accountAndUser;
         final HashMap<String, AuthorityInfo> authorities =
@@ -228,39 +162,21 @@
     public static class EndPoint {
         public final static EndPoint USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL =
                 new EndPoint(null, null, UserHandle.USER_ALL);
-        final ComponentName service;
-        final int serviceUid;           // -1 for "any"
         final Account account;
         final int userId;
         final String provider;
-        final boolean target_service;
-        final boolean target_provider;
-
-        public EndPoint(ComponentName service, int userId, int uid) {
-            this.service = service;
-            this.serviceUid = uid;
-            this.userId = userId;
-            this.account = null;
-            this.provider = null;
-            this.target_service = true;
-            this.target_provider = false;
-        }
 
         public EndPoint(Account account, String provider, int userId) {
             this.account = account;
             this.provider = provider;
             this.userId = userId;
-            this.service = null;
-            this.serviceUid = -1;
-            this.target_service = false;
-            this.target_provider = true;
         }
 
         /**
          * An Endpoint for a sync matches if it targets the same sync adapter for the same user.
          *
          * @param spec the Endpoint to match. If the spec has null fields, they indicate a wildcard
-         * and match any. 
+         * and match any.
          */
         public boolean matchesSpec(EndPoint spec) {
             if (userId != spec.userId
@@ -268,44 +184,26 @@
                     && spec.userId != UserHandle.USER_ALL) {
                 return false;
             }
-            if (target_service && spec.target_service) {
-                if (serviceUid != spec.serviceUid
-                    && serviceUid >= 0
-                    && spec.serviceUid >= 0) {
-                    return false;
-                }
-                return service.equals(spec.service);
-            } else if (target_provider && spec.target_provider) {
-                boolean accountsMatch;
-                if (spec.account == null) {
-                    accountsMatch = true;
-                } else {
-                    accountsMatch = account.equals(spec.account);
-                }
-                boolean providersMatch;
-                if (spec.provider == null) {
-                    providersMatch = true;
-                } else {
-                    providersMatch = provider.equals(spec.provider);
-                }
-                return accountsMatch && providersMatch;
+            boolean accountsMatch;
+            if (spec.account == null) {
+                accountsMatch = true;
+            } else {
+                accountsMatch = account.equals(spec.account);
             }
-            return false;
+            boolean providersMatch;
+            if (spec.provider == null) {
+                providersMatch = true;
+            } else {
+                providersMatch = provider.equals(spec.provider);
+            }
+            return accountsMatch && providersMatch;
         }
 
         public String toString() {
             StringBuilder sb = new StringBuilder();
-            if (target_provider) {
-                sb.append(account == null ? "ALL ACCS" : account.name)
+            sb.append(account == null ? "ALL ACCS" : account.name)
                     .append("/")
                     .append(provider == null ? "ALL PDRS" : provider);
-            } else if (target_service) {
-                service.appendShortString(sb);
-                sb.append(":");
-                UserHandle.formatUid(sb,serviceUid);
-            } else {
-                sb.append("invalid target");
-            }
             sb.append(":u" + userId);
             return sb.toString();
         }
@@ -373,12 +271,7 @@
         AuthorityInfo(EndPoint info, int id) {
             target = info;
             ident = id;
-            enabled = info.target_provider ?
-                    SYNC_ENABLED_DEFAULT : true;
-            // Service is active by default,
-            if (info.target_service) {
-                this.syncable = 1;
-            }
+            enabled = SYNC_ENABLED_DEFAULT;
             periodicSyncs = new ArrayList<PeriodicSync>();
             defaultInitialisation();
         }
@@ -387,15 +280,11 @@
             syncable = NOT_INITIALIZED; // default to "unknown"
             backoffTime = -1; // if < 0 then we aren't in backoff mode
             backoffDelay = -1; // if < 0 then we aren't in backoff mode
-            PeriodicSync defaultSync;
-            // Old version is one sync a day.
-            if (target.target_provider) {
-                defaultSync =
-                        new PeriodicSync(target.account, target.provider,
-                            new Bundle(),
-                            DEFAULT_POLL_FREQUENCY_SECONDS,
-                            calculateDefaultFlexTime(DEFAULT_POLL_FREQUENCY_SECONDS));
-                periodicSyncs.add(defaultSync);
+
+            if (mPeriodicSyncAddedListener != null) {
+                mPeriodicSyncAddedListener.onPeriodicSyncAdded(target, new Bundle(),
+                        DEFAULT_POLL_FREQUENCY_SECONDS,
+                        calculateDefaultFlexTime(DEFAULT_POLL_FREQUENCY_SECONDS));
             }
         }
 
@@ -439,6 +328,16 @@
         public void onSyncRequest(EndPoint info, int reason, Bundle extras);
     }
 
+    interface PeriodicSyncAddedListener {
+        /** Called when a periodic sync is added. */
+        void onPeriodicSyncAdded(EndPoint target, Bundle extras, long pollFrequency, long flex);
+    }
+
+    interface OnAuthorityRemovedListener {
+        /** Called when an authority is removed. */
+        void onAuthorityRemoved(EndPoint removedAuthority);
+    }
+
     // Primary list of all syncable authorities.  Also our global lock.
     private final SparseArray<AuthorityInfo> mAuthorities =
             new SparseArray<AuthorityInfo>();
@@ -446,9 +345,6 @@
     private final HashMap<AccountAndUser, AccountInfo> mAccounts
             = new HashMap<AccountAndUser, AccountInfo>();
 
-    private final ArrayList<PendingOperation> mPendingOperations =
-            new ArrayList<PendingOperation>();
-
     private final SparseArray<ArrayList<SyncInfo>> mCurrentSyncs
             = new SparseArray<ArrayList<SyncInfo>>();
 
@@ -499,20 +395,12 @@
      */
     private final AtomicFile mStatisticsFile;
 
-    /**
-     * This file contains the pending sync operations.  It is a binary file,
-     * which must be updated every time an operation is added or removed,
-     * so we have special handling of it.
-     */
-    private final AtomicFile mPendingFile;
-    private static final int PENDING_FINISH_TO_WRITE = 4;
-    private int mNumPendingFinished = 0;
-
     private int mNextHistoryId = 0;
     private SparseArray<Boolean> mMasterSyncAutomatically = new SparseArray<Boolean>();
     private boolean mDefaultMasterSyncAutomatically;
 
     private OnSyncRequestListener mSyncRequestListener;
+    private OnAuthorityRemovedListener mAuthorityRemovedListener;
 
     private SyncStorageEngine(Context context, File dataDir) {
         mContext = context;
@@ -521,7 +409,7 @@
         mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
 
         mDefaultMasterSyncAutomatically = mContext.getResources().getBoolean(
-               com.android.internal.R.bool.config_syncstorageengine_masterSyncAutomatically);
+                com.android.internal.R.bool.config_syncstorageengine_masterSyncAutomatically);
 
         File systemDir = new File(dataDir, "system");
         File syncDir = new File(systemDir, "sync");
@@ -531,17 +419,14 @@
 
         mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
         mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
-        mPendingFile = new AtomicFile(new File(syncDir, "pending.xml"));
         mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
 
         readAccountInfoLocked();
         readStatusLocked();
-        readPendingOperationsLocked();
         readStatisticsLocked();
         readAndDeleteLegacyAccountInfoLocked();
         writeAccountInfoLocked();
         writeStatusLocked();
-        writePendingOperationsLocked();
         writeStatisticsLocked();
     }
 
@@ -572,6 +457,18 @@
         }
     }
 
+    protected void setOnAuthorityRemovedListener(OnAuthorityRemovedListener listener) {
+        if (mAuthorityRemovedListener == null) {
+            mAuthorityRemovedListener = listener;
+        }
+    }
+
+    protected void setPeriodicSyncAddedListener(PeriodicSyncAddedListener listener) {
+        if (mPeriodicSyncAddedListener == null) {
+            mPeriodicSyncAddedListener = listener;
+        }
+    }
+
     @Override public void handleMessage(Message msg) {
         if (msg.what == MSG_WRITE_STATUS) {
             synchronized (mAuthorities) {
@@ -622,7 +519,7 @@
         }
     }
 
-    private void reportChange(int which) {
+    void reportChange(int which) {
         ArrayList<ISyncStatusObserver> reports = null;
         synchronized (mAuthorities) {
             int i = mChangeListeners.beginBroadcast();
@@ -641,7 +538,7 @@
         }
 
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "reportChange " + which + " to: " + reports);
+            Slog.v(TAG, "reportChange " + which + " to: " + reports);
         }
 
         if (reports != null) {
@@ -680,9 +577,9 @@
     }
 
     public void setSyncAutomatically(Account account, int userId, String providerName,
-            boolean sync) {
+                                     boolean sync) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.d(TAG, "setSyncAutomatically: " + /* account + */" provider " + providerName
+            Slog.d(TAG, "setSyncAutomatically: " + /* account + */" provider " + providerName
                     + ", user " + userId + " -> " + sync);
         }
         synchronized (mAuthorities) {
@@ -693,7 +590,7 @@
                             false);
             if (authority.enabled == sync) {
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.d(TAG, "setSyncAutomatically: already set to " + sync + ", doing nothing");
+                    Slog.d(TAG, "setSyncAutomatically: already set to " + sync + ", doing nothing");
                 }
                 return;
             }
@@ -744,26 +641,6 @@
         setSyncableStateForEndPoint(new EndPoint(account, providerName, userId), syncable);
     }
 
-    public boolean getIsTargetServiceActive(ComponentName cname, int userId) {
-        synchronized (mAuthorities) {
-            if (cname != null) {
-                AuthorityInfo authority = getAuthorityLocked(
-                        new EndPoint(cname, userId, -1),
-                        "get service active");
-                if (authority == null) {
-                    return false;
-                }
-                return (authority.syncable == 1);
-            }
-            return false;
-        }
-    }
-
-    public void setIsTargetServiceActive(ComponentName cname, int userId, boolean active) {
-        setSyncableStateForEndPoint(new EndPoint(cname, userId, -1), active ?
-                AuthorityInfo.SYNCABLE : AuthorityInfo.NOT_SYNCABLE);
-    }
-
     /**
      * An enabled sync service and a syncable provider's adapter both get resolved to the same
      * persisted variable - namely the "syncable" attribute for an AuthorityInfo in accounts.xml.
@@ -778,11 +655,11 @@
                 syncable = AuthorityInfo.NOT_INITIALIZED;
             }
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.d(TAG, "setIsSyncable: " + aInfo.toString() + " -> " + syncable);
+                Slog.d(TAG, "setIsSyncable: " + aInfo.toString() + " -> " + syncable);
             }
             if (aInfo.syncable == syncable) {
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.d(TAG, "setIsSyncable: already set to " + syncable + ", doing nothing");
+                    Slog.d(TAG, "setIsSyncable: already set to " + syncable + ", doing nothing");
                 }
                 return;
             }
@@ -811,15 +688,14 @@
      */
     public void setBackoff(EndPoint info, long nextSyncTime, long nextDelay) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "setBackoff: " + info
+            Slog.v(TAG, "setBackoff: " + info
                     + " -> nextSyncTime " + nextSyncTime + ", nextDelay " + nextDelay);
         }
         boolean changed;
         synchronized (mAuthorities) {
-            if (info.target_provider
-                    && (info.account == null || info.provider == null)) {
+            if (info.account == null || info.provider == null) {
                 // Do more work for a provider sync if the provided info has specified all
-                // accounts/providers. 
+                // accounts/providers.
                 changed = setBackoffLocked(
                         info.account /* may be null */,
                         info.userId,
@@ -853,7 +729,7 @@
      * @return true if a change occured.
      */
     private boolean setBackoffLocked(Account account, int userId, String providerName,
-            long nextSyncTime, long nextDelay) {
+                                     long nextSyncTime, long nextDelay) {
         boolean changed = false;
         for (AccountInfo accountInfo : mAccounts.values()) {
             if (account != null && !account.equals(accountInfo.accountAndUser.account)
@@ -876,40 +752,27 @@
         return changed;
     }
 
-    public void clearAllBackoffsLocked(SyncQueue syncQueue) {
+    public void clearAllBackoffsLocked() {
         boolean changed = false;
         synchronized (mAuthorities) {
-                // Clear backoff for all sync adapters.
-                for (AccountInfo accountInfo : mAccounts.values()) {
-                    for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
-                        if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
-                                || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
-                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                                Log.v(TAG, "clearAllBackoffsLocked:"
-                                        + " authority:" + authorityInfo.target
-                                        + " account:" + accountInfo.accountAndUser.account.name
-                                        + " user:" + accountInfo.accountAndUser.userId
-                                        + " backoffTime was: " + authorityInfo.backoffTime
-                                        + " backoffDelay was: " + authorityInfo.backoffDelay);
-                            }
-                            authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
-                            authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
-                            changed = true;
+            // Clear backoff for all sync adapters.
+            for (AccountInfo accountInfo : mAccounts.values()) {
+                for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
+                    if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
+                            || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Slog.v(TAG, "clearAllBackoffsLocked:"
+                                    + " authority:" + authorityInfo.target
+                                    + " account:" + accountInfo.accountAndUser.account.name
+                                    + " user:" + accountInfo.accountAndUser.userId
+                                    + " backoffTime was: " + authorityInfo.backoffTime
+                                    + " backoffDelay was: " + authorityInfo.backoffDelay);
                         }
+                        authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
+                        authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
+                        changed = true;
                     }
                 }
-                // Clear backoff for all sync services.
-                for (ComponentName service : mServices.keySet()) {
-                    SparseArray<AuthorityInfo> aInfos = mServices.get(service);
-                    for (int i = 0; i < aInfos.size(); i++) {
-                        AuthorityInfo authorityInfo = aInfos.valueAt(i);
-                        if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
-                                || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
-                            authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
-                            authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
-                        }
-                    }
-                syncQueue.clearBackoffs();
             }
         }
 
@@ -930,7 +793,7 @@
 
     public void setDelayUntilTime(EndPoint info, long delayUntil) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "setDelayUntil: " + info
+            Slog.v(TAG, "setDelayUntil: " + info
                     + " -> delayUntil " + delayUntil);
         }
         synchronized (mAuthorities) {
@@ -943,123 +806,26 @@
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
     }
 
-    public void updateOrAddPeriodicSync(EndPoint info, long period, long flextime, Bundle extras) {
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "addPeriodicSync: " + info
-                    + " -> period " + period + ", flex " + flextime + ", extras "
-                    + extras.toString());
-        }
-        synchronized (mAuthorities) {
-            if (period <= 0) {
-                Log.e(TAG, "period < 0, should never happen in updateOrAddPeriodicSync");
-            }
-            if (extras == null) {
-                Log.e(TAG, "null extras, should never happen in updateOrAddPeriodicSync:");
-            }
-            try {
-                PeriodicSync toUpdate;
-                if (info.target_provider) {
-                    toUpdate = new PeriodicSync(info.account,
-                            info.provider,
-                            extras,
-                            period,
-                            flextime);
-                } else {
-                    return;
-                }
-                AuthorityInfo authority =
-                        getOrCreateAuthorityLocked(info, -1, false);
-                // add this periodic sync if an equivalent periodic doesn't already exist.
-                boolean alreadyPresent = false;
-                for (int i = 0, N = authority.periodicSyncs.size(); i < N; i++) {
-                    PeriodicSync syncInfo = authority.periodicSyncs.get(i);
-                    if (SyncManager.syncExtrasEquals(syncInfo.extras,
-                            extras,
-                            true /* includeSyncSettings*/)) {
-                        if (period == syncInfo.period &&
-                                flextime == syncInfo.flexTime) {
-                            // Absolutely the same.
-                            return;
-                        }
-                        authority.periodicSyncs.set(i, toUpdate);
-                        alreadyPresent = true;
-                        break;
-                    }
-                }
-                // If we added an entry to the periodicSyncs array also add an entry to
-                // the periodic syncs status to correspond to it.
-                if (!alreadyPresent) {
-                    authority.periodicSyncs.add(toUpdate);
-                    SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
-                    // A new periodic sync is initialised as already having been run.
-                    status.setPeriodicSyncTime(
-                            authority.periodicSyncs.size() - 1,
-                            System.currentTimeMillis());
-                }
-            } finally {
-                writeAccountInfoLocked();
-                writeStatusLocked();
-            }
-        }
-        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
-    }
-
-    public void removePeriodicSync(EndPoint info, Bundle extras) {
-        synchronized(mAuthorities) {
-            try {
-                AuthorityInfo authority =
-                        getOrCreateAuthorityLocked(info, -1, false);
-                // Remove any periodic syncs that match the target and extras.
-                SyncStatusInfo status = mSyncStatus.get(authority.ident);
-                boolean changed = false;
-                Iterator<PeriodicSync> iterator = authority.periodicSyncs.iterator();
-                int i = 0;
-                while (iterator.hasNext()) {
-                    PeriodicSync syncInfo = iterator.next();
-                    if (SyncManager.syncExtrasEquals(syncInfo.extras,
-                            extras,
-                            true /* includeSyncSettings */)) {
-                        iterator.remove();
-                        changed = true;
-                        // If we removed an entry from the periodicSyncs array also
-                        // remove the corresponding entry from the status
-                        if (status != null) {
-                            status.removePeriodicSyncTime(i);
-                        } else {
-                            Log.e(TAG, "Tried removing sync status on remove periodic sync but"
-                                    + " did not find it.");
-                        }
-                    } else {
-                        i++;
-                    }
-                }
-                if (!changed) {
-                    return;
-                }
-            } finally {
-                writeAccountInfoLocked();
-                writeStatusLocked();
-            }
-        }
-        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
-    }
-
     /**
-     * @return list of periodic syncs for a target. Never null. If no such syncs exist, returns an
-     * empty list.
+     * Restore all periodic syncs read from persisted files. Used to restore periodic syncs
+     * after an OS update.
      */
-    public List<PeriodicSync> getPeriodicSyncs(EndPoint info) {
-        synchronized (mAuthorities) {
-            AuthorityInfo authorityInfo = getAuthorityLocked(info, "getPeriodicSyncs");
-            ArrayList<PeriodicSync> syncs = new ArrayList<PeriodicSync>();
-            if (authorityInfo != null) {
-                for (PeriodicSync item : authorityInfo.periodicSyncs) {
-                    // Copy and send out. Necessary for thread-safety although it's parceled.
-                    syncs.add(new PeriodicSync(item));
-                }
-            }
-            return syncs;
+    boolean restoreAllPeriodicSyncs() {
+        if (mPeriodicSyncAddedListener == null) {
+            return false;
         }
+        synchronized (mAuthorities) {
+            for (int i=0; i<mAuthorities.size(); i++) {
+                AuthorityInfo authority = mAuthorities.valueAt(i);
+                for (PeriodicSync periodicSync: authority.periodicSyncs) {
+                    mPeriodicSyncAddedListener.onPeriodicSyncAdded(authority.target,
+                            periodicSync.extras, periodicSync.period, periodicSync.flexTime);
+                }
+                authority.periodicSyncs.clear();
+            }
+            writeAccountInfoLocked();
+        }
+        return true;
     }
 
     public void setMasterSyncAutomatically(boolean flag, int userId) {
@@ -1109,101 +875,18 @@
         return false;
     }
 
-    public PendingOperation insertIntoPending(SyncOperation op) {
-        PendingOperation pop;
+    public void markPending(EndPoint info, boolean pendingValue) {
         synchronized (mAuthorities) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "insertIntoPending: authority=" + op.target
-                        + " extras=" + op.extras);
-            }
-            final EndPoint info = op.target;
-            AuthorityInfo authority =
-                    getOrCreateAuthorityLocked(info,
-                            -1 /* desired identifier */,
-                            true /* write accounts to storage */);
+            AuthorityInfo authority = getOrCreateAuthorityLocked(info,
+                    -1 /* desired identifier */,
+                    true /* write accounts to storage */);
             if (authority == null) {
-                return null;
+                return;
             }
-
-            pop = new PendingOperation(authority, op.reason, op.syncSource, op.extras,
-                    op.isExpedited());
-            mPendingOperations.add(pop);
-            appendPendingOperationLocked(pop);
-
             SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
-            status.pending = true;
+            status.pending = pendingValue;
         }
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
-        return pop;
-    }
-
-    /**
-     * Remove from list of pending operations. If successful, search through list for matching
-     * authorities. If there are no more pending syncs for the same target,
-     * update the SyncStatusInfo for that target.
-     * @param op Pending op to delete.
-     */
-    public boolean deleteFromPending(PendingOperation op) {
-        boolean res = false;
-        synchronized (mAuthorities) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "deleteFromPending: account=" + op.toString());
-            }
-            if (mPendingOperations.remove(op)) {
-                if (mPendingOperations.size() == 0
-                        || mNumPendingFinished >= PENDING_FINISH_TO_WRITE) {
-                    writePendingOperationsLocked();
-                    mNumPendingFinished = 0;
-                } else {
-                    mNumPendingFinished++;
-                }
-                AuthorityInfo authority = getAuthorityLocked(op.target, "deleteFromPending");
-                if (authority != null) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "removing - " + authority.toString());
-                    }
-                    final int N = mPendingOperations.size();
-                    boolean morePending = false;
-                    for (int i = 0; i < N; i++) {
-                        PendingOperation cur = mPendingOperations.get(i);
-                        if (cur.equals(op)) {
-                            morePending = true;
-                            break;
-                        }
-                    }
-
-                    if (!morePending) {
-                        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "no more pending!");
-                        SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
-                        status.pending = false;
-                    }
-                }
-                res = true;
-            }
-        }
-
-        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
-        return res;
-    }
-
-    /**
-     * Return a copy of the current array of pending operations.  The
-     * PendingOperation objects are the real objects stored inside, so that
-     * they can be used with deleteFromPending().
-     */
-    public ArrayList<PendingOperation> getPendingOperations() {
-        synchronized (mAuthorities) {
-            return new ArrayList<PendingOperation>(mPendingOperations);
-        }
-    }
-
-    /**
-     * Return the number of currently pending operations.
-     */
-    public int getPendingOperationCount() {
-        synchronized (mAuthorities) {
-            return mPendingOperations.size();
-        }
     }
 
     /**
@@ -1213,7 +896,7 @@
     public void doDatabaseCleanup(Account[] accounts, int userId) {
         synchronized (mAuthorities) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "Updating for new accounts...");
+                Slog.v(TAG, "Updating for new accounts...");
             }
             SparseArray<AuthorityInfo> removing = new SparseArray<AuthorityInfo>();
             Iterator<AccountInfo> accIt = mAccounts.values().iterator();
@@ -1223,7 +906,7 @@
                         && acc.accountAndUser.userId == userId) {
                     // This account no longer exists...
                     if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "Account removed: " + acc.accountAndUser);
+                        Slog.v(TAG, "Account removed: " + acc.accountAndUser);
                     }
                     for (AuthorityInfo auth : acc.authorities.values()) {
                         removing.put(auth.ident, auth);
@@ -1238,6 +921,10 @@
                 while (i > 0) {
                     i--;
                     int ident = removing.keyAt(i);
+                    AuthorityInfo auth = removing.valueAt(i);
+                    if (mAuthorityRemovedListener != null) {
+                        mAuthorityRemovedListener.onAuthorityRemoved(auth.target);
+                    }
                     mAuthorities.remove(ident);
                     int j = mSyncStatus.size();
                     while (j > 0) {
@@ -1256,7 +943,6 @@
                 }
                 writeAccountInfoLocked();
                 writeStatusLocked();
-                writePendingOperationsLocked();
                 writeStatisticsLocked();
             }
         }
@@ -1270,10 +956,10 @@
         final SyncInfo syncInfo;
         synchronized (mAuthorities) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "setActiveSync: account="
-                    + " auth=" + activeSyncContext.mSyncOperation.target
-                    + " src=" + activeSyncContext.mSyncOperation.syncSource
-                    + " extras=" + activeSyncContext.mSyncOperation.extras);
+                Slog.v(TAG, "setActiveSync: account="
+                        + " auth=" + activeSyncContext.mSyncOperation.target
+                        + " src=" + activeSyncContext.mSyncOperation.syncSource
+                        + " extras=" + activeSyncContext.mSyncOperation.extras);
             }
             final EndPoint info = activeSyncContext.mSyncOperation.target;
             AuthorityInfo authorityInfo = getOrCreateAuthorityLocked(
@@ -1297,7 +983,7 @@
     public void removeActiveSync(SyncInfo syncInfo, int userId) {
         synchronized (mAuthorities) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "removeActiveSync: account=" + syncInfo.account
+                Slog.v(TAG, "removeActiveSync: account=" + syncInfo.account
                         + " user=" + userId
                         + " auth=" + syncInfo.authority);
             }
@@ -1321,7 +1007,7 @@
         long id;
         synchronized (mAuthorities) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "insertStartSyncEvent: " + op);
+                Slog.v(TAG, "insertStartSyncEvent: " + op);
             }
             AuthorityInfo authority = getAuthorityLocked(op.target, "insertStartSyncEvent");
             if (authority == null) {
@@ -1342,7 +1028,7 @@
                 mSyncHistory.remove(mSyncHistory.size()-1);
             }
             id = item.historyId;
-            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "returning historyId " + id);
+            if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "returning historyId " + id);
         }
 
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
@@ -1350,10 +1036,10 @@
     }
 
     public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
-            long downstreamActivity, long upstreamActivity) {
+                              long downstreamActivity, long upstreamActivity) {
         synchronized (mAuthorities) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "stopSyncEvent: historyId=" + historyId);
+                Slog.v(TAG, "stopSyncEvent: historyId=" + historyId);
             }
             SyncHistoryItem item = null;
             int i = mSyncHistory.size();
@@ -1367,7 +1053,7 @@
             }
 
             if (item == null) {
-                Log.w(TAG, "stopSyncEvent: no history for id " + historyId);
+                Slog.w(TAG, "stopSyncEvent: no history for id " + historyId);
                 return;
             }
 
@@ -1501,22 +1187,6 @@
     }
 
     /**
-     * Return an array of the current sync status for all authorities.  Note
-     * that the objects inside the array are the real, live status objects,
-     * so be careful what you do with them.
-     */
-    public ArrayList<SyncStatusInfo> getSyncStatus() {
-        synchronized (mAuthorities) {
-            final int N = mSyncStatus.size();
-            ArrayList<SyncStatusInfo> ops = new ArrayList<SyncStatusInfo>(N);
-            for (int i=0; i<N; i++) {
-                ops.add(mSyncStatus.valueAt(i));
-            }
-            return ops;
-        }
-    }
-
-    /**
      * Return a copy of the specified target with the corresponding sync status
      */
     public Pair<AuthorityInfo, SyncStatusInfo> getCopyOfAuthorityWithSyncStatus(EndPoint info) {
@@ -1529,29 +1199,13 @@
     }
 
     /**
-     * Return a copy of all authorities with their corresponding sync status
-     */
-    public ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> getCopyOfAllAuthoritiesWithSyncStatus() {
-        synchronized (mAuthorities) {
-            ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> infos =
-                    new ArrayList<Pair<AuthorityInfo, SyncStatusInfo>>(mAuthorities.size());
-            for (int i = 0; i < mAuthorities.size(); i++) {
-                infos.add(createCopyPairOfAuthorityWithSyncStatusLocked(mAuthorities.valueAt(i)));
-            }
-            return infos;
-        }
-    }
-
-    /**
      * Returns the status that matches the target.
      *
      * @param info the endpoint target we are querying status info for.
      * @return the SyncStatusInfo for the endpoint.
      */
     public SyncStatusInfo getStatusByAuthority(EndPoint info) {
-        if (info.target_provider && (info.account == null || info.provider == null)) {
-            return null;
-        } else if (info.target_service && info.service == null) {
+        if (info.account == null || info.provider == null) {
             return null;
         }
         synchronized (mAuthorities) {
@@ -1561,7 +1215,7 @@
                 AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
                 if (ainfo != null
                         && ainfo.target.matchesSpec(info)) {
-                  return cur;
+                    return cur;
                 }
             }
             return null;
@@ -1644,47 +1298,26 @@
      * requested target does not exist.
      */
     private AuthorityInfo getAuthorityLocked(EndPoint info, String tag) {
-        if (info.target_service) {
-            SparseArray<AuthorityInfo> aInfo = mServices.get(info.service);
-            AuthorityInfo authority = null;
-            if (aInfo != null) {
-                authority = aInfo.get(info.userId);
-            }
-            if (authority == null) {
-                if (tag != null) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, tag + " No authority info found for " + info.service + " for"
-                                + " user " + info.userId);
-                    }
+        AccountAndUser au = new AccountAndUser(info.account, info.userId);
+        AccountInfo accountInfo = mAccounts.get(au);
+        if (accountInfo == null) {
+            if (tag != null) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Slog.v(TAG, tag + ": unknown account " + au);
                 }
-                return null;
             }
-            return authority;
-        } else if (info.target_provider){
-            AccountAndUser au = new AccountAndUser(info.account, info.userId);
-            AccountInfo accountInfo = mAccounts.get(au);
-            if (accountInfo == null) {
-                if (tag != null) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, tag + ": unknown account " + au);
-                    }
-                }
-                return null;
-            }
-            AuthorityInfo authority = accountInfo.authorities.get(info.provider);
-            if (authority == null) {
-                if (tag != null) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, tag + ": unknown provider " + info.provider);
-                    }
-                }
-                return null;
-            }
-            return authority;
-        } else {
-            Log.e(TAG, tag + " Authority : " + info + ", invalid target");
             return null;
         }
+        AuthorityInfo authority = accountInfo.authorities.get(info.provider);
+        if (authority == null) {
+            if (tag != null) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Slog.v(TAG, tag + ": unknown provider " + info.provider);
+                }
+            }
+            return null;
+        }
+        return authority;
     }
 
     /**
@@ -1696,29 +1329,16 @@
      */
     private AuthorityInfo getOrCreateAuthorityLocked(EndPoint info, int ident, boolean doWrite) {
         AuthorityInfo authority = null;
-        if (info.target_service) {
-            SparseArray<AuthorityInfo> aInfo = mServices.get(info.service);
-            if (aInfo == null) {
-                aInfo = new SparseArray<AuthorityInfo>();
-                mServices.put(info.service, aInfo);
-            }
-            authority = aInfo.get(info.userId);
-            if (authority == null) {
-                authority = createAuthorityLocked(info, ident, doWrite);
-                aInfo.put(info.userId, authority);
-            }
-        } else if (info.target_provider) {
-            AccountAndUser au = new AccountAndUser(info.account, info.userId);
-            AccountInfo account = mAccounts.get(au);
-            if (account == null) {
-                account = new AccountInfo(au);
-                mAccounts.put(au, account);
-            }
-            authority = account.authorities.get(info.provider);
-            if (authority == null) {
-                authority = createAuthorityLocked(info, ident, doWrite);
-                account.authorities.put(info.provider, authority);
-            }
+        AccountAndUser au = new AccountAndUser(info.account, info.userId);
+        AccountInfo account = mAccounts.get(au);
+        if (account == null) {
+            account = new AccountInfo(au);
+            mAccounts.put(au, account);
+        }
+        authority = account.authorities.get(info.provider);
+        if (authority == null) {
+            authority = createAuthorityLocked(info, ident, doWrite);
+            account.authorities.put(info.provider, authority);
         }
         return authority;
     }
@@ -1731,7 +1351,7 @@
             doWrite = true;
         }
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "created a new AuthorityInfo for " + info);
+            Slog.v(TAG, "created a new AuthorityInfo for " + info);
         }
         authority = new AuthorityInfo(info, ident);
         mAuthorities.put(ident, authority);
@@ -1743,33 +1363,24 @@
 
     public void removeAuthority(EndPoint info) {
         synchronized (mAuthorities) {
-            if (info.target_provider) {
-                removeAuthorityLocked(info.account, info.userId, info.provider, true /* doWrite */);
-            } else {
-                SparseArray<AuthorityInfo> aInfos = mServices.get(info.service);
-                if (aInfos != null) {
-                    AuthorityInfo authorityInfo = aInfos.get(info.userId);
-                    if (authorityInfo != null) {
-                        mAuthorities.remove(authorityInfo.ident);
-                        aInfos.delete(info.userId);
-                        writeAccountInfoLocked();
-                    }
-                }
-
-            }
+            removeAuthorityLocked(info.account, info.userId, info.provider, true /* doWrite */);
         }
     }
 
+
     /**
      * Remove an authority associated with a provider. Needs to be a standalone function for
      * backward compatibility.
      */
     private void removeAuthorityLocked(Account account, int userId, String authorityName,
-            boolean doWrite) {
+                                       boolean doWrite) {
         AccountInfo accountInfo = mAccounts.get(new AccountAndUser(account, userId));
         if (accountInfo != null) {
             final AuthorityInfo authorityInfo = accountInfo.authorities.remove(authorityName);
             if (authorityInfo != null) {
+                if (mAuthorityRemovedListener != null) {
+                    mAuthorityRemovedListener.onAuthorityRemoved(authorityInfo.target);
+                }
                 mAuthorities.remove(authorityInfo.ident);
                 if (doWrite) {
                     writeAccountInfoLocked();
@@ -1778,30 +1389,6 @@
         }
     }
 
-    /**
-     * Updates (in a synchronized way) the periodic sync time of the specified
-     * target id and target periodic sync
-     */
-    public void setPeriodicSyncTime(int authorityId, PeriodicSync targetPeriodicSync, long when) {
-        boolean found = false;
-        final AuthorityInfo authorityInfo;
-        synchronized (mAuthorities) {
-            authorityInfo = mAuthorities.get(authorityId);
-            for (int i = 0; i < authorityInfo.periodicSyncs.size(); i++) {
-                PeriodicSync periodicSync = authorityInfo.periodicSyncs.get(i);
-                if (targetPeriodicSync.equals(periodicSync)) {
-                    mSyncStatus.get(authorityId).setPeriodicSyncTime(i, when);
-                    found = true;
-                    break;
-                }
-            }
-        }
-        if (!found) {
-            Log.w(TAG, "Ignoring setPeriodicSyncTime request for a sync that does not exist. " +
-                    "Authority: " + authorityInfo.target);
-        }
-    }
-
     private SyncStatusInfo getOrCreateSyncStatusLocked(int authorityId) {
         SyncStatusInfo status = mSyncStatus.get(authorityId);
         if (status == null) {
@@ -1814,13 +1401,6 @@
     public void writeAllState() {
         synchronized (mAuthorities) {
             // Account info is always written so no need to do it here.
-
-            if (mNumPendingFinished > 0) {
-                // Only write these if they are out of date.
-                writePendingOperationsLocked();
-            }
-
-            // Just always write these...  they are likely out of date.
             writeStatusLocked();
             writeStatisticsLocked();
         }
@@ -1834,18 +1414,15 @@
             mAuthorities.clear();
             mAccounts.clear();
             mServices.clear();
-            mPendingOperations.clear();
             mSyncStatus.clear();
             mSyncHistory.clear();
 
             readAccountInfoLocked();
             readStatusLocked();
-            readPendingOperationsLocked();
             readStatisticsLocked();
             readAndDeleteLegacyAccountInfoLocked();
             writeAccountInfoLocked();
             writeStatusLocked();
-            writePendingOperationsLocked();
             writeStatisticsLocked();
         }
     }
@@ -1859,7 +1436,7 @@
         try {
             fis = mAccountInfoFile.openRead();
             if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                Log.v(TAG_FILE, "Reading " + mAccountInfoFile.getBaseFile());
+                Slog.v(TAG_FILE, "Reading " + mAccountInfoFile.getBaseFile());
             }
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, StandardCharsets.UTF_8.name());
@@ -1869,7 +1446,7 @@
                 eventType = parser.next();
             }
             if (eventType == XmlPullParser.END_DOCUMENT) {
-                Log.i(TAG, "No initial accounts");
+                Slog.i(TAG, "No initial accounts");
                 return;
             }
 
@@ -1933,11 +1510,11 @@
                 } while (eventType != XmlPullParser.END_DOCUMENT);
             }
         } catch (XmlPullParserException e) {
-            Log.w(TAG, "Error reading accounts", e);
+            Slog.w(TAG, "Error reading accounts", e);
             return;
         } catch (java.io.IOException e) {
-            if (fis == null) Log.i(TAG, "No initial accounts");
-            else Log.w(TAG, "Error reading accounts", e);
+            if (fis == null) Slog.i(TAG, "No initial accounts");
+            else Slog.w(TAG, "Error reading accounts", e);
             return;
         } finally {
             mNextAuthorityId = Math.max(highestAuthorityId + 1, mNextAuthorityId);
@@ -1977,10 +1554,6 @@
         final int N = mAuthorities.size();
         for (int i = 0; i < N; i++) {
             AuthorityInfo authority = mAuthorities.valueAt(i);
-            // skip this authority if it doesn't target a provider
-            if (authority.target.target_service) {
-                continue;
-            }
             // skip this authority if it isn't one of the renamed ones
             final String newAuthorityName = sAuthorityRenames.get(authority.target.provider);
             if (newAuthorityName == null) {
@@ -2030,9 +1603,9 @@
         try {
             userId = Integer.parseInt(user);
         } catch (NumberFormatException e) {
-            Log.e(TAG, "error parsing the user for listen-for-tickles", e);
+            Slog.e(TAG, "error parsing the user for listen-for-tickles", e);
         } catch (NullPointerException e) {
-            Log.e(TAG, "the user in listen-for-tickles is null", e);
+            Slog.e(TAG, "the user in listen-for-tickles is null", e);
         }
         String enabled = parser.getAttributeValue(null, XML_ATTR_ENABLED);
         boolean listen = enabled == null || Boolean.parseBoolean(enabled);
@@ -2045,9 +1618,9 @@
         try {
             id = Integer.parseInt(parser.getAttributeValue(null, "id"));
         } catch (NumberFormatException e) {
-            Log.e(TAG, "error parsing the id of the authority", e);
+            Slog.e(TAG, "error parsing the id of the authority", e);
         } catch (NullPointerException e) {
-            Log.e(TAG, "the id of the authority is null", e);
+            Slog.e(TAG, "the id of the authority is null", e);
         }
         if (id >= 0) {
             String authorityName = parser.getAttributeValue(null, "authority");
@@ -2065,7 +1638,7 @@
             }
             authority = mAuthorities.get(id);
             if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                Log.v(TAG_FILE, "Adding authority:"
+                Slog.v(TAG_FILE, "Adding authority:"
                         + " account=" + accountName
                         + " accountType=" + accountType
                         + " auth=" + authorityName
@@ -2077,27 +1650,13 @@
             }
             if (authority == null) {
                 if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                    Log.v(TAG_FILE, "Creating authority entry");
+                    Slog.v(TAG_FILE, "Creating authority entry");
                 }
-                EndPoint info;
+                EndPoint info = null;
                 if (accountName != null && authorityName != null) {
                     info = new EndPoint(
                             new Account(accountName, accountType),
                             authorityName, userId);
-                } else {
-                    final ComponentName cname = new ComponentName(packageName, className);
-                    android.content.pm.ServiceInfo sinfo = null;
-                    try {
-                        sinfo = mContext.getPackageManager().getServiceInfo(cname, userId);
-                    } catch (PackageManager.NameNotFoundException e) {
-                        Slog.w(TAG, "Not restoring sync " + cname
-                                + " -- can't find service for user " + userId);
-                    }
-                    if (sinfo != null) {
-                        info = new EndPoint(cname, userId, sinfo.applicationInfo.uid);
-                    } else {
-                        info = null;
-                    }
                 }
                 if (info != null) {
                     authority = getOrCreateAuthorityLocked(info, id, false);
@@ -2128,7 +1687,7 @@
 
                 }
             } else {
-                Log.w(TAG, "Failure adding authority: account="
+                Slog.w(TAG, "Failure adding authority: account="
                         + accountName + " auth=" + authorityName
                         + " enabled=" + enabled
                         + " syncable=" + syncable);
@@ -2149,35 +1708,30 @@
         try {
             period = Long.parseLong(periodValue);
         } catch (NumberFormatException e) {
-            Log.e(TAG, "error parsing the period of a periodic sync", e);
+            Slog.e(TAG, "error parsing the period of a periodic sync", e);
             return null;
         } catch (NullPointerException e) {
-            Log.e(TAG, "the period of a periodic sync is null", e);
+            Slog.e(TAG, "the period of a periodic sync is null", e);
             return null;
         }
         try {
             flextime = Long.parseLong(flexValue);
         } catch (NumberFormatException e) {
             flextime = calculateDefaultFlexTime(period);
-            Log.e(TAG, "Error formatting value parsed for periodic sync flex: " + flexValue
+            Slog.e(TAG, "Error formatting value parsed for periodic sync flex: " + flexValue
                     + ", using default: "
                     + flextime);
         } catch (NullPointerException expected) {
             flextime = calculateDefaultFlexTime(period);
-            Log.d(TAG, "No flex time specified for this sync, using a default. period: "
-            + period + " flex: " + flextime);
+            Slog.d(TAG, "No flex time specified for this sync, using a default. period: "
+                    + period + " flex: " + flextime);
         }
         PeriodicSync periodicSync;
-        if (authorityInfo.target.target_provider) {
-            periodicSync =
+        periodicSync =
                 new PeriodicSync(authorityInfo.target.account,
                         authorityInfo.target.provider,
                         extras,
                         period, flextime);
-        } else {
-            Log.e(TAG, "Unknown target.");
-            return null;
-        }
         authorityInfo.periodicSyncs.add(periodicSync);
         return periodicSync;
     }
@@ -2205,9 +1759,9 @@
                 extras.putParcelable(name, new Account(value1, value2));
             }
         } catch (NumberFormatException e) {
-            Log.e(TAG, "error parsing bundle value", e);
+            Slog.e(TAG, "error parsing bundle value", e);
         } catch (NullPointerException e) {
-            Log.e(TAG, "error parsing bundle value", e);
+            Slog.e(TAG, "error parsing bundle value", e);
         }
     }
 
@@ -2216,7 +1770,7 @@
      */
     private void writeAccountInfoLocked() {
         if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-            Log.v(TAG_FILE, "Writing new " + mAccountInfoFile.getBaseFile());
+            Slog.v(TAG_FILE, "Writing new " + mAccountInfoFile.getBaseFile());
         }
         FileOutputStream fos = null;
 
@@ -2251,30 +1805,17 @@
                 out.attribute(null, "id", Integer.toString(authority.ident));
                 out.attribute(null, XML_ATTR_USER, Integer.toString(info.userId));
                 out.attribute(null, XML_ATTR_ENABLED, Boolean.toString(authority.enabled));
-                if (info.service == null) {
-                    out.attribute(null, "account", info.account.name);
-                    out.attribute(null, "type", info.account.type);
-                    out.attribute(null, "authority", info.provider);
-                } else {
-                    out.attribute(null, "package", info.service.getPackageName());
-                    out.attribute(null, "class", info.service.getClassName());
-                }
+                out.attribute(null, "account", info.account.name);
+                out.attribute(null, "type", info.account.type);
+                out.attribute(null, "authority", info.provider);
                 out.attribute(null, "syncable", Integer.toString(authority.syncable));
-                for (PeriodicSync periodicSync : authority.periodicSyncs) {
-                    out.startTag(null, "periodicSync");
-                    out.attribute(null, "period", Long.toString(periodicSync.period));
-                    out.attribute(null, "flex", Long.toString(periodicSync.flexTime));
-                    final Bundle extras = periodicSync.extras;
-                    extrasToXml(out, extras);
-                    out.endTag(null, "periodicSync");
-                }
                 out.endTag(null, "authority");
             }
             out.endTag(null, "accounts");
             out.endDocument();
             mAccountInfoFile.finishWrite(fos);
         } catch (java.io.IOException e1) {
-            Log.w(TAG, "Error writing accounts", e1);
+            Slog.w(TAG, "Error writing accounts", e1);
             if (fos != null) {
                 mAccountInfoFile.failWrite(fos);
             }
@@ -2313,7 +1854,7 @@
 
             // Copy in all of the status information, as well as accounts.
             if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                Log.v(TAG_FILE, "Reading legacy sync accounts db");
+                Slog.v(TAG_FILE, "Reading legacy sync accounts db");
             }
             SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
             qb.setTables("stats, status");
@@ -2429,7 +1970,7 @@
      */
     private void readStatusLocked() {
         if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-            Log.v(TAG_FILE, "Reading " + mStatusFile.getBaseFile());
+            Slog.v(TAG_FILE, "Reading " + mStatusFile.getBaseFile());
         }
         try {
             byte[] data = mStatusFile.readFully();
@@ -2443,18 +1984,18 @@
                     if (mAuthorities.indexOfKey(status.authorityId) >= 0) {
                         status.pending = false;
                         if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                            Log.v(TAG_FILE, "Adding status for id " + status.authorityId);
+                            Slog.v(TAG_FILE, "Adding status for id " + status.authorityId);
                         }
                         mSyncStatus.put(status.authorityId, status);
                     }
                 } else {
                     // Ooops.
-                    Log.w(TAG, "Unknown status token: " + token);
+                    Slog.w(TAG, "Unknown status token: " + token);
                     break;
                 }
             }
         } catch (java.io.IOException e) {
-            Log.i(TAG, "No initial status");
+            Slog.i(TAG, "No initial status");
         }
     }
 
@@ -2463,7 +2004,7 @@
      */
     private void writeStatusLocked() {
         if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-            Log.v(TAG_FILE, "Writing new " + mStatusFile.getBaseFile());
+            Slog.v(TAG_FILE, "Writing new " + mStatusFile.getBaseFile());
         }
 
         // The file is being written, so we don't need to have a scheduled
@@ -2486,266 +2027,13 @@
 
             mStatusFile.finishWrite(fos);
         } catch (java.io.IOException e1) {
-            Log.w(TAG, "Error writing status", e1);
+            Slog.w(TAG, "Error writing status", e1);
             if (fos != null) {
                 mStatusFile.failWrite(fos);
             }
         }
     }
 
-    public static final int PENDING_OPERATION_VERSION = 3;
-
-    /** Read all pending operations back in to the initial engine state. */
-    private void readPendingOperationsLocked() {
-        FileInputStream fis = null;
-        if (!mPendingFile.getBaseFile().exists()) {
-            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                Log.v(TAG_FILE, "No pending operation file.");
-            }
-            return;
-        }
-        try {
-            fis = mPendingFile.openRead();
-            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                Log.v(TAG_FILE, "Reading " + mPendingFile.getBaseFile());
-            }
-            XmlPullParser parser;
-            parser = Xml.newPullParser();
-            parser.setInput(fis, StandardCharsets.UTF_8.name());
-
-            int eventType = parser.getEventType();
-            while (eventType != XmlPullParser.START_TAG &&
-                    eventType != XmlPullParser.END_DOCUMENT) {
-                eventType = parser.next();
-            }
-            if (eventType == XmlPullParser.END_DOCUMENT) return; // Nothing to read.
-
-            do {
-                PendingOperation pop = null;
-                if (eventType == XmlPullParser.START_TAG) {
-                    try {
-                        String tagName = parser.getName();
-                        if (parser.getDepth() == 1 && "op".equals(tagName)) {
-                            // Verify version.
-                            String versionString =
-                                    parser.getAttributeValue(null, XML_ATTR_VERSION);
-                            if (versionString == null ||
-                                    Integer.parseInt(versionString) != PENDING_OPERATION_VERSION) {
-                                Log.w(TAG, "Unknown pending operation version " + versionString);
-                                throw new java.io.IOException("Unknown version.");
-                            }
-                            int authorityId = Integer.valueOf(parser.getAttributeValue(
-                                    null, XML_ATTR_AUTHORITYID));
-                            boolean expedited = Boolean.valueOf(parser.getAttributeValue(
-                                    null, XML_ATTR_EXPEDITED));
-                            int syncSource = Integer.valueOf(parser.getAttributeValue(
-                                    null, XML_ATTR_SOURCE));
-                            int reason = Integer.valueOf(parser.getAttributeValue(
-                                    null, XML_ATTR_REASON));
-                            AuthorityInfo authority = mAuthorities.get(authorityId);
-                            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                                Log.v(TAG_FILE, authorityId + " " + expedited + " " + syncSource + " "
-                                        + reason);
-                            }
-                            if (authority != null) {
-                                pop = new PendingOperation(
-                                        authority, reason, syncSource, new Bundle(), expedited);
-                                pop.flatExtras = null; // No longer used.
-                                mPendingOperations.add(pop);
-                                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                                    Log.v(TAG_FILE, "Adding pending op: "
-                                            + pop.target
-                                            + " src=" + pop.syncSource
-                                            + " reason=" + pop.reason
-                                            + " expedited=" + pop.expedited);
-                                    }
-                            } else {
-                                // Skip non-existent authority.
-                                pop = null;
-                                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                                    Log.v(TAG_FILE, "No authority found for " + authorityId
-                                            + ", skipping");
-                                }
-                            }
-                        } else if (parser.getDepth() == 2 &&
-                                pop != null &&
-                                "extra".equals(tagName)) {
-                            parseExtra(parser, pop.extras);
-                        }
-                    } catch (NumberFormatException e) {
-                        Log.d(TAG, "Invalid data in xml file.", e);
-                    }
-                }
-                eventType = parser.next();
-            } while(eventType != XmlPullParser.END_DOCUMENT);
-        } catch (java.io.IOException e) {
-            Log.w(TAG_FILE, "Error reading pending data.", e);
-        } catch (XmlPullParserException e) {
-            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                Log.w(TAG_FILE, "Error parsing pending ops xml.", e);
-            }
-        } finally {
-            if (fis != null) {
-                try {
-                    fis.close();
-                } catch (java.io.IOException e1) {}
-            }
-        }
-    }
-
-    static private byte[] flattenBundle(Bundle bundle) {
-        byte[] flatData = null;
-        Parcel parcel = Parcel.obtain();
-        try {
-            bundle.writeToParcel(parcel, 0);
-            flatData = parcel.marshall();
-        } finally {
-            parcel.recycle();
-        }
-        return flatData;
-    }
-
-    static private Bundle unflattenBundle(byte[] flatData) {
-        Bundle bundle;
-        Parcel parcel = Parcel.obtain();
-        try {
-            parcel.unmarshall(flatData, 0, flatData.length);
-            parcel.setDataPosition(0);
-            bundle = parcel.readBundle();
-        } catch (RuntimeException e) {
-            // A RuntimeException is thrown if we were unable to parse the parcel.
-            // Create an empty parcel in this case.
-            bundle = new Bundle();
-        } finally {
-            parcel.recycle();
-        }
-        return bundle;
-    }
-
-    private static final String XML_ATTR_VERSION = "version";
-    private static final String XML_ATTR_AUTHORITYID = "authority_id";
-    private static final String XML_ATTR_SOURCE = "source";
-    private static final String XML_ATTR_EXPEDITED = "expedited";
-    private static final String XML_ATTR_REASON = "reason";
-
-    /**
-     * Write all currently pending ops to the pending ops file.
-     */
-    private void writePendingOperationsLocked() {
-        final int N = mPendingOperations.size();
-        FileOutputStream fos = null;
-        try {
-            if (N == 0) {
-                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)){
-                    Log.v(TAG, "Truncating " + mPendingFile.getBaseFile());
-                }
-                mPendingFile.truncate();
-                return;
-            }
-            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                Log.v(TAG, "Writing new " + mPendingFile.getBaseFile());
-            }
-            fos = mPendingFile.startWrite();
-            XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, StandardCharsets.UTF_8.name());
-
-            for (int i = 0; i < N; i++) {
-                PendingOperation pop = mPendingOperations.get(i);
-                writePendingOperationLocked(pop, out);
-             }
-             out.endDocument();
-             mPendingFile.finishWrite(fos);
-        } catch (java.io.IOException e1) {
-            Log.w(TAG, "Error writing pending operations", e1);
-            if (fos != null) {
-                mPendingFile.failWrite(fos);
-            }
-        }
-    }
-
-    /** Write all currently pending ops to the pending ops file. */
-     private void writePendingOperationLocked(PendingOperation pop, XmlSerializer out)
-             throws IOException {
-         // Pending operation.
-         out.startTag(null, "op");
-
-         out.attribute(null, XML_ATTR_VERSION, Integer.toString(PENDING_OPERATION_VERSION));
-         out.attribute(null, XML_ATTR_AUTHORITYID, Integer.toString(pop.authorityId));
-         out.attribute(null, XML_ATTR_SOURCE, Integer.toString(pop.syncSource));
-         out.attribute(null, XML_ATTR_EXPEDITED, Boolean.toString(pop.expedited));
-         out.attribute(null, XML_ATTR_REASON, Integer.toString(pop.reason));
-         extrasToXml(out, pop.extras);
-
-         out.endTag(null, "op");
-     }
-
-    /**
-     * Append the given operation to the pending ops file; if unable to,
-     * write all pending ops.
-     */
-    private void appendPendingOperationLocked(PendingOperation op) {
-        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-            Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
-        }
-        FileOutputStream fos = null;
-        try {
-            fos = mPendingFile.openAppend();
-        } catch (java.io.IOException e) {
-            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-                Log.v(TAG, "Failed append; writing full file");
-            }
-            writePendingOperationsLocked();
-            return;
-        }
-
-        try {
-            XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, StandardCharsets.UTF_8.name());
-            writePendingOperationLocked(op, out);
-            out.endDocument();
-            mPendingFile.finishWrite(fos);
-        } catch (java.io.IOException e1) {
-            Log.w(TAG, "Error writing appending operation", e1);
-            mPendingFile.failWrite(fos);
-        } finally {
-            try {
-                fos.close();
-            } catch (IOException e) {}
-        }
-    }
-
-    private void extrasToXml(XmlSerializer out, Bundle extras) throws java.io.IOException {
-        for (String key : extras.keySet()) {
-            out.startTag(null, "extra");
-            out.attribute(null, "name", key);
-            final Object value = extras.get(key);
-            if (value instanceof Long) {
-                out.attribute(null, "type", "long");
-                out.attribute(null, "value1", value.toString());
-            } else if (value instanceof Integer) {
-                out.attribute(null, "type", "integer");
-                out.attribute(null, "value1", value.toString());
-            } else if (value instanceof Boolean) {
-                out.attribute(null, "type", "boolean");
-                out.attribute(null, "value1", value.toString());
-            } else if (value instanceof Float) {
-                out.attribute(null, "type", "float");
-                out.attribute(null, "value1", value.toString());
-            } else if (value instanceof Double) {
-                out.attribute(null, "type", "double");
-                out.attribute(null, "value1", value.toString());
-            } else if (value instanceof String) {
-                out.attribute(null, "type", "string");
-                out.attribute(null, "value1", value.toString());
-            } else if (value instanceof Account) {
-                out.attribute(null, "type", "account");
-                out.attribute(null, "value1", ((Account)value).name);
-                out.attribute(null, "value2", ((Account)value).type);
-            }
-            out.endTag(null, "extra");
-        }
-    }
-
     private void requestSync(AuthorityInfo authorityInfo, int reason, Bundle extras) {
         if (android.os.Process.myUid() == android.os.Process.SYSTEM_UID
                 && mSyncRequestListener != null) {
@@ -2755,20 +2043,13 @@
                     new SyncRequest.Builder()
                             .syncOnce()
                             .setExtras(extras);
-            if (authorityInfo.target.target_provider) {
-                req.setSyncAdapter(authorityInfo.target.account, authorityInfo.target.provider);
-            } else {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Unknown target, skipping sync request.");
-                }
-                return;
-            }
+            req.setSyncAdapter(authorityInfo.target.account, authorityInfo.target.provider);
             ContentResolver.requestSync(req.build());
         }
     }
 
     private void requestSync(Account account, int userId, int reason, String authority,
-            Bundle extras) {
+                             Bundle extras) {
         // If this is happening in the system process, then call the syncrequest listener
         // to make a request back to the SyncManager directly.
         // If this is probably a test instance, then call back through the ContentResolver
@@ -2776,9 +2057,9 @@
         if (android.os.Process.myUid() == android.os.Process.SYSTEM_UID
                 && mSyncRequestListener != null) {
             mSyncRequestListener.onSyncRequest(
-                new EndPoint(account, authority, userId),
-                reason,
-                extras);
+                    new EndPoint(account, authority, userId),
+                    reason,
+                    extras);
         } else {
             ContentResolver.requestSync(account, authority, extras);
         }
@@ -2817,12 +2098,12 @@
                     }
                 } else {
                     // Ooops.
-                    Log.w(TAG, "Unknown stats token: " + token);
+                    Slog.w(TAG, "Unknown stats token: " + token);
                     break;
                 }
             }
         } catch (java.io.IOException e) {
-            Log.i(TAG, "No initial statistics");
+            Slog.i(TAG, "No initial statistics");
         }
     }
 
@@ -2831,7 +2112,7 @@
      */
     private void writeStatisticsLocked() {
         if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
-            Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
+            Slog.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
         }
 
         // The file is being written, so we don't need to have a scheduled
@@ -2861,7 +2142,7 @@
 
             mStatisticsFile.finishWrite(fos);
         } catch (java.io.IOException e1) {
-            Log.w(TAG, "Error writing stats", e1);
+            Slog.w(TAG, "Error writing stats", e1);
             if (fos != null) {
                 mStatisticsFile.failWrite(fos);
             }
@@ -2869,18 +2150,6 @@
     }
 
     /**
-     * Dump state of PendingOperations.
-     */
-    public void dumpPendingOperations(StringBuilder sb) {
-        sb.append("Pending Ops: ").append(mPendingOperations.size()).append(" operation(s)\n");
-        for (PendingOperation pop : mPendingOperations) {
-            sb.append("(info: " + pop.target.toString())
-                .append(", extras: " + pop.extras)
-                .append(")\n");
-        }
-    }
-
-    /**
      * Let the BackupManager know that account sync settings have changed. This will trigger
      * {@link com.android.server.backup.SystemBackupAgent} to run.
      */
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 43cd44f..4c269989 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -83,7 +83,7 @@
     public static final boolean DEBUG = false;
     /** The number of concurrent jobs we run at one time. */
     private static final int MAX_JOB_CONTEXTS_COUNT
-            = ActivityManager.isLowRamDeviceStatic() ? 1 : 3;
+            = ActivityManager.isLowRamDeviceStatic() ? 3 : 6;
     static final String TAG = "JobSchedulerService";
     /** Master list of jobs. */
     final JobStore mJobs;
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 4113180..e749433 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -255,10 +255,13 @@
      * the constraints are satisfied <strong>or</strong> the deadline on the job has expired.
      */
     public synchronized boolean isReady() {
-        // Deadline constraint trumps other constraints
+        // Deadline constraint trumps other constraints (except for periodic jobs where deadline
+        // (is an implementation detail. A periodic job should only run if it's constraints are
+        // satisfied).
         // AppNotIdle implicit constraint trumps all!
         return (isConstraintsSatisfied()
-                    || (hasDeadlineConstraint() && deadlineConstraintSatisfied.get()))
+                    || (!job.isPeriodic()
+                            && hasDeadlineConstraint() && deadlineConstraintSatisfied.get()))
                 && appNotIdleConstraintSatisfied.get();
     }
 
@@ -346,9 +349,9 @@
         pw.print(prefix); UserHandle.formatUid(pw, uId);
         pw.print(" tag="); pw.println(tag);
         pw.print(prefix);
-        pw.print("Source: uid="); UserHandle.formatUid(pw, sourceUid);
-        pw.print(" user="); pw.print(sourceUserId);
-        pw.print(" pkg="); pw.println(sourcePackageName);
+        pw.print("Source: uid="); UserHandle.formatUid(pw, getSourceUid());
+        pw.print(" user="); pw.print(getSourceUserId());
+        pw.print(" pkg="); pw.println(getSourcePackageName());
         pw.print(prefix); pw.println("JobInfo:");
         pw.print(prefix); pw.print("  Service: ");
         pw.println(job.getService().flattenToShortString());
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 9798e56..ffc52b3 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -38,8 +38,8 @@
 import android.location.GnssStatus;
 import android.location.IGnssStatusListener;
 import android.location.IGnssStatusProvider;
-import android.location.GpsMeasurementsEvent;
-import android.location.GpsNavigationMessageEvent;
+import android.location.GnssMeasurementsEvent;
+import android.location.GnssNavigationMessageEvent;
 import android.location.IGpsGeofenceHardware;
 import android.location.ILocationManager;
 import android.location.INetInitiatedListener;
@@ -368,8 +368,8 @@
     private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
     private Bundle mLocationExtras = new Bundle();
     private final GnssStatusListenerHelper mListenerHelper;
-    private final GpsMeasurementsProvider mGpsMeasurementsProvider;
-    private final GpsNavigationMessageProvider mGpsNavigationMessageProvider;
+    private final GnssMeasurementsProvider mGnssMeasurementsProvider;
+    private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
 
     // Handler for processing events
     private Handler mHandler;
@@ -428,12 +428,12 @@
         return mGpsGeofenceBinder;
     }
 
-    public GpsMeasurementsProvider getGpsMeasurementsProvider() {
-        return mGpsMeasurementsProvider;
+    public GnssMeasurementsProvider getGnssMeasurementsProvider() {
+        return mGnssMeasurementsProvider;
     }
 
-    public GpsNavigationMessageProvider getGpsNavigationMessageProvider() {
-        return mGpsNavigationMessageProvider;
+    public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
+        return mGnssNavigationMessageProvider;
     }
 
     /**
@@ -713,7 +713,7 @@
             }
         };
 
-        mGpsMeasurementsProvider = new GpsMeasurementsProvider(mHandler) {
+        mGnssMeasurementsProvider = new GnssMeasurementsProvider(mHandler) {
             @Override
             public boolean isAvailableInPlatform() {
                 return native_is_measurement_supported();
@@ -735,7 +735,7 @@
             }
         };
 
-        mGpsNavigationMessageProvider = new GpsNavigationMessageProvider(mHandler) {
+        mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mHandler) {
             @Override
             protected boolean isAvailableInPlatform() {
                 return native_is_navigation_message_supported();
@@ -1087,8 +1087,8 @@
                 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
             }
 
-            mGpsMeasurementsProvider.onGpsEnabledChanged();
-            mGpsNavigationMessageProvider.onGpsEnabledChanged();
+            mGnssMeasurementsProvider.onGpsEnabledChanged();
+            mGnssNavigationMessageProvider.onGpsEnabledChanged();
         } else {
             synchronized (mLock) {
                 mEnabled = false;
@@ -1123,8 +1123,8 @@
         // do this before releasing wakelock
         native_cleanup();
 
-        mGpsMeasurementsProvider.onGpsEnabledChanged();
-        mGpsNavigationMessageProvider.onGpsEnabledChanged();
+        mGnssMeasurementsProvider.onGpsEnabledChanged();
+        mGnssNavigationMessageProvider.onGpsEnabledChanged();
     }
 
     @Override
@@ -1655,15 +1655,15 @@
     /**
      * called from native code - Gps measurements callback
      */
-    private void reportMeasurementData(GpsMeasurementsEvent event) {
-        mGpsMeasurementsProvider.onMeasurementsAvailable(event);
+    private void reportMeasurementData(GnssMeasurementsEvent event) {
+        mGnssMeasurementsProvider.onMeasurementsAvailable(event);
     }
 
     /**
      * called from native code - GPS navigation message callback
      */
-    private void reportNavigationMessage(GpsNavigationMessageEvent event) {
-        mGpsNavigationMessageProvider.onNavigationMessageAvailable(event);
+    private void reportNavigationMessage(GnssNavigationMessageEvent event) {
+        mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
     }
 
     /**
@@ -1677,9 +1677,9 @@
             requestUtcTime();
         }
 
-        mGpsMeasurementsProvider.onCapabilitiesUpdated(
+        mGnssMeasurementsProvider.onCapabilitiesUpdated(
                 (capabilities & GPS_CAPABILITY_MEASUREMENTS) == GPS_CAPABILITY_MEASUREMENTS);
-        mGpsNavigationMessageProvider.onCapabilitiesUpdated(
+        mGnssNavigationMessageProvider.onCapabilitiesUpdated(
                 (capabilities & GPS_CAPABILITY_NAV_MESSAGES) == GPS_CAPABILITY_NAV_MESSAGES);
     }
 
diff --git a/services/core/java/com/android/server/location/GpsMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
similarity index 62%
rename from services/core/java/com/android/server/location/GpsMeasurementsProvider.java
rename to services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index b327ca2..d9e8e91 100644
--- a/services/core/java/com/android/server/location/GpsMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -16,8 +16,8 @@
 
 package com.android.server.location;
 
-import android.location.GpsMeasurementsEvent;
-import android.location.IGpsMeasurementsListener;
+import android.location.GnssMeasurementsEvent;
+import android.location.IGnssMeasurementsListener;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
@@ -29,27 +29,27 @@
  *
  * @hide
  */
-public abstract class GpsMeasurementsProvider
-        extends RemoteListenerHelper<IGpsMeasurementsListener> {
-    private static final String TAG = "GpsMeasurementsProvider";
+public abstract class GnssMeasurementsProvider
+        extends RemoteListenerHelper<IGnssMeasurementsListener> {
+    private static final String TAG = "GnssMeasurementsProvider";
 
-    protected GpsMeasurementsProvider(Handler handler) {
+    protected GnssMeasurementsProvider(Handler handler) {
         super(handler, TAG);
     }
 
-    public void onMeasurementsAvailable(final GpsMeasurementsEvent event) {
-        ListenerOperation<IGpsMeasurementsListener> operation =
-                new ListenerOperation<IGpsMeasurementsListener>() {
+    public void onMeasurementsAvailable(final GnssMeasurementsEvent event) {
+        ListenerOperation<IGnssMeasurementsListener> operation =
+                new ListenerOperation<IGnssMeasurementsListener>() {
             @Override
-            public void execute(IGpsMeasurementsListener listener) throws RemoteException {
-                listener.onGpsMeasurementsReceived(event);
+            public void execute(IGnssMeasurementsListener listener) throws RemoteException {
+                listener.onGnssMeasurementsReceived(event);
             }
         };
         foreach(operation);
     }
 
-    public void onCapabilitiesUpdated(boolean isGpsMeasurementsSupported) {
-        setSupported(isGpsMeasurementsSupported);
+    public void onCapabilitiesUpdated(boolean isGnssMeasurementsSupported) {
+        setSupported(isGnssMeasurementsSupported);
         updateResult();
     }
 
@@ -60,19 +60,19 @@
     }
 
     @Override
-    protected ListenerOperation<IGpsMeasurementsListener> getHandlerOperation(int result) {
+    protected ListenerOperation<IGnssMeasurementsListener> getHandlerOperation(int result) {
         int status;
         switch (result) {
             case RESULT_SUCCESS:
-                status = GpsMeasurementsEvent.STATUS_READY;
+                status = GnssMeasurementsEvent.STATUS_READY;
                 break;
             case RESULT_NOT_AVAILABLE:
             case RESULT_NOT_SUPPORTED:
             case RESULT_INTERNAL_ERROR:
-                status = GpsMeasurementsEvent.STATUS_NOT_SUPPORTED;
+                status = GnssMeasurementsEvent.STATUS_NOT_SUPPORTED;
                 break;
             case RESULT_GPS_LOCATION_DISABLED:
-                status = GpsMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
+                status = GnssMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
                 break;
             case RESULT_UNKNOWN:
                 return null;
@@ -84,7 +84,7 @@
     }
 
     private static class StatusChangedOperation
-            implements ListenerOperation<IGpsMeasurementsListener> {
+            implements ListenerOperation<IGnssMeasurementsListener> {
         private final int mStatus;
 
         public StatusChangedOperation(int status) {
@@ -92,7 +92,7 @@
         }
 
         @Override
-        public void execute(IGpsMeasurementsListener listener) throws RemoteException {
+        public void execute(IGnssMeasurementsListener listener) throws RemoteException {
             listener.onStatusChanged(mStatus);
         }
     }
diff --git a/services/core/java/com/android/server/location/GpsNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
similarity index 61%
rename from services/core/java/com/android/server/location/GpsNavigationMessageProvider.java
rename to services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index e6bbe56..57bce4b 100644
--- a/services/core/java/com/android/server/location/GpsNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -16,8 +16,8 @@
 
 package com.android.server.location;
 
-import android.location.GpsNavigationMessageEvent;
-import android.location.IGpsNavigationMessageListener;
+import android.location.GnssNavigationMessageEvent;
+import android.location.IGnssNavigationMessageListener;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
@@ -29,28 +29,28 @@
  *
  * @hide
  */
-public abstract class GpsNavigationMessageProvider
-        extends RemoteListenerHelper<IGpsNavigationMessageListener> {
-    private static final String TAG = "GpsNavigationMessageProvider";
+public abstract class GnssNavigationMessageProvider
+        extends RemoteListenerHelper<IGnssNavigationMessageListener> {
+    private static final String TAG = "GnssNavigationMessageProvider";
 
-    protected GpsNavigationMessageProvider(Handler handler) {
+    protected GnssNavigationMessageProvider(Handler handler) {
         super(handler, TAG);
     }
 
-    public void onNavigationMessageAvailable(final GpsNavigationMessageEvent event) {
-        ListenerOperation<IGpsNavigationMessageListener> operation =
-                new ListenerOperation<IGpsNavigationMessageListener>() {
+    public void onNavigationMessageAvailable(final GnssNavigationMessageEvent event) {
+        ListenerOperation<IGnssNavigationMessageListener> operation =
+                new ListenerOperation<IGnssNavigationMessageListener>() {
                     @Override
-                    public void execute(IGpsNavigationMessageListener listener)
+                    public void execute(IGnssNavigationMessageListener listener)
                             throws RemoteException {
-                        listener.onGpsNavigationMessageReceived(event);
+                        listener.onGnssNavigationMessageReceived(event);
                     }
                 };
         foreach(operation);
     }
 
-    public void onCapabilitiesUpdated(boolean isGpsNavigationMessageSupported) {
-        setSupported(isGpsNavigationMessageSupported);
+    public void onCapabilitiesUpdated(boolean isGnssNavigationMessageSupported) {
+        setSupported(isGnssNavigationMessageSupported);
         updateResult();
     }
 
@@ -61,19 +61,19 @@
     }
 
     @Override
-    protected ListenerOperation<IGpsNavigationMessageListener> getHandlerOperation(int result) {
+    protected ListenerOperation<IGnssNavigationMessageListener> getHandlerOperation(int result) {
         int status;
         switch (result) {
             case RESULT_SUCCESS:
-                status = GpsNavigationMessageEvent.STATUS_READY;
+                status = GnssNavigationMessageEvent.STATUS_READY;
                 break;
             case RESULT_NOT_AVAILABLE:
             case RESULT_NOT_SUPPORTED:
             case RESULT_INTERNAL_ERROR:
-                status = GpsNavigationMessageEvent.STATUS_NOT_SUPPORTED;
+                status = GnssNavigationMessageEvent.STATUS_NOT_SUPPORTED;
                 break;
             case RESULT_GPS_LOCATION_DISABLED:
-                status = GpsNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
+                status = GnssNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
                 break;
             case RESULT_UNKNOWN:
                 return null;
@@ -85,7 +85,7 @@
     }
 
     private static class StatusChangedOperation
-            implements ListenerOperation<IGpsNavigationMessageListener> {
+            implements ListenerOperation<IGnssNavigationMessageListener> {
         private final int mStatus;
 
         public StatusChangedOperation(int status) {
@@ -93,7 +93,7 @@
         }
 
         @Override
-        public void execute(IGpsNavigationMessageListener listener) throws RemoteException {
+        public void execute(IGnssNavigationMessageListener listener) throws RemoteException {
             listener.onStatusChanged(mStatus);
         }
     }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 5c77079..7f8099e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -192,7 +192,7 @@
  * enforcement.
  */
 public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
-    private static final String TAG = "NetworkPolicy";
+    static final String TAG = "NetworkPolicy";
     private static final boolean LOGD = false;
     private static final boolean LOGV = false;
 
@@ -255,6 +255,7 @@
     private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
     private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
     private static final int MSG_SCREEN_ON_CHANGED = 8;
+    private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9;
 
     private final Context mContext;
     private final IActivityManager mActivityManager;
@@ -1688,6 +1689,7 @@
             }
             writePolicy = true;
         }
+        updateRulesForGlobalChangeLocked(true);
 
         // Remove associated UID policies
         int[] uids = new int[0];
@@ -1861,9 +1863,10 @@
         Slog.i(TAG, "adding uid " + uid + " to restrict background whitelist");
         synchronized (mRulesLock) {
             mRestrictBackgroundWhitelistUids.append(uid, true);
+            updateRulesForGlobalChangeLocked(true);
             writePolicyLocked();
-            // TODO: call other update methods like updateNetworkRulesLocked?
         }
+        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 0).sendToTarget();
     }
 
     @Override
@@ -1873,11 +1876,13 @@
         synchronized (mRulesLock) {
             removeRestrictBackgroundWhitelistedUidLocked(uid, true);
         }
+        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 0).sendToTarget();
     }
 
-    private void removeRestrictBackgroundWhitelistedUidLocked(int uid, boolean writePolicy) {
+    private void removeRestrictBackgroundWhitelistedUidLocked(int uid, boolean updateNow) {
         mRestrictBackgroundWhitelistUids.delete(uid);
-        if (writePolicy) {
+        if (updateNow) {
+            updateRulesForGlobalChangeLocked(true);
             writePolicyLocked();
         }
     }
@@ -2571,6 +2576,25 @@
                         }
                     }
                     mListeners.finishBroadcast();
+                    final Intent intent =
+                            new Intent(ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED);
+                    intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                    mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+                    return true;
+                }
+                case MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED: {
+                    final int uid = msg.arg1;
+                    final PackageManager pm = mContext.getPackageManager();
+                    final String[] packages = pm.getPackagesForUid(uid);
+                    final int userId = UserHandle.getUserId(uid);
+                    for (String packageName : packages) {
+                        final Intent intent =
+                                new Intent(ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED);
+                        intent.setPackage(packageName);
+                        intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                        mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
+                    }
+
                     return true;
                 }
                 case MSG_ADVISE_PERSIST_THRESHOLD: {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index 7b1acca..281c3d0 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -16,18 +16,24 @@
 
 package com.android.server.net;
 
-import java.io.PrintWriter;
+import static com.android.server.net.NetworkPolicyManagerService.TAG;
 
-import android.content.Intent;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
 import android.net.INetworkPolicyManager;
+import android.net.NetworkPolicy;
+import android.os.Binder;
 import android.os.RemoteException;
 import android.os.ShellCommand;
+import android.util.Log;
 
-public class NetworkPolicyManagerShellCommand extends ShellCommand {
+class NetworkPolicyManagerShellCommand extends ShellCommand {
 
     final INetworkPolicyManager mInterface;
 
-    NetworkPolicyManagerShellCommand(NetworkPolicyManagerService service) {
+    NetworkPolicyManagerShellCommand(INetworkPolicyManager service) {
         mInterface = service;
     }
 
@@ -65,16 +71,24 @@
         pw.println("  help");
         pw.println("    Print this help text.");
         pw.println("");
-        pw.println("  get restrict-background");
-        pw.println("    Gets the global restrict background usage status.");
-        pw.println("  set restrict-background BOOLEAN");
-        pw.println("    Sets the global restrict background usage status.");
-        pw.println("  list restrict-background-whitelist");
-        pw.println("    Prints UID that are whitelisted for restrict background usage.");
         pw.println("  add restrict-background-whitelist UID");
         pw.println("    Adds a UID to the whitelist 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("    If a boolean argument is passed, filters just the metered (or unmetered)");
+        pw.println("    networks.");
+        pw.println("  list restrict-background-whitelist");
+        pw.println("    Lists UIDs that are whitelisted for restrict background usage.");
         pw.println("  remove restrict-background-whitelist UID");
         pw.println("    Removes a UID from the whitelist for restrict background usage.");
+        pw.println("  set metered-network ID BOOLEAN");
+        pw.println("    Toggles whether the given non-mobile network is metered.");
+        pw.println("  set restrict-background BOOLEAN");
+        pw.println("    Sets the global restrict background usage status.");
     }
 
     private int runGet() throws RemoteException {
@@ -85,8 +99,10 @@
             return -1;
         }
         switch(type) {
+            case "metered-network":
+                return getNonMobileMeteredNetwork();
             case "restrict-background":
-                return getRestrictBackgroundWhitelist();
+                return getRestrictBackground();
         }
         pw.println("Error: unknown get type '" + type + "'");
         return -1;
@@ -100,8 +116,10 @@
             return -1;
         }
         switch(type) {
+            case "metered-network":
+                return setNonMobileMeteredNetwork();
             case "restrict-background":
-                return setRestrictBackgroundWhitelist();
+                return setRestrictBackground();
         }
         pw.println("Error: unknown set type '" + type + "'");
         return -1;
@@ -115,6 +133,8 @@
             return -1;
         }
         switch(type) {
+            case "metered-networks":
+                return listNonMobileMeteredNetworks();
             case "restrict-background-whitelist":
                 return runListRestrictBackgroundWhitelist();
         }
@@ -169,19 +189,24 @@
         return 0;
     }
 
-    private int getRestrictBackgroundWhitelist() throws RemoteException {
+    private int getRestrictBackground() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         pw.print("Restrict background status: ");
         pw.println(mInterface.getRestrictBackground() ? "enabled" : "disabled");
         return 0;
     }
 
-    private int setRestrictBackgroundWhitelist() throws RemoteException {
+    private int setRestrictBackground() throws RemoteException {
         final int enabled = getNextBooleanArg();
         if (enabled < 0) {
             return enabled;
         }
-        mInterface.setRestrictBackground(enabled > 0);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mInterface.setRestrictBackground(enabled > 0);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
         return 0;
     }
 
@@ -190,7 +215,12 @@
       if (uid < 0) {
           return uid;
       }
-      mInterface.addRestrictBackgroundWhitelistedUid(uid);
+      final long token = Binder.clearCallingIdentity();
+      try {
+          mInterface.addRestrictBackgroundWhitelistedUid(uid);
+      } finally {
+          Binder.restoreCallingIdentity(token);
+      }
       return 0;
     }
 
@@ -199,10 +229,95 @@
         if (uid < 0) {
             return uid;
         }
-        mInterface.removeRestrictBackgroundWhitelistedUid(uid);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mInterface.removeRestrictBackgroundWhitelistedUid(uid);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
         return 0;
     }
 
+    private int listNonMobileMeteredNetworks() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        final String arg = getNextArg();
+        final Boolean filter = arg == null ? null : Boolean.valueOf(arg);
+        for (NetworkPolicy policy : getNonMobilePolicies()) {
+            if (filter != null && filter.booleanValue() != policy.metered) {
+                continue;
+            }
+            pw.print(getNetworkId(policy));
+            pw.print(';');
+            pw.println(policy.metered);
+        }
+        return 0;
+    }
+
+    private int getNonMobileMeteredNetwork() 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 = getNonMobilePolicies();
+        for (NetworkPolicy policy: policies) {
+            if (id.equals(getNetworkId(policy))) {
+                pw.println(policy.metered);
+                return 0;
+            }
+        }
+        return 0;
+    }
+
+    private int setNonMobileMeteredNetwork() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        final String id = getNextArg();
+        if (id == null) {
+            pw.println("Error: didn't specify ID");
+            return -1;
+        }
+        final String arg = getNextArg();
+        if (arg == null) {
+            pw.println("Error: didn't specify BOOLEAN");
+            return -1;
+        }
+        final boolean metered = Boolean.valueOf(arg);
+        final NetworkPolicy[] policies = mInterface.getNetworkPolicies(null);
+        boolean changed = false;
+        for (NetworkPolicy policy : policies) {
+            if (policy.template.isMatchRuleMobile() || policy.metered == metered) {
+                continue;
+            }
+            final String networkId = getNetworkId(policy);
+            if (id.equals(networkId)) {
+                Log.i(TAG, "Changing " + networkId + " metered status to " + metered);
+                policy.metered = metered;
+                changed = true;
+            }
+        }
+        if (changed) {
+            mInterface.setNetworkPolicies(policies);
+        }
+        return 0;
+    }
+
+    private List<NetworkPolicy> getNonMobilePolicies() throws RemoteException {
+        final NetworkPolicy[] policies = mInterface.getNetworkPolicies(null);
+        final List<NetworkPolicy> nonMobilePolicies = new ArrayList<NetworkPolicy>(policies.length);
+        for (NetworkPolicy policy: policies) {
+            if (!policy.template.isMatchRuleMobile()) {
+                nonMobilePolicies.add(policy);
+            }
+        }
+        return nonMobilePolicies;
+    }
+
+    private String getNetworkId(NetworkPolicy policy) {
+        // ids are typically enclosed on double quotes (")
+        return policy.template.getNetworkId().replaceAll("^\"|\"$", "");
+    }
+
     private int getNextBooleanArg() {
         final PrintWriter pw = getOutPrintWriter();
         final String arg = getNextArg();
diff --git a/services/core/java/com/android/server/notification/CountdownConditionProvider.java b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
index 07903e9..c1a7ac6 100644
--- a/services/core/java/com/android/server/notification/CountdownConditionProvider.java
+++ b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
@@ -107,11 +107,6 @@
     }
 
     @Override
-    public void onRequestConditions(int relevance) {
-        // by convention
-    }
-
-    @Override
     public void onSubscribe(Uri conditionId) {
         if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
         mTime = ZenModeConfig.tryParseCountdownConditionId(conditionId);
diff --git a/services/core/java/com/android/server/notification/EventConditionProvider.java b/services/core/java/com/android/server/notification/EventConditionProvider.java
index a4d5bce..ab3cb83 100644
--- a/services/core/java/com/android/server/notification/EventConditionProvider.java
+++ b/services/core/java/com/android/server/notification/EventConditionProvider.java
@@ -134,12 +134,6 @@
     }
 
     @Override
-    public void onRequestConditions(int relevance) {
-        if (DEBUG) Slog.d(TAG, "onRequestConditions relevance=" + relevance);
-        // does not advertise conditions
-    }
-
-    @Override
     public void onSubscribe(Uri conditionId) {
         if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
         if (!ZenModeConfig.isValidEventConditionId(conditionId)) {
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index f5da52e..29d52c1 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -250,6 +250,12 @@
         rebindServices();
     }
 
+    public void onUserUnlocked(int user) {
+        if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user);
+        rebuildRestoredPackages();
+        rebindServices();
+    }
+
     public ManagedServiceInfo getServiceFromTokenLocked(IInterface service) {
         if (service == null) {
             return null;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b54efcc..bcb2c59 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -30,15 +30,16 @@
 import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_BANNED;
 import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_CHANGED;
 import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_SUSPENDED;
+import static android.service.notification.NotificationAssistantService.REASON_PROFILE_TURNED_OFF;
 import static android.service.notification.NotificationAssistantService.REASON_TOPIC_BANNED;
 import static android.service.notification.NotificationAssistantService.REASON_USER_STOPPED;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
 import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_LIGHTS;
 import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_PEEK;
 import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -118,6 +119,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
+
 import com.android.internal.R;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.util.FastXmlSerializer;
@@ -134,6 +136,7 @@
 import com.android.server.vr.VrStateListener;
 
 import libcore.io.IoUtils;
+
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -787,6 +790,13 @@
                     cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle,
                             REASON_USER_STOPPED, null, null);
                 }
+            } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED)) {
+                boolean inQuietMode = intent.getBooleanExtra(Intent.EXTRA_QUIET_MODE, false);
+                int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                if (inQuietMode && userHandle >= 0) {
+                    cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle,
+                            REASON_PROFILE_TURNED_OFF, null, null);
+                }
             } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
                 // turn off LED when user passes through lock screen
                 mNotificationLight.turnOff();
@@ -806,6 +816,12 @@
             } else if (action.equals(Intent.ACTION_USER_REMOVED)) {
                 final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                 mZenModeHelper.onUserRemoved(user);
+            } else if (action.equals(Intent.ACTION_USER_UNLOCKED)) {
+                final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+                mConditionProviders.onUserUnlocked(user);
+                mListeners.onUserUnlocked(user);
+                mAssistant.onUserUnlocked(user);
+                mZenModeHelper.onUserUnlocked(user);
             }
         }
     };
@@ -984,6 +1000,8 @@
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         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);
         getContext().registerReceiver(mIntentReceiver, filter);
 
         IntentFilter pkgFilter = new IntentFilter();
@@ -1254,6 +1272,12 @@
         }
 
         @Override
+        public boolean hasBannedTopics(String pkg, int uid) {
+            checkCallerIsSystem();
+            return mRankingHelper.hasBannedTopics(pkg, uid);
+        }
+
+        @Override
         public ParceledListSlice<Notification.Topic> getTopics(String pkg, int uid) {
             checkCallerIsSystem();
             return new ParceledListSlice<Notification.Topic>(mRankingHelper.getTopics(pkg, uid));
@@ -2829,17 +2853,20 @@
             final int N = mNotificationList.size();
             ArrayList<String> orderBefore = new ArrayList<String>(N);
             int[] visibilities = new int[N];
+            int [] importances = new int[N];
             for (int i = 0; i < N; i++) {
                 final NotificationRecord r = mNotificationList.get(i);
                 orderBefore.add(r.getKey());
                 visibilities[i] = r.getPackageVisibilityOverride();
+                importances[i] = r.getImportance();
                 mRankingHelper.extractSignals(r);
             }
             mRankingHelper.sort(mNotificationList);
             for (int i = 0; i < N; i++) {
                 final NotificationRecord r = mNotificationList.get(i);
                 if (!orderBefore.get(i).equals(r.getKey())
-                        || visibilities[i] != r.getPackageVisibilityOverride()) {
+                        || visibilities[i] != r.getPackageVisibilityOverride()
+                        || importances[i] != r.getImportance()) {
                     scheduleSendRankingUpdate();
                     return;
                 }
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 7f85e1f..1a7e355 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -37,4 +37,6 @@
     int getImportance(String packageName, int uid, Notification.Topic topic);
 
     boolean doesAppUseTopics(String packageName, int uid);
+
+    boolean hasBannedTopics(String packageName, int uid);
 }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 827482f..aa36e29 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -389,6 +389,17 @@
         return topics;
     }
 
+    @Override
+    public boolean hasBannedTopics(String packageName, int uid) {
+        final Record r = getOrCreateRecord(packageName, uid);
+        for (Topic t : r.topics.values()) {
+            if (t.importance == Ranking.IMPORTANCE_NONE) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Gets priority. If a topic is given, returns the priority of that topic. Otherwise, the
      * priority of the app.
diff --git a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
index 44448cc..c9b0ebb 100644
--- a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
+++ b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
@@ -107,12 +107,6 @@
     }
 
     @Override
-    public void onRequestConditions(int relevance) {
-        if (DEBUG) Slog.d(TAG, "onRequestConditions relevance=" + relevance);
-        // does not advertise conditions
-    }
-
-    @Override
     public void onSubscribe(Uri conditionId) {
         if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
         if (!ZenModeConfig.isValidScheduleConditionId(conditionId)) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 1d91fb7..7518c6e 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -16,9 +16,10 @@
 
 package com.android.server.notification;
 
-import static android.media.AudioAttributes.USAGE_ALARM;
 import static android.media.AudioAttributes.USAGE_NOTIFICATION;
 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
+import static android.media.AudioAttributes.USAGE_UNKNOWN;
+import static android.media.AudioAttributes.USAGE_VIRTUAL_SOURCE;
 
 import android.app.AppOpsManager;
 import android.app.AutomaticZenRule;
@@ -34,6 +35,7 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
+import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
 import android.media.AudioSystem;
@@ -192,19 +194,7 @@
     }
 
     public void onUserSwitched(int user) {
-        if (mUser == user || user < UserHandle.USER_SYSTEM) return;
-        mUser = user;
-        if (DEBUG) Log.d(TAG, "onUserSwitched u=" + user);
-        ZenModeConfig config = mConfigs.get(user);
-        if (config == null) {
-            if (DEBUG) Log.d(TAG, "onUserSwitched: generating default config for user " + user);
-            config = mDefaultConfig.copy();
-            config.user = user;
-        }
-        synchronized (mConfig) {
-            setConfigLocked(config, "onUserSwitched");
-        }
-        cleanUpZenRules();
+        loadConfigForUser(user, "onUserSwitched");
     }
 
     public void onUserRemoved(int user) {
@@ -213,6 +203,26 @@
         mConfigs.remove(user);
     }
 
+    public void onUserUnlocked(int user) {
+        loadConfigForUser(user, "onUserUnlocked");
+    }
+
+    private void loadConfigForUser(int user, String reason) {
+        if (mUser == user || user < UserHandle.USER_SYSTEM) return;
+        mUser = user;
+        if (DEBUG) Log.d(TAG, reason + " u=" + user);
+        ZenModeConfig config = mConfigs.get(user);
+        if (config == null) {
+            if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user);
+            config = mDefaultConfig.copy();
+            config.user = user;
+        }
+        synchronized (mConfig) {
+            setConfigLocked(config, reason);
+        }
+        cleanUpZenRules();
+    }
+
     public int getZenModeListenerInterruptionFilter() {
         return NotificationManager.zenModeToInterruptionFilter(mZenMode);
     }
@@ -705,15 +715,20 @@
 
         // notification restrictions
         final boolean muteNotifications = mEffectsSuppressed;
-        applyRestrictions(muteNotifications, USAGE_NOTIFICATION);
-
         // call restrictions
         final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers;
-        applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE);
+        // total silence restrictions
+        final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
 
-        // alarm restrictions
-        final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
-        applyRestrictions(muteAlarms, USAGE_ALARM);
+        for (int i = USAGE_UNKNOWN; i <= USAGE_VIRTUAL_SOURCE; i++) {
+            if (i == USAGE_NOTIFICATION) {
+                applyRestrictions(muteNotifications || muteEverything, i);
+            } else if (i == USAGE_NOTIFICATION_RINGTONE) {
+                applyRestrictions(muteCalls || muteEverything, i);
+            } else {
+                applyRestrictions(muteEverything, i);
+            }
+        }
     }
 
     private void applyRestrictions(boolean mute, int usage) {
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 89e89b0..0eacd13 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -94,7 +94,7 @@
                         continue;
                     }
                     if (!pm.performDexOpt(pkg, /* instruction set */ null, useJitProfiles,
-                            /* extractOnly */ false)) {
+                            /* extractOnly */ false, /* force */ false)) {
                         // there was a problem running dexopt,
                         // remember this so we do not keep retrying.
                         sFailedPackageNames.add(pkg);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 5d97afa..c08f713 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -16,11 +16,11 @@
 
 package com.android.server.pm;
 
-import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.PackageStats;
 import android.os.Build;
+import android.os.storage.StorageManager;
 import android.util.Slog;
 
 import com.android.internal.os.InstallerConnection;
@@ -29,9 +29,6 @@
 
 import dalvik.system.VMRuntime;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 public final class Installer extends SystemService {
     private static final String TAG = "Installer";
 
@@ -49,20 +46,12 @@
     public static final int DEXOPT_BOOTCOMPLETE = 1 << 4;
     /** Do not compile, only extract bytecode into an OAT file */
     public static final int DEXOPT_EXTRACTONLY  = 1 << 5;
+    /** This is an OTA update dexopt */
+    public static final int DEXOPT_OTA          = 1 << 6;
 
-    /** @hide */
-    @IntDef(flag = true, value = {
-            FLAG_DE_STORAGE,
-            FLAG_CE_STORAGE,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface StorageFlags {}
-
-    public static final int FLAG_DE_STORAGE = 1 << 0;
-    public static final int FLAG_CE_STORAGE = 1 << 1;
-
-    public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 2;
-    public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 3;
+    // NOTE: keep in sync with installd
+    public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
+    public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
 
     private final InstallerConnection mInstaller;
 
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
new file mode 100644
index 0000000..da62a2d
--- /dev/null
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.AppGlobals;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.IOtaDexopt;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.Package;
+import android.content.pm.ResolveInfo;
+import android.os.Environment;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.storage.StorageManager;
+import android.util.ArraySet;
+import android.util.Log;
+
+import dalvik.system.DexFile;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static com.android.server.pm.Installer.DEXOPT_OTA;
+
+/**
+ * A service for A/B OTA dexopting.
+ *
+ * {@hide}
+ */
+public class OtaDexoptService extends IOtaDexopt.Stub {
+    private final static String TAG = "OTADexopt";
+    private final static boolean DEBUG_DEXOPT = true;
+    // Apps used in the last 7 days.
+    private final static long DEXOPT_LRU_THRESHOLD_IN_MINUTES = 7 * 24 * 60;
+
+    private final Context mContext;
+    private final PackageDexOptimizer mPackageDexOptimizer;
+    private final PackageManagerService mPackageManagerService;
+
+    // TODO: Evaluate the need for WeakReferences here.
+    private List<PackageParser.Package> mDexoptPackages;
+
+    public OtaDexoptService(Context context, PackageManagerService packageManagerService) {
+        this.mContext = context;
+        this.mPackageManagerService = packageManagerService;
+
+        // Use the package manager install and install lock here for the OTA dex optimizer.
+        mPackageDexOptimizer = new OTADexoptPackageDexOptimizer(packageManagerService.mInstaller,
+                packageManagerService.mInstallLock, context);
+    }
+
+    public static OtaDexoptService main(Context context,
+            PackageManagerService packageManagerService) {
+        OtaDexoptService ota = new OtaDexoptService(context, packageManagerService);
+        ServiceManager.addService("otadexopt", ota);
+
+        return ota;
+    }
+
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ResultReceiver resultReceiver) throws RemoteException {
+        (new OtaDexoptShellCommand(this)).exec(
+                this, in, out, err, args, resultReceiver);
+    }
+
+    @Override
+    public synchronized void prepare() throws RemoteException {
+        if (mDexoptPackages != null) {
+            throw new IllegalStateException("already called prepare()");
+        }
+
+        mDexoptPackages = new LinkedList<>();
+
+        ArrayList<PackageParser.Package> pkgs;
+        synchronized (mPackageManagerService.mPackages) {
+            pkgs = new ArrayList<PackageParser.Package>(mPackageManagerService.mPackages.values());
+        }
+
+        // Sort apps by importance for dexopt ordering. Important apps are given more priority
+        // in case the device runs out of space.
+
+        // Give priority to core apps.
+        for (PackageParser.Package pkg : pkgs) {
+            if (pkg.coreApp) {
+                if (DEBUG_DEXOPT) {
+                    Log.i(TAG, "Adding core app " + mDexoptPackages.size() + ": " + pkg.packageName);
+                }
+                mDexoptPackages.add(pkg);
+            }
+        }
+        pkgs.removeAll(mDexoptPackages);
+
+        // Give priority to system apps that listen for pre boot complete.
+        Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
+        ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
+        for (PackageParser.Package pkg : pkgs) {
+            if (pkgNames.contains(pkg.packageName)) {
+                if (DEBUG_DEXOPT) {
+                    Log.i(TAG, "Adding pre boot system app " + mDexoptPackages.size() + ": " +
+                            pkg.packageName);
+                }
+                mDexoptPackages.add(pkg);
+            }
+        }
+        pkgs.removeAll(mDexoptPackages);
+
+        // Filter out packages that aren't recently used, add all remaining apps.
+        // TODO: add a property to control this?
+        if (mPackageManagerService.isHistoricalPackageUsageAvailable()) {
+            filterRecentlyUsedApps(pkgs, DEXOPT_LRU_THRESHOLD_IN_MINUTES * 60 * 1000);
+        }
+        mDexoptPackages.addAll(pkgs);
+
+        // Now go ahead and also add the libraries required for these packages.
+        // TODO: Think about interleaving things.
+        Set<PackageParser.Package> dependencies = new HashSet<>();
+        for (PackageParser.Package p : mDexoptPackages) {
+            dependencies.addAll(mPackageManagerService.findSharedNonSystemLibraries(p));
+        }
+        if (!dependencies.isEmpty()) {
+            dependencies.removeAll(mDexoptPackages);
+        }
+        mDexoptPackages.addAll(dependencies);
+
+        if (DEBUG_DEXOPT) {
+            StringBuilder sb = new StringBuilder();
+            for (PackageParser.Package pkg : mDexoptPackages) {
+                if (sb.length() > 0) {
+                    sb.append(", ");
+                }
+                sb.append(pkg.packageName);
+            }
+            Log.i(TAG, "Packages to be optimized: " + sb.toString());
+        }
+    }
+
+    @Override
+    public synchronized void cleanup() throws RemoteException {
+        if (DEBUG_DEXOPT) {
+            Log.i(TAG, "Cleaning up OTA Dexopt state.");
+        }
+        mDexoptPackages = null;
+    }
+
+    @Override
+    public synchronized boolean isDone() throws RemoteException {
+        if (mDexoptPackages == null) {
+            throw new IllegalStateException("done() called before prepare()");
+        }
+
+        return mDexoptPackages.isEmpty();
+    }
+
+    @Override
+    public synchronized void dexoptNextPackage() throws RemoteException {
+        if (mDexoptPackages == null) {
+            throw new IllegalStateException("dexoptNextPackage() called before prepare()");
+        }
+        if (mDexoptPackages.isEmpty()) {
+            // Tolerate repeated calls.
+            return;
+        }
+
+        PackageParser.Package nextPackage = mDexoptPackages.remove(0);
+
+        if (DEBUG_DEXOPT) {
+            Log.i(TAG, "Processing " + nextPackage.packageName + " for OTA dexopt.");
+        }
+
+        // Check for low space.
+        // TODO: If apps are not installed in the internal /data partition, we should compare
+        //       against that storage's free capacity.
+        File dataDir = Environment.getDataDirectory();
+        long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
+        if (lowThreshold == 0) {
+            throw new IllegalStateException("Invalid low memory threshold");
+        }
+        long usableSpace = dataDir.getUsableSpace();
+        if (usableSpace < lowThreshold) {
+            Log.w(TAG, "Not running dexopt on " + nextPackage.packageName + " due to low memory: " +
+                    usableSpace);
+            return;
+        }
+
+        mPackageDexOptimizer.performDexOpt(nextPackage, null /* ISAs */, false /* useProfiles */,
+                false /* extractOnly */);
+    }
+
+    private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
+        List<ResolveInfo> ris = null;
+        try {
+            ris = AppGlobals.getPackageManager().queryIntentReceivers(
+                    intent, null, 0, userId);
+        } catch (RemoteException e) {
+        }
+        ArraySet<String> pkgNames = new ArraySet<String>(ris == null ? 0 : ris.size());
+        if (ris != null) {
+            for (ResolveInfo ri : ris) {
+                pkgNames.add(ri.activityInfo.packageName);
+            }
+        }
+        return pkgNames;
+    }
+
+    private void filterRecentlyUsedApps(Collection<PackageParser.Package> pkgs,
+            long dexOptLRUThresholdInMills) {
+        // Filter out packages that aren't recently used.
+        int total = pkgs.size();
+        int skipped = 0;
+        long now = System.currentTimeMillis();
+        for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
+            PackageParser.Package pkg = i.next();
+            long then = pkg.mLastPackageUsageTimeInMills;
+            if (then + dexOptLRUThresholdInMills < now) {
+                if (DEBUG_DEXOPT) {
+                    Log.i(TAG, "Skipping dexopt of " + pkg.packageName + " last resumed: " +
+                          ((then == 0) ? "never" : new Date(then)));
+                }
+                i.remove();
+                skipped++;
+            }
+        }
+        if (DEBUG_DEXOPT) {
+            Log.i(TAG, "Skipped optimizing " + skipped + " of " + total);
+        }
+    }
+
+    private static class OTADexoptPackageDexOptimizer extends
+            PackageDexOptimizer.ForcedUpdatePackageDexOptimizer {
+
+        public OTADexoptPackageDexOptimizer(Installer installer, Object installLock,
+                Context context) {
+            super(installer, installLock, context, "*otadexopt*");
+        }
+
+        @Override
+        protected int adjustDexoptFlags(int dexoptFlags) {
+            // Add the OTA flag.
+            return dexoptFlags | DEXOPT_OTA;
+        }
+
+        @Override
+        protected void recordSuccessfulDexopt(Package pkg, String instructionSet) {
+            // Never record the dexopt, as it's in the B partition.
+        }
+
+    }
+}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java b/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java
new file mode 100644
index 0000000..ea9cf17
--- /dev/null
+++ b/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.content.pm.IOtaDexopt;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+
+import java.io.PrintWriter;
+
+class OtaDexoptShellCommand extends ShellCommand {
+    final IOtaDexopt mInterface;
+
+    OtaDexoptShellCommand(OtaDexoptService service) {
+        mInterface = service;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(null);
+        }
+
+        final PrintWriter pw = getOutPrintWriter();
+        try {
+            switch(cmd) {
+                case "prepare":
+                    return runOtaPrepare();
+                case "cleanup":
+                    return runOtaCleanup();
+                case "done":
+                    return runOtaDone();
+                case "step":
+                    return runOtaStep();
+                default:
+                    return handleDefaultCommands(cmd);
+            }
+        } catch (RemoteException e) {
+            pw.println("Remote exception: " + e);
+        }
+        return -1;
+    }
+
+    private int runOtaPrepare() throws RemoteException {
+        mInterface.prepare();
+        getOutPrintWriter().println("Success");
+        return 0;
+    }
+
+    private int runOtaCleanup() throws RemoteException {
+        mInterface.cleanup();
+        return 0;
+    }
+
+    private int runOtaDone() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        if (mInterface.isDone()) {
+            pw.println("OTA complete.");
+        } else {
+            pw.println("OTA incomplete.");
+        }
+        return 0;
+    }
+
+    private int runOtaStep() throws RemoteException {
+        mInterface.dexoptNextPackage();
+        return 0;
+    }
+
+    @Override
+    public void onHelp() {
+        final PrintWriter pw = getOutPrintWriter();
+        pw.println("OTA Dexopt (ota) commands:");
+        pw.println("  help");
+        pw.println("    Print this help text.");
+        pw.println("");
+        pw.println("  prepare");
+        pw.println("    Prepare an OTA dexopt pass, collecting all packages.");
+        pw.println("  done");
+        pw.println("    Replies whether the OTA is complete or not.");
+        pw.println("  step");
+        pw.println("    OTA dexopt the next package.");
+        pw.println("  cleanup");
+        pw.println("    Clean up internal states. Ends an OTA session.");
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 4d66e10..a3af561 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.Package;
 import android.os.PowerManager;
 import android.os.UserHandle;
 import android.os.WorkSource;
@@ -48,7 +49,7 @@
 /**
  * Helper class for running dexopt command on packages.
  */
-final class PackageDexOptimizer {
+class PackageDexOptimizer {
     private static final String TAG = "PackageManager.DexOptimizer";
     static final String OAT_DIR_NAME = "oat";
     // TODO b/19550105 Remove error codes and use exceptions
@@ -57,16 +58,28 @@
     static final int DEX_OPT_DEFERRED = 2;
     static final int DEX_OPT_FAILED = -1;
 
-    private final PackageManagerService mPackageManagerService;
+    private static final boolean DEBUG_DEXOPT = PackageManagerService.DEBUG_DEXOPT;
+
+    private final Installer mInstaller;
+    private final Object mInstallLock;
 
     private final PowerManager.WakeLock mDexoptWakeLock;
     private volatile boolean mSystemReady;
 
-    PackageDexOptimizer(PackageManagerService packageManagerService) {
-        this.mPackageManagerService = packageManagerService;
-        PowerManager powerManager = (PowerManager)packageManagerService.mContext.getSystemService(
-                Context.POWER_SERVICE);
-        mDexoptWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*dexopt*");
+    PackageDexOptimizer(Installer installer, Object installLock, Context context,
+            String wakeLockTag) {
+        this.mInstaller = installer;
+        this.mInstallLock = installLock;
+
+        PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mDexoptWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, wakeLockTag);
+    }
+
+    protected PackageDexOptimizer(PackageDexOptimizer from) {
+        this.mInstaller = from.mInstaller;
+        this.mInstallLock = from.mInstallLock;
+        this.mDexoptWakeLock = from.mDexoptWakeLock;
+        this.mSystemReady = from.mSystemReady;
     }
 
     static boolean canOptimizePackage(PackageParser.Package pkg) {
@@ -77,27 +90,19 @@
      * Performs dexopt on all code paths and libraries of the specified package for specified
      * instruction sets.
      *
-     * <p>Calls to {@link com.android.server.pm.Installer#dexopt} are synchronized on
-     * {@link PackageManagerService#mInstallLock}.
+     * <p>Calls to {@link com.android.server.pm.Installer#dexopt} on {@link #mInstaller} are
+     * synchronized on {@link #mInstallLock}.
      */
-    int performDexOpt(PackageParser.Package pkg, String[] instructionSets,
-            boolean inclDependencies, boolean useProfiles, boolean extractOnly) {
-        ArraySet<String> done;
-        if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
-            done = new ArraySet<String>();
-            done.add(pkg.packageName);
-        } else {
-            done = null;
-        }
-        synchronized (mPackageManagerService.mInstallLock) {
+    int performDexOpt(PackageParser.Package pkg, String[] instructionSets, boolean useProfiles,
+            boolean extractOnly) {
+        synchronized (mInstallLock) {
             final boolean useLock = mSystemReady;
             if (useLock) {
                 mDexoptWakeLock.setWorkSource(new WorkSource(pkg.applicationInfo.uid));
                 mDexoptWakeLock.acquire();
             }
             try {
-                return performDexOptLI(pkg, instructionSets, done, useProfiles,
-                        extractOnly);
+                return performDexOptLI(pkg, instructionSets, useProfiles, extractOnly);
             } finally {
                 if (useLock) {
                     mDexoptWakeLock.release();
@@ -106,21 +111,42 @@
         }
     }
 
+    /**
+     * Determine whether the package should be skipped for the given instruction set. A return
+     * value of true means the package will be skipped. A return value of false means that the
+     * package will be further investigated, and potentially compiled.
+     */
+    protected boolean shouldSkipBasedOnISA(PackageParser.Package pkg, String instructionSet) {
+        return pkg.mDexOptPerformed.contains(instructionSet);
+    }
+
+    /**
+     * Adjust the given dexopt-needed value. Can be overridden to influence the decision to
+     * optimize or not (and in what way).
+     */
+    protected int adjustDexoptNeeded(int dexoptNeeded) {
+        return dexoptNeeded;
+    }
+
+    /**
+     * Adjust the given dexopt flags that will be passed to the installer.
+     */
+    protected int adjustDexoptFlags(int dexoptFlags) {
+        return dexoptFlags;
+    }
+
+    /**
+     * Update the package status after a successful compilation.
+     */
+    protected void recordSuccessfulDexopt(PackageParser.Package pkg, String instructionSet) {
+        pkg.mDexOptPerformed.add(instructionSet);
+    }
+
     private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
-            ArraySet<String> done, boolean useProfiles, boolean extractOnly) {
+            boolean useProfiles, boolean extractOnly) {
         final String[] instructionSets = targetInstructionSets != null ?
                 targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
 
-        if (done != null) {
-            done.add(pkg.packageName);
-            if (pkg.usesLibraries != null) {
-                performDexOptLibsLI(pkg.usesLibraries, instructionSets, done);
-            }
-            if (pkg.usesOptionalLibraries != null) {
-                performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSets, done);
-            }
-        }
-
         if (!canOptimizePackage(pkg)) {
             return DEX_OPT_SKIPPED;
         }
@@ -132,13 +158,14 @@
         boolean performedDexOpt = false;
         final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
         for (String dexCodeInstructionSet : dexCodeInstructionSets) {
-            if (!useProfiles && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) {
+            if (!useProfiles && shouldSkipBasedOnISA(pkg, dexCodeInstructionSet)) {
                 // Skip only if we do not use profiles since they might trigger a recompilation.
                 continue;
             }
 
             for (String path : paths) {
                 int dexoptNeeded;
+
                 try {
                     dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
                             dexCodeInstructionSet, /* defer */false);
@@ -146,11 +173,12 @@
                     Slog.w(TAG, "IOException reading apk: " + path, ioe);
                     return DEX_OPT_FAILED;
                 }
+                dexoptNeeded = adjustDexoptNeeded(dexoptNeeded);
 
                 if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
                     if (useProfiles) {
-                        // If we do a profile guided compilation then we might recompile the same
-                        // package if more profile information is available.
+                        // Profiles may trigger re-compilation. The final decision is taken in
+                        // installd.
                         dexoptNeeded = DexFile.DEX2OAT_NEEDED;
                     } else {
                         // No dexopt needed and we don't use profiles. Nothing to do.
@@ -170,21 +198,22 @@
                     throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
                 }
 
+
                 Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
                         + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
                         + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
                         + " extractOnly=" + extractOnly + " oatDir = " + oatDir);
                 final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
-                final int dexFlags =
+                final int dexFlags = adjustDexoptFlags(
                         (!pkg.isForwardLocked() ? DEXOPT_PUBLIC : 0)
                         | (vmSafeMode ? DEXOPT_SAFEMODE : 0)
                         | (debuggable ? DEXOPT_DEBUGGABLE : 0)
                         | (extractOnly ? DEXOPT_EXTRACTONLY : 0)
-                        | DEXOPT_BOOTCOMPLETE;
+                        | DEXOPT_BOOTCOMPLETE);
+
                 try {
-                    mPackageManagerService.mInstaller.dexopt(path, sharedGid,
-                            pkg.packageName, dexCodeInstructionSet, dexoptNeeded, oatDir,
-                            dexFlags, pkg.volumeUuid, useProfiles);
+                    mInstaller.dexopt(path, sharedGid, pkg.packageName, dexCodeInstructionSet,
+                            dexoptNeeded, oatDir, dexFlags, pkg.volumeUuid, useProfiles);
                     performedDexOpt = true;
                 } catch (InstallerException e) {
                     Slog.w(TAG, "Failed to dexopt", e);
@@ -197,7 +226,7 @@
                 // it isn't required. We therefore mark that this package doesn't need dexopt unless
                 // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped
                 // it.
-                pkg.mDexOptPerformed.add(dexCodeInstructionSet);
+                recordSuccessfulDexopt(pkg, dexCodeInstructionSet);
             }
         }
 
@@ -228,8 +257,7 @@
         if (codePath.isDirectory()) {
             File oatDir = getOatDir(codePath);
             try {
-                mPackageManagerService.mInstaller.createOatDir(oatDir.getAbsolutePath(),
-                        dexInstructionSet);
+                mInstaller.createOatDir(oatDir.getAbsolutePath(), dexInstructionSet);
             } catch (InstallerException e) {
                 Slog.w(TAG, "Failed to create oat dir", e);
                 return null;
@@ -243,21 +271,36 @@
         return new File(codePath, OAT_DIR_NAME);
     }
 
-    private void performDexOptLibsLI(ArrayList<String> libs, String[] instructionSets,
-            ArraySet<String> done) {
-        for (String libName : libs) {
-            PackageParser.Package libPkg = mPackageManagerService.findSharedNonSystemLibrary(
-                    libName);
-            if (libPkg != null && !done.contains(libName)) {
-                // TODO: Analyze and investigate if we (should) profile libraries.
-                // Currently this will do a full compilation of the library.
-                performDexOptLI(libPkg, instructionSets, done, /*useProfiles*/ false,
-                        /* extractOnly */ false);
-            }
-        }
-    }
-
     void systemReady() {
         mSystemReady = true;
     }
+
+    /**
+     * A specialized PackageDexOptimizer that overrides already-installed checks, forcing a
+     * dexopt path.
+     */
+    public static class ForcedUpdatePackageDexOptimizer extends PackageDexOptimizer {
+
+        public ForcedUpdatePackageDexOptimizer(Installer installer, Object installLock,
+                Context context, String wakeLockTag) {
+            super(installer, installLock, context, wakeLockTag);
+        }
+
+        public ForcedUpdatePackageDexOptimizer(PackageDexOptimizer from) {
+            super(from);
+        }
+
+        @Override
+        protected boolean shouldSkipBasedOnISA(Package pkg, String instructionSet) {
+            // Forced compilation, never skip.
+            return false;
+        }
+
+        @Override
+        protected int adjustDexoptNeeded(int dexoptNeeded) {
+            // Ensure compilation, no matter the current state.
+            // TODO: The return value is wrong when patchoat is needed.
+            return DexFile.DEX2OAT_NEEDED;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 05ef8dcd..504ce31 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -139,6 +139,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.ActivityIntentInfo;
+import android.content.pm.PackageParser.Package;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.PackageStats;
@@ -234,7 +235,6 @@
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
 import com.android.server.Watchdog;
-import com.android.server.pm.Installer.StorageFlags;
 import com.android.server.pm.PermissionsState.PermissionState;
 import com.android.server.pm.Settings.DatabaseVersion;
 import com.android.server.pm.Settings.VersionInfo;
@@ -263,6 +263,7 @@
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
@@ -277,6 +278,7 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -313,7 +315,12 @@
     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_DEXOPT = 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
+    // user, but by default initialize to this.
+    static final boolean DEBUG_DEXOPT = false;
+
     private static final boolean DEBUG_ABI_SELECTION = false;
     private static final boolean DEBUG_EPHEMERAL = false;
     private static final boolean DEBUG_TRIAGED_MISSING = false;
@@ -1990,7 +1997,8 @@
         }
 
         mInstaller = installer;
-        mPackageDexOptimizer = new PackageDexOptimizer(this);
+        mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
+                "*dexopt*");
         mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
 
         mOnPermissionChangeListeners = new OnPermissionChangeListeners(
@@ -2379,9 +2387,9 @@
             // can't wait for user to start
             final int flags;
             if (StorageManager.isFileBasedEncryptionEnabled()) {
-                flags = Installer.FLAG_DE_STORAGE;
+                flags = StorageManager.FLAG_STORAGE_DE;
             } else {
-                flags = Installer.FLAG_DE_STORAGE | Installer.FLAG_CE_STORAGE;
+                flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             }
             reconcileAppsData(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM, flags);
 
@@ -3377,19 +3385,6 @@
         return null;
     }
 
-    /**
-     * @hide
-     */
-    PackageParser.Package findSharedNonSystemLibrary(String libName) {
-        synchronized (mPackages) {
-            PackageManagerService.SharedLibraryEntry lib = mSharedLibraries.get(libName);
-            if (lib != null && lib.apk != null) {
-                return mPackages.get(lib.apk);
-            }
-        }
-        return null;
-    }
-
     @Override
     public FeatureInfo[] getSystemAvailableFeatures() {
         Collection<FeatureInfo> featSet;
@@ -5369,9 +5364,15 @@
         int targetUserId = filter.getTargetUserId();
         List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent,
                 resolvedType, flags, targetUserId);
-        if (resultTargetUser != null && !resultTargetUser.isEmpty()
-                && isUserEnabled(targetUserId)) {
-            return createForwardingResolveInfoUnchecked(filter, sourceUserId, targetUserId);
+        if (resultTargetUser != null && isUserEnabled(targetUserId)) {
+            // If all the matches in the target profile are suspended, return null.
+            for (int i = resultTargetUser.size() - 1; i >= 0; i--) {
+                if ((resultTargetUser.get(i).activityInfo.applicationInfo.flags
+                        & ApplicationInfo.FLAG_SUSPENDED) == 0) {
+                    return createForwardingResolveInfoUnchecked(filter, sourceUserId,
+                            targetUserId);
+                }
+            }
         }
         return null;
     }
@@ -6633,7 +6634,7 @@
             if (pkgs != null) {
                 for (String pkg : pkgs) {
                     performDexOpt(pkg, null /* instructionSet */, false /* useProfiles */,
-                            true /* extractOnly */);
+                            true /* extractOnly */, false /* force */);
                 }
             }
         }
@@ -6670,26 +6671,28 @@
     @Override
     public boolean performDexOptIfNeeded(String packageName, String instructionSet) {
         return performDexOptTraced(packageName, instructionSet, false /* useProfiles */,
-                false /* extractOnly */);
+                false /* extractOnly */, false /* force */);
     }
 
+    @Override
     public boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles,
-            boolean extractOnly) {
-        return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly);
+            boolean extractOnly, boolean force) {
+        return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly, force);
     }
 
     private boolean performDexOptTraced(String packageName, String instructionSet,
-                boolean useProfiles, boolean extractOnly) {
+                boolean useProfiles, boolean extractOnly, boolean force) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
         try {
-            return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly);
+            return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly,
+                    force);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
     }
 
     private boolean performDexOptInternal(String packageName, String instructionSet,
-                boolean useProfiles, boolean extractOnly) {
+                boolean useProfiles, boolean extractOnly, boolean force) {
         PackageParser.Package p;
         final String targetInstructionSet;
         synchronized (mPackages) {
@@ -6701,7 +6704,7 @@
 
             targetInstructionSet = instructionSet != null ? instructionSet :
                     getPrimaryInstructionSet(p.applicationInfo);
-            if (!useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) {
+            if (!force && !useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) {
                 // Skip only if we do not use profiles since they might trigger a recompilation.
                 return false;
             }
@@ -6710,8 +6713,8 @@
         try {
             synchronized (mInstallLock) {
                 final String[] instructionSets = new String[] { targetInstructionSet };
-                int result = mPackageDexOptimizer.performDexOpt(p, instructionSets,
-                        true /* inclDependencies */, useProfiles, extractOnly);
+                int result = performDexOptInternalWithDependenciesLI(p, instructionSets,
+                        useProfiles, extractOnly, force);
                 return result == PackageDexOptimizer.DEX_OPT_PERFORMED;
             }
         } finally {
@@ -6731,6 +6734,80 @@
         return pkgs;
     }
 
+    private int performDexOptInternalWithDependenciesLI(PackageParser.Package p,
+            String instructionSets[], boolean useProfiles, boolean extractOnly, boolean force) {
+        // Select the dex optimizer based on the force parameter.
+        // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to
+        //       allocate an object here.
+        PackageDexOptimizer pdo = force
+                ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer)
+                : mPackageDexOptimizer;
+
+        // Optimize all dependencies first. Note: we ignore the return value and march on
+        // on errors.
+        Collection<PackageParser.Package> deps = findSharedNonSystemLibraries(p);
+        if (!deps.isEmpty()) {
+            for (PackageParser.Package depPackage : deps) {
+                // TODO: Analyze and investigate if we (should) profile libraries.
+                // Currently this will do a full compilation of the library.
+                pdo.performDexOpt(depPackage, instructionSets, false /* useProfiles */,
+                        false /* extractOnly */);
+            }
+        }
+
+        return pdo.performDexOpt(p, instructionSets, useProfiles, extractOnly);
+    }
+
+    Collection<PackageParser.Package> findSharedNonSystemLibraries(PackageParser.Package p) {
+        if (p.usesLibraries != null || p.usesOptionalLibraries != null) {
+            ArrayList<PackageParser.Package> retValue = new ArrayList<>();
+            Set<String> collectedNames = new HashSet<>();
+            findSharedNonSystemLibrariesRecursive(p, retValue, collectedNames);
+
+            retValue.remove(p);
+
+            return retValue;
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    private void findSharedNonSystemLibrariesRecursive(PackageParser.Package p,
+            Collection<PackageParser.Package> collected, Set<String> collectedNames) {
+        if (!collectedNames.contains(p.packageName)) {
+            collectedNames.add(p.packageName);
+            collected.add(p);
+
+            if (p.usesLibraries != null) {
+                findSharedNonSystemLibrariesRecursive(p.usesLibraries, collected, collectedNames);
+            }
+            if (p.usesOptionalLibraries != null) {
+                findSharedNonSystemLibrariesRecursive(p.usesOptionalLibraries, collected,
+                        collectedNames);
+            }
+        }
+    }
+
+    private void findSharedNonSystemLibrariesRecursive(Collection<String> libs,
+            Collection<PackageParser.Package> collected, Set<String> collectedNames) {
+        for (String libName : libs) {
+            PackageParser.Package libPkg = findSharedNonSystemLibrary(libName);
+            if (libPkg != null) {
+                findSharedNonSystemLibrariesRecursive(libPkg, collected, collectedNames);
+            }
+        }
+    }
+
+    private PackageParser.Package findSharedNonSystemLibrary(String libName) {
+        synchronized (mPackages) {
+            PackageManagerService.SharedLibraryEntry lib = mSharedLibraries.get(libName);
+            if (lib != null && lib.apk != null) {
+                return mPackages.get(lib.apk);
+            }
+        }
+        return null;
+    }
+
     public void shutdown() {
         mPackageUsage.write(true);
     }
@@ -6755,9 +6832,8 @@
 
             // Whoever is calling forceDexOpt wants a fully compiled package.
             // Don't use profiles since that may cause compilation to be skipped.
-            final int res = mPackageDexOptimizer.performDexOpt(pkg, instructionSets,
-                    true /* inclDependencies */, false /* useProfiles */,
-                    false /* extractOnly */);
+            final int res = performDexOptInternalWithDependenciesLI(pkg, instructionSets,
+                    false /* useProfiles */, false /* extractOnly */, true /* force */);
 
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
@@ -6783,7 +6859,7 @@
 
     private boolean removeDataDirsLI(String volumeUuid, String packageName) {
         // TODO: triage flags as part of 26466827
-        final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+        final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
 
         boolean res = true;
         final int[] users = sUserManager.getUserIds();
@@ -6829,7 +6905,7 @@
 
     private void deleteCodeCacheDirsLI(String volumeUuid, String packageName) {
         // TODO: triage flags as part of 26466827
-        final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+        final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
 
         final int[] users = sUserManager.getUserIds();
         for (int user : users) {
@@ -7972,6 +8048,11 @@
                         pkg.applicationInfo.primaryCpuAbi = abi;
                     }
                 }
+                if (cpuAbiOverride != null &&
+                        cpuAbiOverride.equals(pkg.applicationInfo.secondaryCpuAbi)) {
+                    pkg.applicationInfo.secondaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
+                    pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
+                }
             } else {
                 String[] abiList = (cpuAbiOverride != null) ?
                         new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
@@ -12834,8 +12915,11 @@
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
 
-        // Mark that we have an install time CPU ABI override.
-        pkg.cpuAbiOverride = args.abiOverride;
+        // If package doesn't declare API override, mark that we have an install
+        // time CPU ABI override.
+        if (TextUtils.isEmpty(pkg.cpuAbiOverride)) {
+            pkg.cpuAbiOverride = args.abiOverride;
+        }
 
         String pkgName = res.name = pkg.packageName;
         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
@@ -13008,7 +13092,9 @@
             scanFlags |= SCAN_NO_DEX;
 
             try {
-                derivePackageAbi(pkg, new File(pkg.codePath), args.abiOverride,
+                String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ?
+                    args.abiOverride : pkg.cpuAbiOverride);
+                derivePackageAbi(pkg, new File(pkg.codePath), abiOverride,
                         true /* extract libs */);
             } catch (PackageManagerException pme) {
                 Slog.e(TAG, "Error deriving application ABI", pme);
@@ -13024,8 +13110,7 @@
                 // Do not run PackageDexOptimizer through the local performDexOpt
                 // method because `pkg` is not in `mPackages` yet.
                 int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
-                        false /* inclDependencies */, false /* useProfiles */,
-                        true /* extractOnly */);
+                        false /* useProfiles */, true /* extractOnly */);
                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
                     String msg = "Extracking package failed for " + pkgName;
@@ -13861,7 +13946,8 @@
                 outInfo.removedUsers = new int[] {removeUser};
             }
             // TODO: triage flags as part of 26466827
-            final int installerFlags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+            final int installerFlags = StorageManager.FLAG_STORAGE_CE
+                    | StorageManager.FLAG_STORAGE_DE;
             try {
                 mInstaller.destroyAppData(ps.volumeUuid, packageName, removeUser, installerFlags);
             } catch (InstallerException e) {
@@ -14041,7 +14127,7 @@
         // record of app. This helps users recover from UID mismatches without
         // resorting to a full data wipe.
         // TODO: triage flags as part of 26466827
-        final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+        final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
         try {
             mInstaller.clearAppData(pkg.volumeUuid, packageName, userId, flags);
         } catch (InstallerException e) {
@@ -14276,7 +14362,7 @@
             return false;
         }
         // TODO: triage flags as part of 26466827
-        final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+        final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
         try {
             mInstaller.clearAppData(p.volumeUuid, packageName, userId,
                     flags | Installer.FLAG_CLEAR_CACHE_ONLY);
@@ -14377,7 +14463,7 @@
         }
 
         // TODO: triage flags as part of 26466827
-        final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+        final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
         try {
             mInstaller.getAppSize(p.volumeUuid, packageName, userHandle, flags, apkPath,
                     libDirRoot, publicSrcDir, asecPath, dexCodeInstructionSets, pStats);
@@ -16701,16 +16787,20 @@
         }
 
         // Reconcile app data for all started/unlocked users
+        final StorageManager sm = mContext.getSystemService(StorageManager.class);
         final UserManager um = mContext.getSystemService(UserManager.class);
         for (UserInfo user : um.getUsers()) {
+            final int flags;
             if (um.isUserUnlocked(user.id)) {
-                reconcileAppsData(volumeUuid, user.id,
-                        Installer.FLAG_DE_STORAGE | Installer.FLAG_CE_STORAGE);
+                flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             } else if (um.isUserRunning(user.id)) {
-                reconcileAppsData(volumeUuid, user.id, Installer.FLAG_DE_STORAGE);
+                flags = StorageManager.FLAG_STORAGE_DE;
             } else {
                 continue;
             }
+
+            sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, flags);
+            reconcileAppsData(volumeUuid, user.id, flags);
         }
 
         synchronized (mPackages) {
@@ -16819,20 +16909,6 @@
                 }
             }
         }
-
-        final StorageManager sm = mContext.getSystemService(StorageManager.class);
-        final UserManager um = mContext.getSystemService(UserManager.class);
-        for (UserInfo user : um.getUsers()) {
-            final File userDir = Environment.getDataUserDirectory(volumeUuid, user.id);
-            if (userDir.exists()) continue;
-
-            try {
-                sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, user.isEphemeral());
-                UserManagerService.enforceSerialNumber(userDir, user.serialNumber);
-            } catch (IOException e) {
-                Log.wtf(TAG, "Failed to create user directory on " + volumeUuid, e);
-            }
-        }
     }
 
     private void assertPackageKnown(String volumeUuid, String packageName)
@@ -16902,7 +16978,7 @@
      * Verifies that directories exist and that ownership and labeling is
      * correct for all installed apps on all mounted volumes.
      */
-    void reconcileAppsData(int userId, @StorageFlags int flags) {
+    void reconcileAppsData(int userId, int flags) {
         final StorageManager storage = mContext.getSystemService(StorageManager.class);
         for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
             final String volumeUuid = vol.getFsUuid();
@@ -16919,7 +16995,7 @@
      * Verifies that directories exist and that ownership and labeling is
      * correct for all installed apps.
      */
-    private void reconcileAppsData(String volumeUuid, int userId, @StorageFlags int flags) {
+    private void reconcileAppsData(String volumeUuid, int userId, int flags) {
         Slog.v(TAG, "reconcileAppsData for " + volumeUuid + " u" + userId + " 0x"
                 + Integer.toHexString(flags));
 
@@ -16930,7 +17006,7 @@
 
         // First look for stale data that doesn't belong, and check if things
         // have changed since we did our last restorecon
-        if ((flags & Installer.FLAG_CE_STORAGE) != 0) {
+        if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
             if (!isUserKeyUnlocked(userId)) {
                 throw new RuntimeException(
                         "Yikes, someone asked us to reconcile CE storage while " + userId
@@ -16948,12 +17024,12 @@
                     logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e);
                     synchronized (mInstallLock) {
                         destroyAppDataLI(volumeUuid, packageName, userId,
-                                Installer.FLAG_CE_STORAGE);
+                                StorageManager.FLAG_STORAGE_CE);
                     }
                 }
             }
         }
-        if ((flags & Installer.FLAG_DE_STORAGE) != 0) {
+        if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) {
             restoreconNeeded |= SELinuxMMAC.isRestoreconNeeded(deDir);
 
             final File[] files = FileUtils.listFilesOrEmpty(deDir);
@@ -16965,7 +17041,7 @@
                     logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e);
                     synchronized (mInstallLock) {
                         destroyAppDataLI(volumeUuid, packageName, userId,
-                                Installer.FLAG_DE_STORAGE);
+                                StorageManager.FLAG_STORAGE_DE);
                     }
                 }
             }
@@ -16994,10 +17070,10 @@
         }
 
         if (restoreconNeeded) {
-            if ((flags & Installer.FLAG_CE_STORAGE) != 0) {
+            if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
                 SELinuxMMAC.setRestoreconDone(ceDir);
             }
-            if ((flags & Installer.FLAG_DE_STORAGE) != 0) {
+            if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) {
                 SELinuxMMAC.setRestoreconDone(deDir);
             }
         }
@@ -17026,9 +17102,9 @@
         for (UserInfo user : um.getUsers()) {
             final int flags;
             if (um.isUserUnlocked(user.id)) {
-                flags = Installer.FLAG_DE_STORAGE | Installer.FLAG_CE_STORAGE;
+                flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             } else if (um.isUserRunning(user.id)) {
-                flags = Installer.FLAG_DE_STORAGE;
+                flags = StorageManager.FLAG_STORAGE_DE;
             } else {
                 continue;
             }
@@ -17049,7 +17125,7 @@
      * will try recovering system apps by wiping data; third-party app data is
      * left intact.
      */
-    private void prepareAppData(String volumeUuid, int userId, @StorageFlags int flags,
+    private void prepareAppData(String volumeUuid, int userId, int flags,
             PackageParser.Package pkg, boolean restoreconNeeded) {
         if (DEBUG_APP_DATA) {
             Slog.v(TAG, "prepareAppData for " + pkg.packageName + " u" + userId + " 0x"
@@ -17087,7 +17163,7 @@
                 restoreconAppDataLI(volumeUuid, packageName, userId, flags, appId, app.seinfo);
             }
 
-            if ((flags & Installer.FLAG_CE_STORAGE) != 0) {
+            if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
                 // Create a native library symlink only if we have native libraries
                 // and if the native libraries are 32 bit libraries. We do not provide
                 // this symlink for 64 bit libraries.
@@ -18025,4 +18101,8 @@
                     "Cannot call " + tag + " from UID " + callingUid);
         }
     }
+
+    boolean isHistoricalPackageUsageAvailable() {
+        return mPackageUsage.isHistoricalPackageUsageAvailable();
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 43e4b84..d8845d8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -44,6 +44,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ShellCommand;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.PrintWriterPrinter;
@@ -96,6 +97,8 @@
                     return runInstallCreate();
                 case "install-write":
                     return runInstallWrite();
+                case "compile":
+                    return runCompile();
                 case "list":
                     return runList();
                 case "uninstall":
@@ -227,6 +230,67 @@
         return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
     }
 
+    private int runCompile() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        boolean useJitProfiles = false;
+        boolean extractOnly = false;
+        boolean forceCompilation = false;
+        String compilationMode = "default";
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-m":
+                    compilationMode = getNextArgRequired();
+                    break;
+                case "-f":
+                    forceCompilation = true;
+                    break;
+                default:
+                    pw.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+
+        switch (compilationMode) {
+            case "default":
+                useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
+                extractOnly = false;
+                break;
+            case "all":
+                useJitProfiles = false;
+                extractOnly = false;
+                break;
+            case "profile":
+                useJitProfiles = true;
+                extractOnly = false;
+                break;
+            case "extract":
+                useJitProfiles = false;
+                extractOnly = true;
+                break;
+            default:
+                pw.println("Error: Unknown compilation mode: " + compilationMode);
+                return 1;
+        }
+
+        String packageName = getNextArg();
+        if (packageName == null) {
+            pw.println("Error: package name not specified");
+            return 1;
+        }
+
+        boolean success = mInterface.performDexOpt(packageName, null /* instructionSet */,
+                useJitProfiles, extractOnly, forceCompilation);
+        if (success) {
+            pw.println("Success");
+            return 0;
+        } else {
+            pw.println("Failure: package " + packageName + " could not be compiled");
+            return 1;
+        }
+    }
+
     private int runList() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         final String type = getNextArg();
@@ -1069,6 +1133,12 @@
         pw.println("  help");
         pw.println("    Print this help text.");
         pw.println("");
+        pw.println("  compile [-m MODE] [-f] TARGET-PACKAGE");
+        pw.println("    Trigger compilation of TARGET-PACKAGE.");
+        pw.println("    Options:");
+        pw.println("      -m: select compilation mode");
+        pw.println("          MODE can be one of \"default\", \"all\", \"profile\", and \"extract\"");
+        pw.println("      -f: force compilation even if not needed");
         pw.println("  list features");
         pw.println("    Prints all features of the system.");
         pw.println("  list instrumentation [-f] [TARGET-PACKAGE]");
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index bbbe693..fcb777b 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3787,7 +3787,7 @@
                 continue;
             }
             // TODO: triage flags!
-            final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+            final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
             try {
                 installer.createAppData(volumeUuids[i], names[i], userHandle, flags, appIds[i],
                         seinfos[i], targetSdkVersions[i]);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4ff7667..3cc7b10 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -25,7 +25,6 @@
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
 import android.app.IStopUserCallback;
-import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -78,7 +77,9 @@
 import com.android.internal.util.XmlUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
-import com.android.server.pm.Installer.StorageFlags;
+
+import libcore.io.IoUtils;
+import libcore.util.Objects;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -96,9 +97,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import libcore.io.IoUtils;
-import libcore.util.Objects;
-
 /**
  * Service for {@link UserManager}.
  *
@@ -930,7 +928,9 @@
     /** @return a specific user restriction that's in effect currently. */
     @Override
     public boolean hasUserRestriction(String restrictionKey, int userId) {
-        UserRestrictionsUtils.checkRestriction(restrictionKey);
+        if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
+            return false;
+        }
         Bundle restrictions = getEffectiveUserRestrictions(userId);
         return restrictions != null && restrictions.getBoolean(restrictionKey);
     }
@@ -947,7 +947,9 @@
     @Override
     public boolean hasBaseUserRestriction(String restrictionKey, int userId) {
         checkManageUsersPermission("hasBaseUserRestriction");
-        UserRestrictionsUtils.checkRestriction(restrictionKey);
+        if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
+            return false;
+        }
         synchronized (mRestrictionsLock) {
             Bundle bundle = mBaseUserRestrictions.get(userId);
             return (bundle != null && bundle.getBoolean(restrictionKey, false));
@@ -957,7 +959,9 @@
     @Override
     public void setUserRestriction(String key, boolean value, int userId) {
         checkManageUsersPermission("setUserRestriction");
-        UserRestrictionsUtils.checkRestriction(key);
+        if (!UserRestrictionsUtils.isValidRestriction(key)) {
+            return;
+        }
         synchronized (mRestrictionsLock) {
             // Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create
             // a copy.
@@ -1887,17 +1891,8 @@
             }
             final StorageManager storage = mContext.getSystemService(StorageManager.class);
             storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral());
-            for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
-                final String volumeUuid = vol.getFsUuid();
-                try {
-                    final File userDir = Environment.getDataUserDirectory(volumeUuid, userId);
-                    storage.prepareUserStorage(
-                            volumeUuid, userId, userInfo.serialNumber, userInfo.isEphemeral());
-                    enforceSerialNumber(userDir, userInfo.serialNumber);
-                } catch (IOException e) {
-                    Log.wtf(LOG_TAG, "Failed to create user directory on " + volumeUuid, e);
-                }
-            }
+            prepareUserStorage(userId, userInfo.serialNumber,
+                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
             mPm.createNewUser(userId);
             userInfo.partial = false;
             synchronized (mPackagesLock) {
@@ -2460,11 +2455,24 @@
     }
 
     /**
+     * Prepare storage areas for given user on all mounted devices.
+     */
+    private void prepareUserStorage(int userId, int userSerial, int flags) {
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
+        for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
+            final String volumeUuid = vol.getFsUuid();
+            storage.prepareUserStorage(volumeUuid, userId, userSerial, flags);
+        }
+    }
+
+    /**
      * Called right before a user is started. This gives us a chance to prepare
      * app storage and apply any user restrictions.
      */
     public void onBeforeStartUser(int userId) {
-        mPm.reconcileAppsData(userId, Installer.FLAG_DE_STORAGE);
+        final int userSerial = getUserSerialNumber(userId);
+        prepareUserStorage(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
+        mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE);
 
         if (userId != UserHandle.USER_SYSTEM) {
             synchronized (mRestrictionsLock) {
@@ -2478,7 +2486,9 @@
      * app storage.
      */
     public void onBeforeUnlockUser(int userId) {
-        mPm.reconcileAppsData(userId, Installer.FLAG_CE_STORAGE);
+        final int userSerial = getUserSerialNumber(userId);
+        prepareUserStorage(userId, userSerial, StorageManager.FLAG_STORAGE_CE);
+        mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE);
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 7ab071f..f57f75f 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -36,6 +36,7 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.util.Log;
+import android.util.Slog;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
@@ -101,7 +102,8 @@
             UserManager.DISALLOW_CAMERA,
             UserManager.DISALLOW_RUN_IN_BACKGROUND,
             UserManager.DISALLOW_DATA_ROAMING,
-            UserManager.DISALLOW_SET_USER_ICON
+            UserManager.DISALLOW_SET_USER_ICON,
+            UserManager.DISALLOW_SET_WALLPAPER
     });
 
     /**
@@ -151,10 +153,12 @@
     /**
      * Throws {@link IllegalArgumentException} if the given restriction name is invalid.
      */
-    public static void checkRestriction(@NonNull String restriction) {
+    public static boolean isValidRestriction(@NonNull String restriction) {
         if (!USER_RESTRICTIONS.contains(restriction)) {
-            throw new IllegalArgumentException("Unknown restriction: " + restriction);
+            Slog.wtf(TAG, "Unknown restriction: " + restriction);
+            return false;
         }
+        return true;
     }
 
     public static void writeRestrictions(@NonNull XmlSerializer serializer,
diff --git a/services/core/java/com/android/server/policy/IconUtilities.java b/services/core/java/com/android/server/policy/IconUtilities.java
index 4658344..b196dec 100644
--- a/services/core/java/com/android/server/policy/IconUtilities.java
+++ b/services/core/java/com/android/server/policy/IconUtilities.java
@@ -37,7 +37,7 @@
 /**
  * Various utilities shared amongst the Launcher's classes.
  */
-final class IconUtilities {
+public final class IconUtilities {
     private static final String TAG = "IconUtilities";
 
     private static final int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
@@ -102,7 +102,7 @@
      * Returns a bitmap suitable for the all apps view.  The bitmap will be a power
      * of two sized ARGB_8888 bitmap that can be used as a gl texture.
      */
-    private Bitmap createIconBitmap(Drawable icon) {
+    public Bitmap createIconBitmap(Drawable icon) {
         int width = mIconWidth;
         int height = mIconHeight;
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 43b82e9..a92cc31 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -6877,7 +6877,12 @@
         final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
         final boolean freeformStackVisible =
                 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
-        final boolean forceShowSystemBars = dockedStackVisible || freeformStackVisible;
+        final boolean resizing = mWindowManagerInternal.isDockedDividerResizing();
+
+        // We need to force system bars when the docked stack is visible, when the freeform stack
+        // is visible but also when we are resizing for the transitions when docked stack
+        // visibility changes.
+        final boolean forceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
         final boolean forceOpaqueSystemBars = forceShowSystemBars && !mForceStatusBarFromKeyguard;
 
         // apply translucent bar vis flags
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 9e2ba95..90340d5 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -17,13 +17,16 @@
 package com.android.server.statusbar;
 
 import android.app.StatusBarManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Slog;
@@ -31,11 +34,13 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.FastPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.notification.NotificationDelegate;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.FileDescriptor;
+import java.io.FileOutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -222,6 +227,39 @@
         }
     }
 
+    public void addTile(ComponentName component) {
+        enforceStatusBarOrShell();
+
+        if (mBar != null) {
+            try {
+                mBar.addQsTile(component);
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
+    public void remTile(ComponentName component) {
+        enforceStatusBarOrShell();
+
+        if (mBar != null) {
+            try {
+                mBar.remQsTile(component);
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
+    public void clickTile(ComponentName component) {
+        enforceStatusBarOrShell();
+
+        if (mBar != null) {
+            try {
+                mBar.clickQsTile(component);
+            } catch (RemoteException ex) {
+            }
+        }
+    }
+
     @Override
     public void disable(int what, IBinder token, String pkg) {
         disableForUser(what, token, pkg, mCurrentUserId);
@@ -552,6 +590,13 @@
         }
     }
 
+    private void enforceStatusBarOrShell() {
+        if (Binder.getCallingUid() == Process.SHELL_UID) {
+            return;
+        }
+        enforceStatusBar();
+    }
+
     private void enforceStatusBar() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR,
                 "StatusBarManagerService");
@@ -728,6 +773,13 @@
         }
     }
 
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ResultReceiver resultReceiver) throws RemoteException {
+        (new StatusBarShellCommand(this)).exec(
+                this, in, out, err, args, resultReceiver);
+    }
+
     // ================================================================================
     // Can be called from any thread
     // ================================================================================
diff --git a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
new file mode 100644
index 0000000..963a572
--- /dev/null
+++ b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 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.statusbar;
+
+import android.content.ComponentName;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import com.android.internal.statusbar.IStatusBarService;
+
+import java.io.PrintWriter;
+
+public class StatusBarShellCommand extends ShellCommand {
+
+    private final IStatusBarService mInterface;
+
+    public StatusBarShellCommand(StatusBarManagerService service) {
+        mInterface = service;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+        try {
+            switch (cmd) {
+                case "expand-notifications":
+                    return runExpandNotifications();
+                case "expand-settings":
+                    return runExpandSettings();
+                case "collapse":
+                    return runCollapse();
+                case "add-tile":
+                    return runAddTile();
+                case "remove-tile":
+                    return runRemoveTile();
+                case "click-tile":
+                    return runClickTile();
+                default:
+                    return handleDefaultCommands(cmd);
+            }
+        } catch (RemoteException e) {
+            final PrintWriter pw = getOutPrintWriter();
+            pw.println("Remote exception: " + e);
+        }
+        return -1;
+    }
+
+    private int runAddTile() throws RemoteException {
+        mInterface.addTile(ComponentName.unflattenFromString(getNextArgRequired()));
+        return 0;
+    }
+
+    private int runRemoveTile() throws RemoteException {
+        mInterface.remTile(ComponentName.unflattenFromString(getNextArgRequired()));
+        return 0;
+    }
+
+    private int runClickTile() throws RemoteException {
+        mInterface.clickTile(ComponentName.unflattenFromString(getNextArgRequired()));
+        return 0;
+    }
+
+    private int runCollapse() throws RemoteException {
+        mInterface.collapsePanels();
+        return 0;
+    }
+
+    private int runExpandSettings() throws RemoteException {
+        mInterface.expandSettingsPanel(null);
+        return 0;
+    }
+
+    private int runExpandNotifications() throws RemoteException {
+        mInterface.expandNotificationsPanel();
+        return 0;
+    }
+
+    @Override
+    public void onHelp() {
+        final PrintWriter pw = getOutPrintWriter();
+        pw.println("Status bar commands:");
+        pw.println("  help");
+        pw.println("    Print this help text.");
+        pw.println("");
+        pw.println("  expand-notifications");
+        pw.println("    Open the notifications panel.");
+        pw.println("");
+        pw.println("  expand-settings");
+        pw.println("    Open the notifications panel and expand quick settings if present.");
+        pw.println("");
+        pw.println("  collapse");
+        pw.println("    Collapse the notifications and settings panel.");
+        pw.println("");
+        pw.println("  add-tile COMPONENT");
+        pw.println("    Add a TileService of the specified component");
+        pw.println("");
+        pw.println("  remove-tile COMPONENT");
+        pw.println("    Remove a TileService of the specified component");
+        pw.println("");
+        pw.println("  click-tile COMPONENT");
+        pw.println("    Click on a TileService of the specified component");
+        pw.println("");
+    }
+}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index b065e85..342c078 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -584,14 +584,14 @@
         for (IBinder sessionToken : serviceState.sessionTokens) {
             SessionState sessionState = userState.sessionStateMap.get(sessionToken);
             if (sessionState.session == null && (inputId == null
-                    || sessionState.info.getId().equals(inputId))) {
+                    || sessionState.inputId.equals(inputId))) {
                 sessionsToAbort.add(sessionState);
             }
         }
         for (SessionState sessionState : sessionsToAbort) {
             removeSessionStateLocked(sessionState.sessionToken, sessionState.userId);
             sendSessionTokenToClientLocked(sessionState.client,
-                    sessionState.info.getId(), null, null, sessionState.seq);
+                    sessionState.inputId, null, null, sessionState.seq);
         }
         updateServiceConnectionLocked(serviceState.component, userId);
     }
@@ -601,7 +601,7 @@
         UserState userState = getOrCreateUserStateLocked(userId);
         SessionState sessionState = userState.sessionStateMap.get(sessionToken);
         if (DEBUG) {
-            Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.info.getId() + ")");
+            Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.inputId + ")");
         }
         InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString());
 
@@ -611,14 +611,14 @@
         // Create a session. When failed, send a null token immediately.
         try {
             if (sessionState.isRecordingSession) {
-                service.createRecordingSession(callback, sessionState.info.getId());
+                service.createRecordingSession(callback, sessionState.inputId);
             } else {
-                service.createSession(channels[1], callback, sessionState.info.getId());
+                service.createSession(channels[1], callback, sessionState.inputId);
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "error in createSession", e);
             removeSessionStateLocked(sessionToken, userId);
-            sendSessionTokenToClientLocked(sessionState.client, sessionState.info.getId(), null,
+            sendSessionTokenToClientLocked(sessionState.client, sessionState.inputId, null,
                     null, sessionState.seq);
         }
         channels[1].dispose();
@@ -684,14 +684,11 @@
             }
         }
 
-        TvInputInfo info = sessionState.info;
-        if (info != null) {
-            ServiceState serviceState = userState.serviceStateMap.get(info.getComponent());
-            if (serviceState != null) {
-                serviceState.sessionTokens.remove(sessionToken);
-            }
+        ServiceState serviceState = userState.serviceStateMap.get(sessionState.componentName);
+        if (serviceState != null) {
+            serviceState.sessionTokens.remove(sessionToken);
         }
-        updateServiceConnectionLocked(sessionState.info.getComponent(), userId);
+        updateServiceConnectionLocked(sessionState.componentName, userId);
 
         // Log the end of watch.
         SomeArgs args = SomeArgs.obtain();
@@ -707,7 +704,7 @@
                 sessionState = getSessionStateLocked(sessionState.hardwareSessionToken,
                         Process.SYSTEM_UID, userId);
             }
-            ServiceState serviceState = getServiceStateLocked(sessionState.info.getComponent(), userId);
+            ServiceState serviceState = getServiceStateLocked(sessionState.componentName, userId);
             if (!serviceState.isHardware) {
                 return;
             }
@@ -1091,8 +1088,9 @@
 
                     // Create a new session token and a session state.
                     IBinder sessionToken = new Binder();
-                    SessionState sessionState = new SessionState(sessionToken, info,
-                            isRecordingSession, client, seq, callingUid, resolvedUserId);
+                    SessionState sessionState = new SessionState(sessionToken, info.getId(),
+                            info.getComponent(), isRecordingSession, client, seq, callingUid,
+                            resolvedUserId);
 
                     // Add them to the global session state map of the current user.
                     userState.sessionStateMap.put(sessionToken, sessionState);
@@ -1273,7 +1271,7 @@
 
                         // Log the start of watch.
                         SomeArgs args = SomeArgs.obtain();
-                        args.arg1 = sessionState.info.getComponent().getPackageName();
+                        args.arg1 = sessionState.componentName.getPackageName();
                         args.arg2 = System.currentTimeMillis();
                         args.arg3 = ContentUris.parseId(channelUri);
                         args.arg4 = params;
@@ -1779,10 +1777,10 @@
                         return false;
                     }
                     for (SessionState sessionState : userState.sessionStateMap.values()) {
-                        if (sessionState.info.getId().equals(inputId)
+                        if (sessionState.inputId.equals(inputId)
                                 && sessionState.hardwareSessionToken != null) {
                             hardwareInputId = userState.sessionStateMap.get(
-                                    sessionState.hardwareSessionToken).info.getId();
+                                    sessionState.hardwareSessionToken).inputId;
                             break;
                         }
                     }
@@ -1918,7 +1916,7 @@
                         pw.println(entry.getKey() + ": " + session);
 
                         pw.increaseIndent();
-                        pw.println("info: " + session.info);
+                        pw.println("inputId: " + session.inputId);
                         pw.println("client: " + session.client);
                         pw.println("seq: " + session.seq);
                         pw.println("callingUid: " + session.callingUid);
@@ -2046,7 +2044,8 @@
     }
 
     private final class SessionState implements IBinder.DeathRecipient {
-        private final TvInputInfo info;
+        private final String inputId;
+        private final ComponentName componentName;
         private final boolean isRecordingSession;
         private final ITvInputClient client;
         private final int seq;
@@ -2058,10 +2057,12 @@
         // Not null if this session represents an external device connected to a hardware TV input.
         private IBinder hardwareSessionToken;
 
-        private SessionState(IBinder sessionToken, TvInputInfo info, boolean isRecordingSession,
-                ITvInputClient client, int seq, int callingUid, int userId) {
+        private SessionState(IBinder sessionToken, String inputId, ComponentName componentName,
+                boolean isRecordingSession, ITvInputClient client, int seq, int callingUid,
+                int userId) {
             this.sessionToken = sessionToken;
-            this.info = info;
+            this.inputId = inputId;
+            this.componentName = componentName;
             this.isRecordingSession = isRecordingSession;
             this.client = client;
             this.seq = seq;
@@ -2274,19 +2275,19 @@
         @Override
         public void onSessionCreated(ITvInputSession session, IBinder hardwareSessionToken) {
             if (DEBUG) {
-                Slog.d(TAG, "onSessionCreated(inputId=" + mSessionState.info.getId() + ")");
+                Slog.d(TAG, "onSessionCreated(inputId=" + mSessionState.inputId + ")");
             }
             synchronized (mLock) {
                 mSessionState.session = session;
                 mSessionState.hardwareSessionToken = hardwareSessionToken;
                 if (session != null && addSessionTokenToClientStateLocked(session)) {
                     sendSessionTokenToClientLocked(mSessionState.client,
-                            mSessionState.info.getId(), mSessionState.sessionToken, mChannels[0],
+                            mSessionState.inputId, mSessionState.sessionToken, mChannels[0],
                             mSessionState.seq);
                 } else {
                     removeSessionStateLocked(mSessionState.sessionToken, mSessionState.userId);
                     sendSessionTokenToClientLocked(mSessionState.client,
-                            mSessionState.info.getId(), null, null, mSessionState.seq);
+                            mSessionState.inputId, null, null, mSessionState.seq);
                 }
                 mChannels[0].dispose();
             }
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 2deb0d5..2f076d1 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -36,6 +36,9 @@
 
     public static final String TAG = "VrManagerService";
 
+    private static native void initializeNative();
+    private static native void setVrModeNative(boolean enabled);
+
     private final Object mLock = new Object();
     private boolean mVrModeEnabled = false;
     private ArraySet<VrStateListener> mListeners = new ArraySet<>();
@@ -68,6 +71,10 @@
 
     @Override
     public void onStart() {
+        synchronized(mLock) {
+            initializeNative();
+        }
+
         publishLocalService(VrManagerInternal.class, new LocalService());
     }
 
@@ -89,6 +96,7 @@
                 mVrModeEnabled = enabled;
                 // Log mode change event.
                 Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
+                setVrModeNative(mVrModeEnabled);
                 onVrModeChangedLocked();
             }
         }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index c7d7096..09c53ae 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -27,6 +27,7 @@
 import android.app.PendingIntent;
 import android.app.WallpaperInfo;
 import android.app.WallpaperManager;
+import android.app.admin.DevicePolicyManager;
 import android.app.backup.BackupManager;
 import android.app.backup.WallpaperBackupHelper;
 import android.content.BroadcastReceiver;
@@ -84,6 +85,7 @@
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
 import java.util.List;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -611,7 +613,7 @@
             return changed;
         }
     }
-    
+
     public WallpaperManagerService(Context context) {
         if (DEBUG) Slog.v(TAG, "WallpaperService startup");
         mContext = context;
@@ -626,7 +628,7 @@
         getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
         loadSettingsLocked(UserHandle.USER_SYSTEM);
     }
-    
+
     private static File getWallpaperDir(int userId) {
         return Environment.getUserSystemDirectory(userId);
     }
@@ -764,7 +766,7 @@
     public void clearWallpaper(String callingPackage) {
         if (DEBUG) Slog.v(TAG, "clearWallpaper");
         checkPermission(android.Manifest.permission.SET_WALLPAPER);
-        if (!isWallpaperSupported(callingPackage)) {
+        if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
             return;
         }
         synchronized (mLock) {
@@ -1000,7 +1002,7 @@
             return null;
         }
 
-        if (!isWallpaperSupported(callingPackage)) {
+        if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
             return null;
         }
 
@@ -1069,7 +1071,7 @@
     }
 
     public void setWallpaperComponentChecked(ComponentName name, String callingPackage) {
-        if (isWallpaperSupported(callingPackage)) {
+        if (isWallpaperSupported(callingPackage) && isWallpaperSettingAllowed(callingPackage)) {
             setWallpaperComponent(name);
         }
     }
@@ -1093,7 +1095,7 @@
             }
         }
     }
-    
+
     boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
             boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
         if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
@@ -1113,7 +1115,7 @@
                 }
             }
         }
-        
+
         try {
             if (componentName == null) {
                 componentName = WallpaperManager.getDefaultWallpaperComponent(mContext);
@@ -1143,9 +1145,9 @@
                 Slog.w(TAG, msg);
                 return false;
             }
-            
+
             WallpaperInfo wi = null;
-            
+
             Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
             if (componentName != null && !componentName.equals(mImageWallpaper)) {
                 // Make sure the selected service is actually a wallpaper service.
@@ -1185,7 +1187,7 @@
                     return false;
                 }
             }
-            
+
             // Bind the service!
             if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
             WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
@@ -1314,6 +1316,23 @@
                 callingPackage) == AppOpsManager.MODE_ALLOWED;
     }
 
+    @Override
+    public boolean isWallpaperSettingAllowed(String callingPackage) {
+        final PackageManager pm = mContext.getPackageManager();
+        String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
+        boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
+        if (!uidMatchPackage) {
+            return false;   // callingPackage was faked.
+        }
+
+        final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+        if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
+            return true;
+        }
+        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
+    }
+
     private static JournaledFile makeJournaledFile(int userId) {
         final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
         return new JournaledFile(new File(base), new File(base + ".tmp"));
@@ -1465,7 +1484,7 @@
                                         .getPackageName())) {
                             wallpaper.nextWallpaperComponent = mImageWallpaper;
                         }
-                          
+
                         if (DEBUG) {
                             Slog.v(TAG, "mWidth:" + wallpaper.width);
                             Slog.v(TAG, "mHeight:" + wallpaper.height);
@@ -1666,7 +1685,7 @@
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
-            
+
             pw.println("Permission Denial: can't dump wallpaper service from from pid="
                     + Binder.getCallingPid()
                     + ", uid=" + Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 43a17c9..1821487 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -483,6 +483,62 @@
      * and inner rectangles.
      */
     private static float computePivot(int startPos, float finalScale) {
+
+        /*
+        Theorem of intercepting lines:
+
+          +      +   +-----------------------------------------------+
+          |      |   |                                               |
+          |      |   |                                               |
+          |      |   |                                               |
+          |      |   |                                               |
+        x |    y |   |                                               |
+          |      |   |                                               |
+          |      |   |                                               |
+          |      |   |                                               |
+          |      |   |                                               |
+          |      +   |             +--------------------+            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             |                    |            |
+          |          |             +--------------------+            |
+          |          |                                               |
+          |          |                                               |
+          |          |                                               |
+          |          |                                               |
+          |          |                                               |
+          |          |                                               |
+          |          |                                               |
+          |          +-----------------------------------------------+
+          |
+          |
+          |
+          |
+          |
+          |
+          |
+          |
+          |
+          +                                 ++
+                                         p  ++
+
+        scale = (x - y) / x
+        <=> x = -y / (scale - 1)
+        */
         final float denom = finalScale-1;
         if (Math.abs(denom) < .0001f) {
             return startPos;
@@ -733,14 +789,14 @@
         float unscaledHeight = thumbHeight * scaleW;
         getNextAppTransitionStartRect(taskId, mTmpRect);
         final float unscaledStartY = mTmpRect.top - (unscaledHeight - thumbHeight) / 2f;
-        final float toY = appRect.top + mNextAppTransitionInsets.top + -unscaledStartY;
+        final float toY = appRect.top + -unscaledStartY;
         if (mNextAppTransitionScaleUp) {
             // Animation up from the thumbnail to the full screen
             Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
                     mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f));
             scale.setInterpolator(mTouchResponseInterpolator);
             scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
-            Animation alpha = new AlphaAnimation(1, 0);
+            Animation alpha = new AlphaAnimation(1f, 0f);
             alpha.setInterpolator(mThumbnailFadeOutInterpolator);
             alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
             final float toX = appRect.left + appRect.width() / 2 -
@@ -809,35 +865,27 @@
                             containingFrame, surfaceInsets, taskId);
                 } else {
                     mTmpFromClipRect.set(containingFrame);
-                    // exclude top screen decor (status bar) region from the source clip.
-                    mTmpFromClipRect.top = contentInsets.top;
-                    // App window scaling up to become full screen
                     mTmpToClipRect.set(containingFrame);
-                    if (orientation == Configuration.ORIENTATION_PORTRAIT) {
-                        // In portrait, we scale the width and clip to the top/left square
-                        scale = thumbWidth / appWidth;
-                        scaledTopDecor = (int) (scale * contentInsets.top);
-                        int unscaledThumbHeight = (int) (thumbHeight / scale);
-                        mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight;
-                    } else {
-                        // In landscape, we scale the height and clip to the top/left square. We
-                        // only scale the part that is not covered by status bar and the nav bar.
-                        scale = thumbHeight / (appHeight - contentInsets.top
-                                - contentInsets.bottom);
-                        scaledTopDecor = (int) (scale * contentInsets.top);
-                        int unscaledThumbWidth = (int) (thumbWidth / scale);
-                        mTmpFromClipRect.right = mTmpFromClipRect.left + unscaledThumbWidth;
-                        // This removes the navigation bar from the first frame, so it better
-                        // matches the thumbnail. We need to do this explicitly in landscape,
-                        // because in portrait we already crop vertically.
-                        mTmpFromClipRect.bottom = mTmpFromClipRect.bottom - contentInsets.bottom;
-                    }
+
+                    // Containing frame is in screen space, but we need the clip rect in the
+                    // app space.
+                    mTmpFromClipRect.offsetTo(0, 0);
+                    mTmpToClipRect.offsetTo(0, 0);
+
+                    // Exclude insets region from the source clip.
+                    mTmpFromClipRect.inset(contentInsets);
+
+                    // We scale the width and clip to the top/left square
+                    scale = thumbWidth / (appWidth - contentInsets.left - contentInsets.right);
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbHeight = (int) (thumbHeight / scale);
+                    mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight;
 
                     mNextAppTransitionInsets.set(contentInsets);
 
                     Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
-                            computePivot(mTmpRect.left, scale),
-                            computePivot(mTmpRect.top, scale));
+                            computePivot(mTmpRect.left - containingFrame.left, scale),
+                            computePivot(mTmpRect.top - containingFrame.top, scale));
                     Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                     Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
 
@@ -879,32 +927,26 @@
                 } else {
                     mTmpFromClipRect.set(containingFrame);
                     mTmpToClipRect.set(containingFrame);
-                    // exclude top screen decor (status bar) region from the destination clip.
-                    mTmpToClipRect.top = contentInsets.top;
-                    if (orientation == Configuration.ORIENTATION_PORTRAIT) {
-                        // In portrait, we scale the width and clip to the top/left square
-                        scale = thumbWidth / appWidth;
-                        scaledTopDecor = (int) (scale * contentInsets.top);
-                        int unscaledThumbHeight = (int) (thumbHeight / scale);
-                        mTmpToClipRect.bottom = mTmpToClipRect.top + unscaledThumbHeight;
-                    } else {
-                        // In landscape, we scale the height and clip to the top/left square. We only
-                        // scale the part that is not covered by status bar and the nav bar.
-                        scale = thumbHeight / (appHeight - contentInsets.top - contentInsets.bottom);
-                        scaledTopDecor = (int) (scale * contentInsets.top);
-                        int unscaledThumbWidth = (int) (thumbWidth / scale);
-                        mTmpToClipRect.right = mTmpToClipRect.left + unscaledThumbWidth;
-                        // This removes the navigation bar from the last frame, so it better matches the
-                        // thumbnail. We need to do this explicitly in landscape, because in portrait we
-                        // already crop vertically.
-                        mTmpToClipRect.bottom = mTmpToClipRect.bottom - contentInsets.bottom;
-                    }
+
+                    // Containing frame is in screen space, but we need the clip rect in the
+                    // app space.
+                    mTmpFromClipRect.offsetTo(0, 0);
+                    mTmpToClipRect.offsetTo(0, 0);
+
+                    // Exclude insets region from the target clip.
+                    mTmpToClipRect.inset(contentInsets);
+
+                    // We scale the width and clip to the top/left square
+                    scale = thumbWidth / (appWidth - contentInsets.left - contentInsets.right);
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbHeight = (int) (thumbHeight / scale);
+                    mTmpToClipRect.bottom = mTmpToClipRect.top + unscaledThumbHeight;
 
                     mNextAppTransitionInsets.set(contentInsets);
 
                     Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
-                            computePivot(mTmpRect.left, scale),
-                            computePivot(mTmpRect.top, scale));
+                            computePivot(mTmpRect.left - containingFrame.left, scale),
+                            computePivot(mTmpRect.top - containingFrame.top, scale));
                     Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                     Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
 
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 6452fee..7ec945d 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -302,7 +302,12 @@
     void setWindowsExiting(boolean exiting) {
         for (int i = allAppWindows.size() - 1; i >= 0; i--) {
             WindowState win = allAppWindows.get(i);
-            win.mExiting = exiting;
+            // If the app already requested to remove its window, we don't modify
+            // its exiting state. Otherwise the stale window won't get removed on
+            // exit and could cause focus to be given to the wrong window.
+            if (!(win.mRemoveOnExit && win.mExiting)) {
+                win.mExiting = exiting;
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 5f97478..1bfdcce 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -22,6 +22,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.graphics.Rect;
 import android.util.ArrayMap;
@@ -50,13 +51,15 @@
         private final Rect mFrom;
         private final Rect mTo;
         private final Rect mTmpRect;
+        private final boolean mMoveToFullScreen;
 
-        BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to) {
+        BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to, boolean moveToFullScreen) {
             super();
             mTarget = target;
             mFrom = from;
             mTo = to;
             mTmpRect = new Rect();
+            mMoveToFullScreen = moveToFullScreen;
             addUpdateListener(this);
             addListener(this);
         }
@@ -88,6 +91,9 @@
         @Override
         public void onAnimationEnd(Animator animation) {
             finishAnimation();
+            if (mMoveToFullScreen) {
+                mTarget.moveToFullscreen();
+            }
         }
 
         @Override
@@ -125,14 +131,25 @@
          * necessary cleanup.
          */
         void finishBoundsAnimation();
+
+        void moveToFullscreen();
+
+        void getFullScreenBounds(Rect bounds);
     }
 
-    void animateBounds(AnimateBoundsUser target, Rect from, Rect to) {
+    void animateBounds(final AnimateBoundsUser target, Rect from, Rect to) {
+        boolean moveToFullscreen = false;
+        if (to == null) {
+            to = new Rect();
+            target.getFullScreenBounds(to);
+            moveToFullscreen = true;
+        }
+
         final BoundsAnimator existing = mRunningAnimations.get(target);
         if (existing != null) {
             existing.cancel();
         }
-        BoundsAnimator animator = new BoundsAnimator(target, from, to);
+        BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen);
         mRunningAnimations.put(target, animator);
         animator.setFloatValues(0f, 1f);
         animator.setDuration(DEFAULT_APP_TRANSITION_DURATION);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c542ff6..a06d3fc 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -288,11 +289,9 @@
         if (displayContent != null) {
             displayContent.getLogicalDisplayRect(mTmpRect);
             rotation = displayContent.getDisplayInfo().rotation;
-            if (bounds == null) {
+            mFullscreen = bounds == null;
+            if (mFullscreen) {
                 bounds = mTmpRect;
-                mFullscreen = true;
-            } else {
-                mFullscreen = mTmpRect.equals(bounds);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index e6fa837..40ca1c5 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -255,11 +255,9 @@
         if (mDisplayContent != null) {
             mDisplayContent.getLogicalDisplayRect(mTmpRect);
             rotation = mDisplayContent.getDisplayInfo().rotation;
-            if (bounds == null) {
+            mFullscreen = bounds == null;
+            if (mFullscreen) {
                 bounds = mTmpRect;
-                mFullscreen = true;
-            } else {
-                mFullscreen = mTmpRect.equals(bounds);
             }
         }
 
@@ -586,8 +584,9 @@
         }
     }
 
-    void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibilityOnKeyguardShowing) {
-        if (!StackId.isResizeableByDockedStack(mStackId) || mDisplayContent == null) {
+    void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibility) {
+        if ((mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId))
+                || mDisplayContent == null) {
             outBounds.set(mBounds);
             return;
         }
@@ -598,7 +597,7 @@
             throw new IllegalStateException(
                     "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
         }
-        if (!dockedStack.isVisibleLocked(ignoreVisibilityOnKeyguardShowing)) {
+        if (!ignoreVisibility && !dockedStack.isVisibleLocked()) {
             // The docked stack is being dismissed, but we caught before it finished being
             // dismissed. In that case we want to treat it as if it is not occupying any space and
             // let others occupy the whole display.
@@ -616,8 +615,7 @@
 
         mDisplayContent.getLogicalDisplayRect(mTmpRect);
         dockedStack.getRawBounds(mTmpRect2);
-        final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP
-                || dockedSide == DOCKED_LEFT;
+        final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
         getStackDockedModeBounds(mTmpRect, outBounds, mStackId, mTmpRect2,
                 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
 
@@ -722,6 +720,19 @@
         }
     }
 
+    void resetDockedStackToMiddle() {
+        if (mStackId != DOCKED_STACK_ID) {
+            throw new IllegalStateException("Not a docked stack=" + this);
+        }
+
+        mService.mDockedStackCreateBounds = null;
+
+        final Rect bounds = new Rect();
+        getStackDockedModeBoundsLocked(bounds, true /*ignoreVisibility*/);
+        mService.mH.obtainMessage(RESIZE_STACK, DOCKED_STACK_ID,
+                1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
+    }
+
     void detachDisplay() {
         EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
 
@@ -865,14 +876,14 @@
         final int orientation = mService.mCurConfiguration.orientation;
         if (orientation == Configuration.ORIENTATION_PORTRAIT) {
             // Portrait mode, docked either at the top or the bottom.
-            if (bounds.top - mTmpRect.top < mTmpRect.bottom - bounds.bottom) {
+            if (bounds.top - mTmpRect.top <= mTmpRect.bottom - bounds.bottom) {
                 return DOCKED_TOP;
             } else {
                 return DOCKED_BOTTOM;
             }
         } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
             // Landscape mode, docked either on the left or on the right.
-            if (bounds.left - mTmpRect.left < mTmpRect.right - bounds.right) {
+            if (bounds.left - mTmpRect.left <= mTmpRect.right - bounds.right) {
                 return DOCKED_LEFT;
             } else {
                 return DOCKED_RIGHT;
@@ -883,17 +894,10 @@
     }
 
     boolean isVisibleLocked() {
-        return isVisibleLocked(false);
-    }
-
-    boolean isVisibleLocked(boolean ignoreVisibilityOnKeyguardShowing) {
         final boolean keyguardOn = mService.mPolicy.isKeyguardShowingOrOccluded();
         if (keyguardOn && !StackId.isAllowedOverLockscreen(mStackId)) {
             // The keyguard is showing and the stack shouldn't show on top of the keyguard.
-            // We return false for visibility except in cases where the caller wants us to return
-            // true for visibility when the keyguard is showing. One example, is if the docked
-            // is being resized due to orientation while the keyguard is on.
-            return ignoreVisibilityOnKeyguardShowing;
+            return false;
         }
 
         for (int i = mTasks.size() - 1; i >= 0; i--) {
@@ -934,4 +938,18 @@
             }
         }
     }
+
+    @Override
+    public void moveToFullscreen() {
+        try {
+            mService.mActivityManager.moveTasksToFullscreenStack(mStackId, true);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void getFullScreenBounds(Rect bounds) {
+        getDisplayContent().getContentRect(bounds);
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index 2cf2618..d843a8c 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -16,12 +16,14 @@
 
 package com.android.server.wm;
 
-import android.app.ActivityManager.StackId;
 import android.util.Slog;
 import android.view.Display;
 
 import java.io.PrintWriter;
+import java.util.ArrayDeque;
 
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -55,10 +57,10 @@
     }
 
     private int mHighestApplicationLayer = 0;
-    private WindowState mPinnedWindow = null;
-    private WindowState mDockedWindow = null;
+    private ArrayDeque<WindowState> mPinnedWindows = new ArrayDeque<>();
+    private ArrayDeque<WindowState> mDockedWindows = new ArrayDeque<>();
     private WindowState mDockDivider = null;
-    private WindowState mReplacingWindow = null;
+    private ArrayDeque<WindowState> mReplacingWindows = new ArrayDeque<>();
 
     final void assignLayersLocked(WindowList windows) {
         if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based on windows=" + windows,
@@ -169,43 +171,54 @@
 
     private void clear() {
         mHighestApplicationLayer = 0;
-        mPinnedWindow = null;
-        mDockedWindow = null;
+        mPinnedWindows.clear();
+        mDockedWindows.clear();
+        mReplacingWindows.clear();
         mDockDivider = null;
     }
 
     private void collectSpecialWindows(WindowState w) {
         if (w.mAttrs.type == TYPE_DOCK_DIVIDER) {
             mDockDivider = w;
-        } else {
-            final TaskStack stack = w.getStack();
-            if (stack == null) {
-                return;
-            }
-            if (stack.mStackId == StackId.PINNED_STACK_ID) {
-                mPinnedWindow = w;
-            } else if (stack.mStackId == StackId.DOCKED_STACK_ID) {
-                mDockedWindow = w;
-            }
+            return;
+        }
+        if (w.mWillReplaceWindow) {
+            mReplacingWindows.add(w);
+        }
+        final TaskStack stack = w.getStack();
+        if (stack == null) {
+            return;
+        }
+        if (stack.mStackId == PINNED_STACK_ID) {
+            mPinnedWindows.add(w);
+        } else if (stack.mStackId == DOCKED_STACK_ID) {
+            mDockedWindows.add(w);
         }
     }
 
     private void adjustSpecialWindows() {
         int layer = mHighestApplicationLayer + 1;
-        // For pinned and docked stack window, we want to make them above other windows
-        // also when these windows are animating.
-        layer = assignAndIncreaseLayerIfNeeded(mDockedWindow, layer);
+        // 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);
-        // 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.
-        layer = assignAndIncreaseLayerIfNeeded(mReplacingWindow, layer);
-        layer = assignAndIncreaseLayerIfNeeded(mPinnedWindow, 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.
+        while (!mReplacingWindows.isEmpty()) {
+            layer = assignAndIncreaseLayerIfNeeded(mReplacingWindows.remove(), layer);
+        }
+
+        while (!mPinnedWindows.isEmpty()) {
+            layer = assignAndIncreaseLayerIfNeeded(mPinnedWindows.remove(), layer);
+        }
     }
 
     private int assignAndIncreaseLayerIfNeeded(WindowState win, int layer) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 66aa863..0979cd3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -35,10 +35,10 @@
 
     static final boolean DEBUG_RESIZE = false;
     static final boolean DEBUG = false;
-    static final boolean DEBUG_ADD_REMOVE = true;
+    static final boolean DEBUG_ADD_REMOVE = false;
     static final boolean DEBUG_FOCUS = false;
     static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
-    static final boolean DEBUG_ANIM = true;
+    static final boolean DEBUG_ANIM = false;
     static final boolean DEBUG_KEYGUARD = false;
     static final boolean DEBUG_LAYOUT = false;
     static final boolean DEBUG_LAYERS = false;
@@ -50,7 +50,7 @@
     static final boolean DEBUG_ORIENTATION = false;
     static final boolean DEBUG_APP_ORIENTATION = false;
     static final boolean DEBUG_CONFIGURATION = false;
-    static final boolean DEBUG_APP_TRANSITIONS = true;
+    static final boolean DEBUG_APP_TRANSITIONS = false;
     static final boolean DEBUG_STARTING_WINDOW = false;
     static final boolean DEBUG_WALLPAPER = false;
     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e7aba6d..ae6c89a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -464,6 +464,8 @@
     EmulatorDisplayOverlay mEmulatorDisplayOverlay;
 
     final float[] mTmpFloats = new float[9];
+    final Rect mTmpRect = new Rect();
+    final Rect mTmpRect2 = new Rect();
 
     boolean mDisplayReady;
     boolean mSafeMode;
@@ -2856,6 +2858,9 @@
             WindowStateAnimator winAnimator, int attrChanges, int oldVisibility) {
         result |= !win.isVisibleLw() ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0;
         if (win.mExiting) {
+            Slog.d(TAG, "relayoutVisibleWindow: " + win + " mExiting=true, mRemoveOnExit="
+                    + win.mRemoveOnExit + ", mDestroying=" + win.mDestroying);
+
             winAnimator.cancelExitAnimationForNextAnimationLocked();
             win.mExiting = false;
         }
@@ -2980,9 +2985,7 @@
             final Rect frame = new Rect(0, 0, width, height);
             final Rect insets = new Rect();
             Rect surfaceInsets = null;
-            final boolean fullscreen = win != null && win.isFrameFullscreen(displayInfo);
             final boolean freeform = win != null && win.inFreeformWorkspace();
-            final boolean docked = win != null && win.inDockedWorkspace();
             if (win != null) {
                 // Containing frame will usually cover the whole screen, including dialog windows.
                 // For freeform workspace windows it will not cover the whole screen and it also
@@ -2994,12 +2997,7 @@
                     frame.set(win.mContainingFrame);
                 }
                 surfaceInsets = win.getAttrs().surfaceInsets;
-                if (fullscreen || docked) {
-                    // For fullscreen windows use the window frames and insets to set the thumbnail
-                    // clip. For non-fullscreen windows we use the app display region so the clip
-                    // isn't affected by the window insets.
-                    insets.set(win.mContentInsets);
-                }
+                insets.set(win.mContentInsets);
             }
 
             if (atoken.mLaunchTaskBehind) {
@@ -3013,7 +3011,7 @@
                     + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
             Animation a = mAppTransition.loadAnimation(lp, transit, enter,
                     mCurConfiguration.orientation, frame, insets, surfaceInsets, isVoiceInteraction,
-                    !fullscreen, atoken.mTask.mTaskId);
+                    freeform, atoken.mTask.mTaskId);
             if (a != null) {
                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
                 final int containingWidth = frame.width();
@@ -4702,11 +4700,6 @@
                     }
                     stack.attachDisplayContent(displayContent);
                     displayContent.attachStack(stack, onTop);
-                    moveStackWindowsLocked(displayContent);
-                    final WindowList windows = displayContent.getWindowList();
-                    for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-                        windows.get(winNdx).reportResized();
-                    }
                     if (stack.getRawFullscreen()) {
                         return null;
                     }
@@ -4821,12 +4814,11 @@
         }
     }
 
-    public void getStackDockedModeBounds(
-            int stackId, Rect bounds, boolean ignoreVisibilityOnKeyguardShowing) {
+    public void getStackDockedModeBounds(int stackId, Rect bounds, boolean ignoreVisibility) {
         synchronized (mWindowMap) {
             final TaskStack stack = mStackIdToStack.get(stackId);
             if (stack != null) {
-                stack.getStackDockedModeBoundsLocked(bounds, ignoreVisibilityOnKeyguardShowing);
+                stack.getStackDockedModeBoundsLocked(bounds, ignoreVisibility);
                 return;
             }
             bounds.setEmpty();
@@ -4855,17 +4847,6 @@
         }
     }
 
-    /** Returns true if the input bounds corresponds to the fullscreen bounds the stack is on. */
-    public boolean isFullscreenBounds(int stackId, Rect bounds) {
-        synchronized (mWindowMap) {
-            final TaskStack stack = mStackIdToStack.get(stackId);
-            if (stack == null || bounds == null) {
-                return true;
-            }
-            return stack.isFullscreenBounds(bounds);
-        }
-    }
-
     /**
      * Re-sizes a stack and its containing tasks.
      * @param stackId Id of stack to resize.
@@ -5383,8 +5364,18 @@
             mWindowPlacerLocked.performSurfacePlacement();
 
             // Notify whether the docked stack exists for the current user
-            getDefaultDisplayContentLocked().mDividerControllerLocked
+            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+            displayContent.mDividerControllerLocked
                     .notifyDockedStackExistsChanged(hasDockedTasksForUser(newUserId));
+
+            // If the display is already prepared, update the density.
+            // Otherwise, we'll update it when it's prepared.
+            if (mDisplayReady) {
+                final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
+                final int targetDensity = forcedDensity != 0 ? forcedDensity
+                        : displayContent.mInitialDisplayDensity;
+                setForcedDisplayDensityLocked(displayContent, targetDensity);
+            }
         }
     }
 
@@ -7267,8 +7258,18 @@
         mTaskPositioner = new TaskPositioner(this);
         mTaskPositioner.register(display);
         mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+        // We need to grab the touch focus so that the touch events during the
+        // resizing/scrolling are not sent to the app. 'win' is the main window
+        // of the app, it may not have focus since there might be other windows
+        // on top (eg. a dialog window).
+        WindowState transferFocusFromWin = win;
+        if (mCurrentFocus != null && mCurrentFocus != win
+                && mCurrentFocus.mAppToken == win.mAppToken) {
+            transferFocusFromWin = mCurrentFocus;
+        }
         if (!mInputManager.transferTouchFocus(
-                win.mInputChannel, mTaskPositioner.mServerChannel)) {
+                transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
             Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
             mTaskPositioner.unregister();
             mTaskPositioner = null;
@@ -8109,7 +8110,9 @@
                         final WindowState imeWin = mInputMethodWindow;
                         final TaskStack focusedStack =
                                 mCurrentFocus != null ? mCurrentFocus.getStack() : null;
-                        if (imeWin != null && focusedStack != null && imeWin.isVisibleNow()
+                        if (imeWin != null && imeWin.isVisibleNow()
+                                && isStackVisibleLocked(DOCKED_STACK_ID)
+                                && focusedStack != null
                                 && focusedStack.getDockSide() == DOCKED_BOTTOM){
                             final ArrayList<TaskStack> stacks = displayContent.getStacks();
                             for (int i = stacks.size() - 1; i >= 0; --i) {
@@ -8368,21 +8371,9 @@
         }
 
         // Display density.
-        String densityStr = Settings.Global.getString(mContext.getContentResolver(),
-                Settings.Global.DISPLAY_DENSITY_FORCED);
-        if (densityStr == null || densityStr.length() == 0) {
-            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
-        }
-        if (densityStr != null && densityStr.length() > 0) {
-            int density;
-            try {
-                density = Integer.parseInt(densityStr);
-                if (displayContent.mBaseDisplayDensity != density) {
-                    Slog.i(TAG_WM, "FORCED DISPLAY DENSITY: " + density);
-                    displayContent.mBaseDisplayDensity = density;
-                }
-            } catch (NumberFormatException ex) {
-            }
+        final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
+        if (density != 0) {
+            displayContent.mBaseDisplayDensity = density;
         }
 
         // Display scaling mode.
@@ -8468,8 +8459,9 @@
                 final DisplayContent displayContent = getDisplayContentLocked(displayId);
                 if (displayContent != null) {
                     setForcedDisplayDensityLocked(displayContent, density);
-                    Settings.Global.putString(mContext.getContentResolver(),
-                            Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                            Settings.Secure.DISPLAY_DENSITY_FORCED,
+                            Integer.toString(density), mCurrentUserId);
                 }
             }
         } finally {
@@ -8477,13 +8469,6 @@
         }
     }
 
-    // displayContent must not be null
-    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
-        Slog.i(TAG_WM, "Using new display density: " + density);
-        displayContent.mBaseDisplayDensity = density;
-        reconfigureDisplayLocked(displayContent);
-    }
-
     @Override
     public void clearForcedDisplayDensity(int displayId) {
         if (mContext.checkCallingOrSelfPermission(
@@ -8502,8 +8487,8 @@
                 if (displayContent != null) {
                     setForcedDisplayDensityLocked(displayContent,
                             displayContent.mInitialDisplayDensity);
-                    Settings.Global.putString(mContext.getContentResolver(),
-                            Settings.Global.DISPLAY_DENSITY_FORCED, "");
+                    Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                            Settings.Secure.DISPLAY_DENSITY_FORCED, "", mCurrentUserId);
                 }
             }
         } finally {
@@ -8511,6 +8496,38 @@
         }
     }
 
+    /**
+     * @param userId the ID of the user
+     * @return the forced display density for the specified user, if set, or
+     *         {@code 0} if not set
+     */
+    private int getForcedDisplayDensityForUserLocked(int userId) {
+        String densityStr = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+                Settings.Secure.DISPLAY_DENSITY_FORCED, userId);
+        if (densityStr == null || densityStr.length() == 0) {
+            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
+        }
+        if (densityStr != null && densityStr.length() > 0) {
+            try {
+                return Integer.parseInt(densityStr);
+            } catch (NumberFormatException ex) {
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Forces the given display to the use the specified density.
+     *
+     * @param displayContent the display to modify
+     * @param density the density in DPI to use
+     */
+    private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
+            int density) {
+        displayContent.mBaseDisplayDensity = density;
+        reconfigureDisplayLocked(displayContent);
+    }
+
     // displayContent must not be null
     private void reconfigureDisplayLocked(DisplayContent displayContent) {
         // TODO: Multidisplay: for now only use with default display.
@@ -10389,6 +10406,34 @@
         }
     }
 
+    @Override
+    public void getStableInsets(Rect outInsets) throws RemoteException {
+        synchronized (mWindowMap) {
+            getStableInsetsLocked(outInsets);
+        }
+    }
+
+    private void getStableInsetsLocked(Rect outInsets) {
+        final DisplayInfo di = getDefaultDisplayInfoLocked();
+        mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
+    }
+
+    /**
+     * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
+     * inset areas.
+     *
+     * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
+     */
+    public void subtractStableInsets(Rect inOutBounds) {
+        synchronized (mWindowMap) {
+            getStableInsetsLocked(mTmpRect2);
+            final DisplayInfo di = getDefaultDisplayInfoLocked();
+            mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
+            mTmpRect.inset(mTmpRect2);
+            inOutBounds.intersect(mTmpRect);
+        }
+    }
+
     private final class LocalService extends WindowManagerInternal {
         @Override
         public void requestTraversalFromDisplayManager() {
@@ -10589,5 +10634,12 @@
                 return WindowManagerService.this.isStackVisibleLocked(stackId);
             }
         }
+
+        @Override
+        public boolean isDockedDividerResizing() {
+            synchronized (mWindowMap) {
+                return getDefaultDisplayContentLocked().getDockedDividerController().isResizing();
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4a9b356..880514c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -16,8 +16,6 @@
 
 package com.android.server.wm;
 
-import com.android.server.input.InputWindowHandle;
-
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.content.Context;
@@ -53,10 +51,13 @@
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 
+import com.android.server.input.InputWindowHandle;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
 import static android.app.ActivityManager.StackId;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
@@ -75,8 +76,8 @@
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
@@ -121,6 +122,8 @@
     static final int DRAG_RESIZE_MODE_FREEFORM = 0;
     static final int DRAG_RESIZE_MODE_DOCKED_DIVIDER = 1;
 
+    static final boolean DEBUG_DISABLE_SAVING_SURFACES = false;
+
     final WindowManagerService mService;
     final WindowManagerPolicy mPolicy;
     final Context mContext;
@@ -1257,8 +1260,11 @@
      * it may obscure windows behind it.
      */
     boolean isOpaqueDrawn() {
-        return (mAttrs.format == PixelFormat.OPAQUE
-                        || mAttrs.type == TYPE_WALLPAPER)
+        // When there is keyguard, wallpaper could be placed over the secure app
+        // window but invisible. We need to check wallpaper visibility explicitly
+        // to determine if it's occluding apps.
+        return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE)
+                || (mIsWallpaper && mWallpaperVisible))
                 && isDrawnLw() && mWinAnimator.mAnimation == null
                 && (mAppToken == null || mAppToken.mAppAnimator.animation == null);
     }
@@ -1606,6 +1612,14 @@
                             win.mAppToken.appDied = true;
                         }
                         mService.removeWindowLocked(win);
+                        if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
+                            // The owner of the docked divider died :( We reset the docked stack,
+                            // just in case they have the divider at an unstable position.
+                            final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
+                            if (stack != null) {
+                                stack.resetDockedStackToMiddle();
+                            }
+                        }
                     } else if (mHasSurface) {
                         Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
                         mService.removeWindowLocked(WindowState.this);
@@ -1798,10 +1812,6 @@
             return false;
         }
 
-        if (isChildWindow()) {
-            return false;
-        }
-
         Task task = getTask();
         if (task == null || task.inHomeStack()) {
             // Don't save surfaces for home stack apps. These usually resume and draw
@@ -1815,6 +1825,10 @@
             return false;
         }
 
+        if (DEBUG_DISABLE_SAVING_SURFACES) {
+            return false;
+        }
+
         return mAppToken.shouldSaveSurface();
     }
 
@@ -2131,7 +2145,8 @@
         // background.
         return (mDisplayContent.mDividerControllerLocked.isResizing()
                         || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
-                !task.inFreeformWorkspace() && !task.isFullscreen();
+                !task.inFreeformWorkspace();
+
     }
 
     void setDragResizing() {
@@ -2325,6 +2340,12 @@
         if (mDrawLock != null) {
             pw.print(prefix); pw.println("mDrawLock=" + mDrawLock);
         }
+        if (isDragResizing()) {
+            pw.print(prefix); pw.println("isDragResizing=" + isDragResizing());
+        }
+        if (computeDragResizing()) {
+            pw.print(prefix); pw.println("computeDragResizing=" + computeDragResizing());
+        }
     }
 
     String makeInputChannelName() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index e904ad5..c7c9cbf 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -572,7 +572,8 @@
     WindowSurfaceController createSurfaceLocked() {
         final WindowState w = mWin;
         if (w.hasSavedSurface()) {
-            Slog.i(TAG, "***** createSurface: " + this + ": called when we had a saved surface");
+            if (DEBUG_ANIM) Slog.i(TAG,
+                    "createSurface: " + this + ": called when we had a saved surface");
             w.restoreSavedSurface();
             return mSurfaceController;
         }
@@ -1225,10 +1226,11 @@
         calculateSurfaceBounds(w, w.getAttrs());
 
         mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, recoveringMemory);
+
+        mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale, mDtDx * w.mVScale,
+                mDsDy * w.mHScale, mDtDy * w.mVScale, recoveringMemory);
         mSurfaceResized = mSurfaceController.setSizeInTransaction(
                 mTmpSize.width(), mTmpSize.height(),
-                mDsDx * w.mHScale, mDtDx * w.mVScale,
-                mDsDy * w.mHScale, mDtDy * w.mVScale,
                 recoveringMemory);
 
         if (mSurfaceResized) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 5674ca2..3219bfe 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -130,7 +130,7 @@
 
     void destroyInTransaction() {
         //        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
-        Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(3));
+        Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(4));
         //        }
         try {
             mSurfaceControl.destroy();
@@ -190,8 +190,27 @@
         }
     }
 
-    boolean setSizeInTransaction(int width, int height, float dsdx, float dtdx, float dsdy, float dtdy,
+    void setMatrixInTransaction(float dsdx, float dtdx, float dsdy, float dtdy,
             boolean recoveringMemory) {
+        try {
+            if (SHOW_TRANSACTIONS) logSurface(
+                    "MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
+            mSurfaceControl.setMatrix(
+                    dsdx, dtdx, dsdy, dtdy);
+        } catch (RuntimeException e) {
+            // If something goes wrong with the surface (such
+            // as running out of memory), don't take down the
+            // entire system.
+            Slog.e(TAG, "Error setting matrix on surface surface" + title
+                    + " MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
+            if (!recoveringMemory) {
+                mAnimator.reclaimSomeSurfaceMemory("matrix", true);
+            }
+        }
+        return;
+    }
+
+    boolean setSizeInTransaction(int width, int height, boolean recoveringMemory) {
         final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height;
         if (surfaceResized) {
             mSurfaceW = width;
@@ -201,8 +220,6 @@
                 if (SHOW_TRANSACTIONS) logSurface(
                         "SIZE " + width + "x" + height, null);
                 mSurfaceControl.setSize(width, height);
-                mSurfaceControl.setMatrix(
-                        dsdx, dtdx, dsdy, dtdy);
             } catch (RuntimeException e) {
                 // If something goes wrong with the surface (such
                 // as running out of memory), don't take down the
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index d1d4721..4e1b644 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -647,14 +647,6 @@
 
             for (int i = windows.size() - 1; i >= 0; i--) {
                 WindowState w = windows.get(i);
-                Task task = w.getTask();
-                if (task == null && w.getDisplayContent().getHomeStack() == null
-                        && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) {
-                    // TODO: Understand what the use case is here and see if the conditions can be
-                    // simplified.
-                    continue;
-                }
-
                 final boolean obscuredChanged = w.mObscured != mObscured;
 
                 // Update effect.
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index d1b8648..bb571c3 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -28,6 +28,7 @@
     $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_SystemServer.cpp \
     $(LOCAL_REL_DIR)/com_android_server_tv_TvInputHal.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_vr_VrManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_UsbDeviceManager.cpp \
     $(LOCAL_REL_DIR)/com_android_server_UsbMidiDevice.cpp \
     $(LOCAL_REL_DIR)/com_android_server_UsbHostManager.cpp \
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index 5cbb277..246ab0d 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -40,6 +40,8 @@
 #include <linux/android_alarm.h>
 #include <linux/rtc.h>
 
+#include <memory>
+
 namespace android {
 
 static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1;
@@ -323,14 +325,14 @@
 
 static int wall_clock_rtc()
 {
-    DIR *dir = opendir(rtc_sysfs);
-    if (!dir) {
+    std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(rtc_sysfs), closedir);
+    if (!dir.get()) {
         ALOGE("failed to open %s: %s", rtc_sysfs, strerror(errno));
         return -1;
     }
 
     struct dirent *dirent;
-    while (errno = 0, dirent = readdir(dir)) {
+    while (errno = 0, dirent = readdir(dir.get())) {
         unsigned int rtc_id;
         int matched = sscanf(dirent->d_name, "rtc%u", &rtc_id);
 
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 0c85a15..e75775f 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -537,11 +537,11 @@
     method_reportMeasurementData = env->GetMethodID(
             clazz,
             "reportMeasurementData",
-            "(Landroid/location/GpsMeasurementsEvent;)V");
+            "(Landroid/location/GnssMeasurementsEvent;)V");
     method_reportNavigationMessages = env->GetMethodID(
             clazz,
             "reportNavigationMessage",
-            "(Landroid/location/GpsNavigationMessageEvent;)V");
+            "(Landroid/location/GnssNavigationMessageEvent;)V");
 
     err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
     if (err == 0) {
@@ -974,7 +974,7 @@
 
     GpsClock* clock = reinterpret_cast<GpsClock*>(data);
 
-    jclass gpsClockClass = env->FindClass("android/location/GpsClock");
+    jclass gpsClockClass = env->FindClass("android/location/GnssClock");
     jmethodID gpsClockCtor = env->GetMethodID(gpsClockClass, "<init>", "()V");
 
     jobject gpsClockObject = env->NewObject(gpsClockClass, gpsClockCtor);
@@ -1049,264 +1049,264 @@
     const char* floatSignature = "(F)V";
     const char* doubleSignature = "(D)V";
 
-    jclass gpsMeasurementClass = env->FindClass("android/location/GpsMeasurement");
-    jmethodID gpsMeasurementCtor = env->GetMethodID(gpsMeasurementClass, "<init>", "()V");
+    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
+    jmethodID gnssMeasurementCtor = env->GetMethodID(gnssMeasurementClass, "<init>", "()V");
     GpsMeasurement* measurement = reinterpret_cast<GpsMeasurement*>(data);
 
-    jobject gpsMeasurementObject = env->NewObject(gpsMeasurementClass, gpsMeasurementCtor);
+    jobject gnssMeasurementObject = env->NewObject(gnssMeasurementClass, gnssMeasurementCtor);
     GpsMeasurementFlags flags = measurement->flags;
 
-    jmethodID prnSetterMethod = env->GetMethodID(gpsMeasurementClass, "setPrn", byteSignature);
-    env->CallVoidMethod(gpsMeasurementObject, prnSetterMethod, measurement->prn);
+    jmethodID prnSetterMethod = env->GetMethodID(gnssMeasurementClass, "setPrn", byteSignature);
+    env->CallVoidMethod(gnssMeasurementObject, prnSetterMethod, measurement->prn);
 
     jmethodID timeOffsetSetterMethod =
-            env->GetMethodID(gpsMeasurementClass, "setTimeOffsetInNs", doubleSignature);
+            env->GetMethodID(gnssMeasurementClass, "setTimeOffsetInNs", doubleSignature);
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             timeOffsetSetterMethod,
             measurement->time_offset_ns);
 
-    jmethodID stateSetterMethod = env->GetMethodID(gpsMeasurementClass, "setState", shortSignature);
-    env->CallVoidMethod(gpsMeasurementObject, stateSetterMethod, measurement->state);
+    jmethodID stateSetterMethod = env->GetMethodID(gnssMeasurementClass, "setState", shortSignature);
+    env->CallVoidMethod(gnssMeasurementObject, stateSetterMethod, measurement->state);
 
     jmethodID receivedGpsTowSetterMethod =
-            env->GetMethodID(gpsMeasurementClass, "setReceivedGpsTowInNs", longSignature);
+            env->GetMethodID(gnssMeasurementClass, "setReceivedGpsTowInNs", longSignature);
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             receivedGpsTowSetterMethod,
             measurement->received_gps_tow_ns);
 
     jmethodID receivedGpsTowUncertaintySetterMethod = env->GetMethodID(
-            gpsMeasurementClass,
+            gnssMeasurementClass,
             "setReceivedGpsTowUncertaintyInNs",
             longSignature);
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             receivedGpsTowUncertaintySetterMethod,
             measurement->received_gps_tow_uncertainty_ns);
 
     jmethodID cn0SetterMethod =
-            env->GetMethodID(gpsMeasurementClass, "setCn0InDbHz", doubleSignature);
-    env->CallVoidMethod(gpsMeasurementObject, cn0SetterMethod, measurement->c_n0_dbhz);
+            env->GetMethodID(gnssMeasurementClass, "setCn0InDbHz", doubleSignature);
+    env->CallVoidMethod(gnssMeasurementObject, cn0SetterMethod, measurement->c_n0_dbhz);
 
     jmethodID pseudorangeRateSetterMethod = env->GetMethodID(
-            gpsMeasurementClass,
+            gnssMeasurementClass,
             "setPseudorangeRateInMetersPerSec",
             doubleSignature);
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             pseudorangeRateSetterMethod,
             measurement->pseudorange_rate_mps);
 
     jmethodID pseudorangeRateUncertaintySetterMethod = env->GetMethodID(
-            gpsMeasurementClass,
+            gnssMeasurementClass,
             "setPseudorangeRateUncertaintyInMetersPerSec",
             doubleSignature);
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             pseudorangeRateUncertaintySetterMethod,
             measurement->pseudorange_rate_uncertainty_mps);
 
     jmethodID accumulatedDeltaRangeStateSetterMethod =
-            env->GetMethodID(gpsMeasurementClass, "setAccumulatedDeltaRangeState", shortSignature);
+            env->GetMethodID(gnssMeasurementClass, "setAccumulatedDeltaRangeState", shortSignature);
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             accumulatedDeltaRangeStateSetterMethod,
             measurement->accumulated_delta_range_state);
 
     jmethodID accumulatedDeltaRangeSetterMethod = env->GetMethodID(
-            gpsMeasurementClass,
+            gnssMeasurementClass,
             "setAccumulatedDeltaRangeInMeters",
             doubleSignature);
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             accumulatedDeltaRangeSetterMethod,
             measurement->accumulated_delta_range_m);
 
     jmethodID accumulatedDeltaRangeUncertaintySetterMethod = env->GetMethodID(
-            gpsMeasurementClass,
+            gnssMeasurementClass,
             "setAccumulatedDeltaRangeUncertaintyInMeters",
             doubleSignature);
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             accumulatedDeltaRangeUncertaintySetterMethod,
             measurement->accumulated_delta_range_uncertainty_m);
 
     if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setPseudorangeInMeters", doubleSignature);
-        env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->pseudorange_m);
+                env->GetMethodID(gnssMeasurementClass, "setPseudorangeInMeters", doubleSignature);
+        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->pseudorange_m);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY) {
         jmethodID setterMethod = env->GetMethodID(
-                gpsMeasurementClass,
+                gnssMeasurementClass,
                 "setPseudorangeUncertaintyInMeters",
                 doubleSignature);
         env->CallVoidMethod(
-                gpsMeasurementObject,
+                gnssMeasurementObject,
                 setterMethod,
                 measurement->pseudorange_uncertainty_m);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setCodePhaseInChips", doubleSignature);
-        env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->code_phase_chips);
+                env->GetMethodID(gnssMeasurementClass, "setCodePhaseInChips", doubleSignature);
+        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->code_phase_chips);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY) {
         jmethodID setterMethod = env->GetMethodID(
-                gpsMeasurementClass,
+                gnssMeasurementClass,
                 "setCodePhaseUncertaintyInChips",
                 doubleSignature);
         env->CallVoidMethod(
-                gpsMeasurementObject,
+                gnssMeasurementObject,
                 setterMethod,
                 measurement->code_phase_uncertainty_chips);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setCarrierFrequencyInHz", floatSignature);
+                env->GetMethodID(gnssMeasurementClass, "setCarrierFrequencyInHz", floatSignature);
         env->CallVoidMethod(
-                gpsMeasurementObject,
+                gnssMeasurementObject,
                 setterMethod,
                 measurement->carrier_frequency_hz);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_CARRIER_CYCLES) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setCarrierCycles", longSignature);
-        env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->carrier_cycles);
+                env->GetMethodID(gnssMeasurementClass, "setCarrierCycles", longSignature);
+        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->carrier_cycles);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setCarrierPhase", doubleSignature);
-        env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->carrier_phase);
+                env->GetMethodID(gnssMeasurementClass, "setCarrierPhase", doubleSignature);
+        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->carrier_phase);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
         jmethodID setterMethod = env->GetMethodID(
-                gpsMeasurementClass,
+                gnssMeasurementClass,
                 "setCarrierPhaseUncertainty",
                 doubleSignature);
         env->CallVoidMethod(
-                gpsMeasurementObject,
+                gnssMeasurementObject,
                 setterMethod,
                 measurement->carrier_phase_uncertainty);
     }
 
     jmethodID lossOfLockSetterMethod =
-            env->GetMethodID(gpsMeasurementClass, "setLossOfLock", byteSignature);
-    env->CallVoidMethod(gpsMeasurementObject, lossOfLockSetterMethod, measurement->loss_of_lock);
+            env->GetMethodID(gnssMeasurementClass, "setLossOfLock", byteSignature);
+    env->CallVoidMethod(gnssMeasurementObject, lossOfLockSetterMethod, measurement->loss_of_lock);
 
     if (flags & GPS_MEASUREMENT_HAS_BIT_NUMBER) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setBitNumber", intSignature);
-        env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->bit_number);
+                env->GetMethodID(gnssMeasurementClass, "setBitNumber", intSignature);
+        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->bit_number);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setTimeFromLastBitInMs", shortSignature);
+                env->GetMethodID(gnssMeasurementClass, "setTimeFromLastBitInMs", shortSignature);
         env->CallVoidMethod(
-                gpsMeasurementObject,
+                gnssMeasurementObject,
                 setterMethod,
                 measurement->time_from_last_bit_ms);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setDopplerShiftInHz", doubleSignature);
-        env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->doppler_shift_hz);
+                env->GetMethodID(gnssMeasurementClass, "setDopplerShiftInHz", doubleSignature);
+        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->doppler_shift_hz);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY) {
         jmethodID setterMethod = env->GetMethodID(
-                gpsMeasurementClass,
+                gnssMeasurementClass,
                 "setDopplerShiftUncertaintyInHz",
                 doubleSignature);
         env->CallVoidMethod(
-                gpsMeasurementObject,
+                gnssMeasurementObject,
                 setterMethod,
                 measurement->doppler_shift_uncertainty_hz);
     }
 
     jmethodID multipathIndicatorSetterMethod =
-            env->GetMethodID(gpsMeasurementClass, "setMultipathIndicator", byteSignature);
+            env->GetMethodID(gnssMeasurementClass, "setMultipathIndicator", byteSignature);
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             multipathIndicatorSetterMethod,
             measurement->multipath_indicator);
 
     if (flags & GPS_MEASUREMENT_HAS_SNR) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setSnrInDb", doubleSignature);
-        env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->snr_db);
+                env->GetMethodID(gnssMeasurementClass, "setSnrInDb", doubleSignature);
+        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->snr_db);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_ELEVATION) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setElevationInDeg", doubleSignature);
-        env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->elevation_deg);
+                env->GetMethodID(gnssMeasurementClass, "setElevationInDeg", doubleSignature);
+        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->elevation_deg);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setElevationUncertaintyInDeg", doubleSignature);
+                env->GetMethodID(gnssMeasurementClass, "setElevationUncertaintyInDeg", doubleSignature);
         env->CallVoidMethod(
-                gpsMeasurementObject,
+                gnssMeasurementObject,
                 setterMethod,
                 measurement->elevation_uncertainty_deg);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_AZIMUTH) {
         jmethodID setterMethod =
-                env->GetMethodID(gpsMeasurementClass, "setAzimuthInDeg", doubleSignature);
-        env->CallVoidMethod(gpsMeasurementObject, setterMethod, measurement->azimuth_deg);
+                env->GetMethodID(gnssMeasurementClass, "setAzimuthInDeg", doubleSignature);
+        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->azimuth_deg);
     }
 
     if (flags & GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY) {
         jmethodID setterMethod = env->GetMethodID(
-                gpsMeasurementClass,
+                gnssMeasurementClass,
                 "setAzimuthUncertaintyInDeg",
                 doubleSignature);
         env->CallVoidMethod(
-                gpsMeasurementObject,
+                gnssMeasurementObject,
                 setterMethod,
                 measurement->azimuth_uncertainty_deg);
     }
 
-    jmethodID usedInFixSetterMethod = env->GetMethodID(gpsMeasurementClass, "setUsedInFix", "(Z)V");
+    jmethodID usedInFixSetterMethod = env->GetMethodID(gnssMeasurementClass, "setUsedInFix", "(Z)V");
     env->CallVoidMethod(
-            gpsMeasurementObject,
+            gnssMeasurementObject,
             usedInFixSetterMethod,
             (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
 
     if (size == sizeof(GpsMeasurement)) {
       jmethodID setterMethod =
-          env->GetMethodID(gpsMeasurementClass,
+          env->GetMethodID(gnssMeasurementClass,
                            "setPseudorangeRateCarrierInMetersPerSec",
                            doubleSignature);
       env->CallVoidMethod(
-          gpsMeasurementObject,
+          gnssMeasurementObject,
           setterMethod,
           measurement->pseudorange_rate_carrier_mps);
 
       setterMethod =
-          env->GetMethodID(gpsMeasurementClass,
+          env->GetMethodID(gnssMeasurementClass,
                            "setPseudorangeRateCarrierUncertaintyInMetersPerSec",
                            doubleSignature);
       env->CallVoidMethod(
-          gpsMeasurementObject,
+          gnssMeasurementObject,
           setterMethod,
           measurement->pseudorange_rate_carrier_uncertainty_mps);
     }
 
-    env->DeleteLocalRef(gpsMeasurementClass);
-    return gpsMeasurementObject;
+    env->DeleteLocalRef(gnssMeasurementClass);
+    return gnssMeasurementObject;
 }
 
 /**
@@ -1321,23 +1321,23 @@
         return NULL;
     }
 
-    jclass gpsMeasurementClass = env->FindClass("android/location/GpsMeasurement");
-    jobjectArray gpsMeasurementArray = env->NewObjectArray(
+    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
+    jobjectArray gnssMeasurementArray = env->NewObjectArray(
             measurementCount,
-            gpsMeasurementClass,
+            gnssMeasurementClass,
             NULL /* initialElement */);
 
     for (uint16_t i = 0; i < measurementCount; ++i) {
-        jobject gpsMeasurement = translate_gps_measurement(
+        jobject gnssMeasurement = translate_gps_measurement(
             env,
             &(gps_data->measurements[i]),
             sizeof(gps_data->measurements[0]));
-        env->SetObjectArrayElement(gpsMeasurementArray, i, gpsMeasurement);
-        env->DeleteLocalRef(gpsMeasurement);
+        env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
+        env->DeleteLocalRef(gnssMeasurement);
     }
 
-    env->DeleteLocalRef(gpsMeasurementClass);
-    return gpsMeasurementArray;
+    env->DeleteLocalRef(gnssMeasurementClass);
+    return gnssMeasurementArray;
 }
 
 static void measurement_callback(GpsData* data) {
@@ -1360,25 +1360,25 @@
         gpsClock = translate_gps_clock(env, &data->clock, sizeof(GpsClock_v1));
         measurementArray = translate_gps_measurements<GpsData_v1>(env, data);
     }
-    jclass gpsMeasurementsEventClass = env->FindClass("android/location/GpsMeasurementsEvent");
-    jmethodID gpsMeasurementsEventCtor = env->GetMethodID(
-        gpsMeasurementsEventClass,
+    jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent");
+    jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
+        gnssMeasurementsEventClass,
         "<init>",
-        "(Landroid/location/GpsClock;[Landroid/location/GpsMeasurement;)V");
+        "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
 
-    jobject gpsMeasurementsEvent = env->NewObject(
-        gpsMeasurementsEventClass,
-        gpsMeasurementsEventCtor,
+    jobject gnssMeasurementsEvent = env->NewObject(
+        gnssMeasurementsEventClass,
+        gnssMeasurementsEventCtor,
         gpsClock,
         measurementArray);
 
-    env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gpsMeasurementsEvent);
+    env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gnssMeasurementsEvent);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 
     env->DeleteLocalRef(gpsClock);
     env->DeleteLocalRef(measurementArray);
-    env->DeleteLocalRef(gpsMeasurementsEventClass);
-    env->DeleteLocalRef(gpsMeasurementsEvent);
+    env->DeleteLocalRef(gnssMeasurementsEventClass);
+    env->DeleteLocalRef(gnssMeasurementsEvent);
 }
 
 GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
@@ -1432,7 +1432,7 @@
         return NULL;
     }
 
-    jclass navigationMessageClass = env->FindClass("android/location/GpsNavigationMessage");
+    jclass navigationMessageClass = env->FindClass("android/location/GnssNavigationMessage");
     jmethodID navigationMessageCtor = env->GetMethodID(navigationMessageClass, "<init>", "()V");
     jobject navigationMessageObject = env->NewObject(navigationMessageClass, navigationMessageCtor);
 
@@ -1470,11 +1470,11 @@
         jobject navigationMessage = translate_gps_navigation_message(env, message);
 
         jclass navigationMessageEventClass =
-                env->FindClass("android/location/GpsNavigationMessageEvent");
+                env->FindClass("android/location/GnssNavigationMessageEvent");
         jmethodID navigationMessageEventCtor = env->GetMethodID(
                 navigationMessageEventClass,
                 "<init>",
-                "(Landroid/location/GpsNavigationMessage;)V");
+                "(Landroid/location/GnssNavigationMessage;)V");
         jobject navigationMessageEvent = env->NewObject(
                 navigationMessageEventClass,
                 navigationMessageEventCtor,
diff --git a/services/core/jni/com_android_server_vr_VrManagerService.cpp b/services/core/jni/com_android_server_vr_VrManagerService.cpp
new file mode 100644
index 0000000..1aba43b
--- /dev/null
+++ b/services/core/jni/com_android_server_vr_VrManagerService.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VrManagerService"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <jni.h>
+#include <JNIHelp.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/vr.h>
+
+namespace android {
+
+static vr_module_t *gVrHardwareModule = NULL;
+
+
+static void init_native(JNIEnv* /* env */, jclass /* clazz */) {
+    if (gVrHardwareModule != NULL) {
+        // This call path should never be hit.
+        ALOGE("%s: May not initialize VR hardware module more than once!", __FUNCTION__);
+        return;
+    }
+
+    int err = hw_get_module(VR_HARDWARE_MODULE_ID, (hw_module_t const**)&gVrHardwareModule);
+    if (err) {
+        ALOGW("%s: Could not open VR hardware module, error %s (%d).", __FUNCTION__,
+                strerror(-err), err);
+        return;
+    }
+
+    // Call init method if implemented.
+    if (gVrHardwareModule->init) {
+        gVrHardwareModule->init(gVrHardwareModule);
+    }
+}
+
+static void setVrMode_native(JNIEnv* /* env */, jclass /* clazz */, jboolean enabled) {
+    if (gVrHardwareModule == NULL) {
+        // There is no VR hardware module implemented, do nothing.
+        return;
+    }
+
+    // Call set_vr_mode method, this must be implemented if the HAL exists.
+    gVrHardwareModule->set_vr_mode(gVrHardwareModule, static_cast<bool>(enabled));
+}
+
+static const JNINativeMethod method_table[] = {
+    { "initializeNative", "()V", (void*)init_native },
+    { "setVrModeNative", "(Z)V", (void*)setVrMode_native },
+};
+
+int register_android_server_vr_VrManagerService(JNIEnv *env)
+{
+    return jniRegisterNativeMethods(env, "com/android/server/vr/VrManagerService",
+            method_table, NELEM(method_table));
+}
+
+}; // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index a7010bc..ef5c56c 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -35,6 +35,7 @@
 int register_android_server_UsbDeviceManager(JNIEnv* env);
 int register_android_server_UsbMidiDevice(JNIEnv* env);
 int register_android_server_UsbHostManager(JNIEnv* env);
+int register_android_server_vr_VrManagerService(JNIEnv* env);
 int register_android_server_VibratorService(JNIEnv* env);
 int register_android_server_location_GnssLocationProvider(JNIEnv* env);
 int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
@@ -69,6 +70,7 @@
     register_android_server_UsbDeviceManager(env);
     register_android_server_UsbMidiDevice(env);
     register_android_server_UsbHostManager(env);
+    register_android_server_vr_VrManagerService(env);
     register_android_server_VibratorService(env);
     register_android_server_SystemServer(env);
     register_android_server_location_GnssLocationProvider(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 83aa64e..f296d68 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1459,6 +1459,18 @@
         void settingsGlobalPutString(String name, String value) {
             Settings.Global.putString(mContext.getContentResolver(), name, value);
         }
+
+        void securityLogSetLoggingEnabledProperty(boolean enabled) {
+            SecurityLog.setLoggingEnabledProperty(enabled);
+        }
+
+        boolean securityLogGetLoggingEnabledProperty() {
+            return SecurityLog.getLoggingEnabledProperty();
+        }
+
+        boolean securityLogIsLoggingEnabled() {
+            return SecurityLog.isLoggingEnabled();
+        }
     }
 
     /**
@@ -1603,7 +1615,7 @@
             if (mOwners.hasDeviceOwner()) {
                 mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "true");
                 disableDeviceLoggingIfNotCompliant();
-                if (SecurityLog.getLoggingEnabledProperty()) {
+                if (mInjector.securityLogGetLoggingEnabledProperty()) {
                     mSecurityLogMonitor.start();
                 }
             } else {
@@ -2001,9 +2013,8 @@
     void removeActiveAdminLocked(final ComponentName adminReceiver, final int userHandle) {
         final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
         if (admin != null) {
-            synchronized (this) {
-                getUserData(userHandle).mRemovingAdmins.add(adminReceiver);
-            }
+            getUserData(userHandle).mRemovingAdmins.add(adminReceiver);
+
             sendAdminCommandLocked(admin,
                     DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED,
                     new BroadcastReceiver() {
@@ -2042,7 +2053,8 @@
         resolveIntent.setComponent(adminName);
         List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceiversAsUser(
                 resolveIntent,
-                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
+                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
+                PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
                 userHandle);
         if (infos == null || infos.size() <= 0) {
             throw new IllegalArgumentException("Unknown admin: " + adminName);
@@ -2809,14 +2821,14 @@
             if (admin == null) {
                 return;
             }
+            // Active device/profile owners must remain active admins.
+            if (isDeviceOwner(adminReceiver, userHandle)
+                    || isProfileOwner(adminReceiver, userHandle)) {
+                Slog.e(LOG_TAG, "Device/profile owner cannot be removed: component=" +
+                        adminReceiver);
+                return;
+            }
             if (admin.getUid() != mInjector.binderGetCallingUid()) {
-                // Active device/profile owners must remain active admins.
-                if (isDeviceOwner(adminReceiver, userHandle)
-                        || isProfileOwner(adminReceiver, userHandle)) {
-                    Slog.e(LOG_TAG, "Device/profile owner cannot be removed: component=" +
-                            adminReceiver);
-                    return;
-                }
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
             }
@@ -3645,7 +3657,7 @@
             if (!(isProfileOwner(adminComponent, userHandle)
                     || isDeviceOwner(adminComponent, userHandle))) {
                 final boolean preN = getTargetSdk(admin.info.getPackageName(), userHandle)
-                        < android.os.Build.VERSION_CODES.N;
+                        <= 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)) {
@@ -4120,7 +4132,7 @@
     public void choosePrivateKeyAlias(final int uid, final Uri uri, final String alias,
             final IBinder response) {
         // Caller UID needs to be trusted, so we restrict this method to SYSTEM_UID callers.
-        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+        if (!isCallerWithSystemUid()) {
             return;
         }
 
@@ -4468,7 +4480,7 @@
             mInjector.binderRestoreCallingIdentity(ident);
         }
 
-        if (SecurityLog.isLoggingEnabled()) {
+        if (mInjector.securityLogIsLoggingEnabled()) {
             SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT, /*result*/ 0);
         }
     }
@@ -4498,7 +4510,7 @@
             }
         }
 
-        if (SecurityLog.isLoggingEnabled()) {
+        if (mInjector.securityLogIsLoggingEnabled()) {
             SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT, /*result*/ 1);
         }
     }
@@ -4507,7 +4519,7 @@
     public void reportKeyguardDismissed() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
-        if (SecurityLog.isLoggingEnabled()) {
+        if (mInjector.securityLogIsLoggingEnabled()) {
             SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISSED);
         }
     }
@@ -4516,7 +4528,7 @@
     public void reportKeyguardSecured() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
-        if (SecurityLog.isLoggingEnabled()) {
+        if (mInjector.securityLogIsLoggingEnabled()) {
             SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_SECURED);
         }
     }
@@ -5469,9 +5481,11 @@
             throw new SecurityException(e);
         }
         synchronized (this) {
+            final ComponentName deviceOwnerComponent = mOwners.getDeviceOwnerComponent();
+            final int deviceOwnerUserId = mOwners.getDeviceOwnerUserId();
             if (!mOwners.hasDeviceOwner()
-                    || !mOwners.getDeviceOwnerComponent().getPackageName().equals(packageName)
-                    || (mOwners.getDeviceOwnerUserId() != UserHandle.getUserId(callingUid))) {
+                    || !deviceOwnerComponent.getPackageName().equals(packageName)
+                    || (deviceOwnerUserId != UserHandle.getUserId(callingUid))) {
                 throw new SecurityException(
                         "clearDeviceOwner can only be called by the device owner");
             }
@@ -5483,8 +5497,7 @@
                 admin.forceEphemeralUsers = false;
                 mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
             }
-
-            clearUserPoliciesLocked(new UserHandle(UserHandle.USER_SYSTEM));
+            clearUserPoliciesLocked(deviceOwnerUserId);
 
             mOwners.clearDeviceOwner();
             mOwners.writeDeviceOwner();
@@ -5494,6 +5507,8 @@
             long ident = mInjector.binderClearCallingIdentity();
             try {
                 mInjector.getIBackupManager().setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+
+                removeActiveAdminLocked(deviceOwnerComponent, deviceOwnerUserId);
             } catch (RemoteException e) {
                 throw new IllegalStateException("Failed reactivating backup service.", e);
             } finally {
@@ -5534,9 +5549,16 @@
         synchronized (this) {
             admin.disableCamera = false;
             admin.userRestrictions = null;
-            clearUserPoliciesLocked(callingUser);
+            clearUserPoliciesLocked(userId);
             mOwners.removeProfileOwner(userId);
             mOwners.writeProfileOwner(userId);
+
+            final long ident = mInjector.binderClearCallingIdentity();
+            try {
+                removeActiveAdminLocked(who, userId);
+            } finally {
+                mInjector.binderRestoreCallingIdentity(ident);
+            }
         }
     }
 
@@ -5564,8 +5586,7 @@
         return mLockPatternUtils.getDeviceOwnerInfo();
     }
 
-    private void clearUserPoliciesLocked(UserHandle userHandle) {
-        int userId = userHandle.getIdentifier();
+    private void clearUserPoliciesLocked(int userId) {
         // Reset some of the user-specific policies
         DevicePolicyData policy = getUserData(userId);
         policy.mPermissionPolicy = DevicePolicyManager.PERMISSION_POLICY_PROMPT;
@@ -5579,8 +5600,8 @@
         try {
             mIPackageManager.updatePermissionFlagsForAllApps(
                     PackageManager.FLAG_PERMISSION_POLICY_FIXED,
-                    0  /* flagValues */, userHandle.getIdentifier());
-            pushUserRestrictions(userHandle.getIdentifier());
+                    0  /* flagValues */, userId);
+            pushUserRestrictions(userId);
         } catch (RemoteException re) {
         } finally {
             mInjector.binderRestoreCallingIdentity(ident);
@@ -5839,8 +5860,7 @@
         }
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
-        if (hasUserSetupCompleted(userHandle)
-                && !UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) {
+        if (hasUserSetupCompleted(userHandle) && !isCallerWithSystemUid()) {
             throw new IllegalStateException("Cannot set the profile owner on a user which is "
                     + "already set-up");
         }
@@ -5900,8 +5920,7 @@
 
     private void enforceManageUsers() {
         final int callingUid = mInjector.binderGetCallingUid();
-        if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
-                || callingUid == Process.ROOT_UID)) {
+        if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {
             mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
         }
     }
@@ -5924,8 +5943,7 @@
         if (userHandle == UserHandle.getUserId(callingUid)) {
             return;
         }
-        if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
-                || callingUid == Process.ROOT_UID)) {
+        if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {
             mContext.enforceCallingOrSelfPermission(permission,
                     "Must be system or have " + permission + " permission");
         }
@@ -5943,6 +5961,10 @@
         }
     }
 
+    private boolean isCallerWithSystemUid() {
+        return UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID);
+    }
+
     private int getProfileParentId(int userHandle) {
         final long ident = mInjector.binderClearCallingIdentity();
         try {
@@ -6227,7 +6249,7 @@
     @Override
     public ComponentName getRestrictionsProvider(int userHandle) {
         synchronized (this) {
-            if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+            if (!isCallerWithSystemUid()) {
                 throw new SecurityException("Only the system can query the permission provider");
             }
             DevicePolicyData userData = getUserData(userHandle);
@@ -6300,8 +6322,7 @@
      * permittedList or are a system app.
      */
     private boolean checkPackagesInPermittedListOrSystem(List<String> enabledPackages,
-            List<String> permittedList) {
-        int userIdToCheck = UserHandle.getCallingUserId();
+            List<String> permittedList, int userIdToCheck) {
         long id = mInjector.binderClearCallingIdentity();
         try {
             // If we have an enabled packages list for a managed profile the packages
@@ -6368,7 +6389,8 @@
                 for (AccessibilityServiceInfo service : enabledServices) {
                     enabledPackages.add(service.getResolveInfo().serviceInfo.packageName);
                 }
-                if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) {
+                if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList,
+                        userId)) {
                     Slog.e(LOG_TAG, "Cannot set permitted accessibility services, "
                             + "because it contains already enabled accesibility services.");
                     return false;
@@ -6460,6 +6482,28 @@
         }
     }
 
+    @Override
+    public boolean isAccessibilityServicePermittedByAdmin(ComponentName who, String packageName,
+            int userHandle) {
+        if (!mHasFeature) {
+            return true;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        Preconditions.checkStringNotEmpty(packageName, "packageName is null");
+        if (!isCallerWithSystemUid()){
+            throw new SecurityException(
+                    "Only the system can query if an accessibility service is disabled by admin");
+        }
+        synchronized (this) {
+            ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+            if (admin.permittedAccessiblityServices == null) {
+                return true;
+            }
+            return checkPackagesInPermittedListOrSystem(Arrays.asList(packageName),
+                    admin.permittedAccessiblityServices, userHandle);
+        }
+    }
+
     private boolean checkCallerIsCurrentUserOrProfile() {
         int callingUserId = UserHandle.getCallingUserId();
         long token = mInjector.binderClearCallingIdentity();
@@ -6515,7 +6559,8 @@
                 for (InputMethodInfo ime : enabledImes) {
                     enabledPackages.add(ime.getPackageName());
                 }
-                if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) {
+                if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList,
+                        mInjector.binderGetCallingUserHandle().getIdentifier())) {
                     Slog.e(LOG_TAG, "Cannot set permitted input methods, "
                             + "because it contains already enabled input method.");
                     return false;
@@ -6608,6 +6653,28 @@
     }
 
     @Override
+    public boolean isInputMethodPermittedByAdmin(ComponentName who, String packageName,
+            int userHandle) {
+        if (!mHasFeature) {
+            return true;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        Preconditions.checkStringNotEmpty(packageName, "packageName is null");
+        if (!isCallerWithSystemUid()) {
+            throw new SecurityException(
+                    "Only the system can query if an input method is disabled by admin");
+        }
+        synchronized (this) {
+            ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+            if (admin.permittedInputMethods == null) {
+                return true;
+            }
+            return checkPackagesInPermittedListOrSystem(Arrays.asList(packageName),
+                    admin.permittedInputMethods, userHandle);
+        }
+    }
+
+    @Override
     public UserHandle createUser(ComponentName who, String name) {
         Preconditions.checkNotNull(who, "ComponentName is null");
         synchronized (this) {
@@ -6847,7 +6914,9 @@
     @Override
     public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner) {
         Preconditions.checkNotNull(who, "ComponentName is null");
-        UserRestrictionsUtils.checkRestriction(key);
+        if (!UserRestrictionsUtils.isValidRestriction(key)) {
+            return;
+        }
 
         final int userHandle = mInjector.userHandleGetCallingUserId();
         synchronized (this) {
@@ -7242,7 +7311,7 @@
                 if (managedUserId < 0) {
                     return;
                 }
-                if (getCrossProfileCallerIdDisabledForUser(managedUserId)) {
+                if (isCrossProfileQuickContactDisabled(managedUserId)) {
                     if (VERBOSE_LOG) {
                         Log.v(LOG_TAG,
                                 "Cross-profile contacts access disabled for user " + managedUserId);
@@ -7258,6 +7327,14 @@
     }
 
     /**
+     * @return true if cross-profile QuickContact is disabled
+     */
+    private boolean isCrossProfileQuickContactDisabled(int userId) {
+        return getCrossProfileCallerIdDisabledForUser(userId)
+                && getCrossProfileContactsSearchDisabledForUser(userId);
+    }
+
+    /**
      * @return the user ID of the managed user that is linked to the current user, if any.
      * Otherwise -1.
      */
@@ -7394,7 +7471,7 @@
 
     @Override
     public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) {
-        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+        if (!isCallerWithSystemUid()) {
             throw new SecurityException("notifyLockTaskModeChanged can only be called by system");
         }
         synchronized (this) {
@@ -8149,7 +8226,7 @@
             return null;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
-        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+        if (!isCallerWithSystemUid()) {
             throw new SecurityException("Only the system can query support message for user");
         }
         synchronized (this) {
@@ -8167,7 +8244,7 @@
             return null;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
-        if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) {
+        if (!isCallerWithSystemUid()) {
             throw new SecurityException("Only the system can query support message for user");
         }
         synchronized (this) {
@@ -8317,7 +8394,7 @@
 
     private void disableDeviceLoggingIfNotCompliant() {
         if (!isDeviceOwnerManagedSingleUserDevice()) {
-            SecurityLog.setLoggingEnabledProperty(false);
+            mInjector.securityLogSetLoggingEnabledProperty(false);
             Slog.w(LOG_TAG, "Device logging turned off as it's no longer a single user device.");
         }
     }
@@ -8328,7 +8405,7 @@
         ensureDeviceOwnerManagingSingleUser(admin);
 
         synchronized (this) {
-            SecurityLog.setLoggingEnabledProperty(enabled);
+            mInjector.securityLogSetLoggingEnabledProperty(enabled);
             if (enabled) {
                 mSecurityLogMonitor.start();
             } else {
@@ -8342,7 +8419,7 @@
         Preconditions.checkNotNull(admin);
         synchronized (this) {
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
-            return SecurityLog.getLoggingEnabledProperty();
+            return mInjector.securityLogGetLoggingEnabledProperty();
         }
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 254a37a..0cf9328 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -80,6 +80,7 @@
 import com.android.server.pm.BackgroundDexOptService;
 import com.android.server.pm.Installer;
 import com.android.server.pm.LauncherAppsService;
+import com.android.server.pm.OtaDexoptService;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.UserManagerService;
 import com.android.server.power.PowerManagerService;
@@ -495,6 +496,7 @@
         boolean disableNonCoreServices = SystemProperties.getBoolean("config.disable_noncore", false);
         boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false);
         boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false);
+        boolean disableRtt = SystemProperties.getBoolean("config.disable_rtt", false);
         boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
 
         try {
@@ -787,7 +789,9 @@
                 mSystemServiceManager.startService(
                             "com.android.server.wifi.WifiScanningService");
 
-                mSystemServiceManager.startService("com.android.server.wifi.RttService");
+                if (!disableRtt) {
+                    mSystemServiceManager.startService("com.android.server.wifi.RttService");
+                }
 
                 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
                     mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
@@ -1087,7 +1091,9 @@
 
                 mSystemServiceManager.startService(TrustManagerService.class);
 
-                mSystemServiceManager.startService(FingerprintService.class);
+                if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+                    mSystemServiceManager.startService(FingerprintService.class);
+                }
 
                 traceBeginAndSlog("StartBackgroundDexOptService");
                 try {
@@ -1097,6 +1103,18 @@
                 }
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
+                // Manages A/B OTA dexopting.
+                boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
+                        false);
+                if (!disableOtaDexopt) {
+                    traceBeginAndSlog("StartOtaDexOptService");
+                    try {
+                        OtaDexoptService.main(mSystemContext, mPackageManagerService);
+                    } catch (Throwable e) {
+                        reportWtf("starting BackgroundDexOptService", e);
+                    }
+                    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+                }
             }
 
             mSystemServiceManager.startService(LauncherAppsService.class);
diff --git a/services/net/java/android/net/apf/ApfGenerator.java b/services/net/java/android/net/apf/ApfGenerator.java
new file mode 100644
index 0000000..96c2ba5
--- /dev/null
+++ b/services/net/java/android/net/apf/ApfGenerator.java
@@ -0,0 +1,883 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.apf;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * APF assembler/generator.  A tool for generating an APF program.
+ *
+ * Call add*() functions to add instructions to the program, then call
+ * {@link generate} to get the APF bytecode for the program.
+ *
+ * @hide
+ */
+public class ApfGenerator {
+    /**
+     * This exception is thrown when an attempt is made to generate an illegal instruction.
+     */
+    public static class IllegalInstructionException extends Exception {
+        IllegalInstructionException(String msg) {
+            super(msg);
+        }
+    }
+    private enum Opcodes {
+        LABEL(-1),
+        LDB(1),    // Load 1 byte from immediate offset, e.g. "ldb R0, [5]"
+        LDH(2),    // Load 2 bytes from immediate offset, e.g. "ldh R0, [5]"
+        LDW(3),    // Load 4 bytes from immediate offset, e.g. "ldw R0, [5]"
+        LDBX(4),   // Load 1 byte from immediate offset plus register, e.g. "ldbx R0, [5]R0"
+        LDHX(5),   // Load 2 byte from immediate offset plus register, e.g. "ldhx R0, [5]R0"
+        LDWX(6),   // Load 4 byte from immediate offset plus register, e.g. "ldwx R0, [5]R0"
+        ADD(7),    // Add, e.g. "add R0,5"
+        MUL(8),    // Multiply, e.g. "mul R0,5"
+        DIV(9),    // Divide, e.g. "div R0,5"
+        AND(10),   // And, e.g. "and R0,5"
+        OR(11),    // Or, e.g. "or R0,5"
+        SH(12),    // Left shift, e.g, "sh R0, 5" or "sh R0, -5" (shifts right)
+        LI(13),    // Load immediate, e.g. "li R0,5" (immediate encoded as signed value)
+        JMP(14),   // Jump, e.g. "jmp label"
+        JEQ(15),   // Compare equal and branch, e.g. "jeq R0,5,label"
+        JNE(16),   // Compare not equal and branch, e.g. "jne R0,5,label"
+        JGT(17),   // Compare greater than and branch, e.g. "jgt R0,5,label"
+        JLT(18),   // Compare less than and branch, e.g. "jlt R0,5,label"
+        JSET(19),  // Compare any bits set and branch, e.g. "jset R0,5,label"
+        JNEBS(20), // Compare not equal byte sequence, e.g. "jnebs R0,5,label,0x1122334455"
+        EXT(21);   // Followed by immediate indicating ExtendedOpcodes.
+
+        final int value;
+
+        private Opcodes(int value) {
+            this.value = value;
+        }
+    }
+    // Extended opcodes. Primary opcode is Opcodes.EXT. ExtendedOpcodes are encoded in the immediate
+    // field.
+    private enum ExtendedOpcodes {
+        LDM(0),   // Load from memory, e.g. "ldm R0,5"
+        STM(16),  // Store to memory, e.g. "stm R0,5"
+        NOT(32),  // Not, e.g. "not R0"
+        NEG(33),  // Negate, e.g. "neg R0"
+        SWAP(34), // Swap, e.g. "swap R0,R1"
+        MOVE(35);  // Move, e.g. "move R0,R1"
+
+        final int value;
+
+        private ExtendedOpcodes(int value) {
+            this.value = value;
+        }
+    }
+    public enum Register {
+        R0(0),
+        R1(1);
+
+        final int value;
+
+        private Register(int value) {
+            this.value = value;
+        }
+    }
+    private class Instruction {
+        private final byte mOpcode;   // A "Opcode" value.
+        private final byte mRegister; // A "Register" value.
+        private boolean mHasImm;
+        private byte mImmSize;
+        private boolean mImmSigned;
+        private int mImm;
+        // When mOpcode is a jump:
+        private byte mTargetLabelSize;
+        private String mTargetLabel;
+        // When mOpcode == Opcodes.LABEL:
+        private String mLabel;
+        // When mOpcode == Opcodes.JNEBS:
+        private byte[] mCompareBytes;
+        // Offset in bytes from the begining of this program. Set by {@link ApfGenerator#generate}.
+        int offset;
+
+        Instruction(Opcodes opcode, Register register) {
+            mOpcode = (byte)opcode.value;
+            mRegister = (byte)register.value;
+        }
+
+        Instruction(Opcodes opcode) {
+            this(opcode, Register.R0);
+        }
+
+        void setImm(int imm, boolean signed) {
+            mHasImm = true;
+            mImm = imm;
+            mImmSigned = signed;
+            mImmSize = calculateImmSize(imm, signed);
+        }
+
+        void setUnsignedImm(int imm) {
+            setImm(imm, false);
+        }
+
+        void setSignedImm(int imm) {
+            setImm(imm, true);
+        }
+
+        void setLabel(String label) throws IllegalInstructionException {
+            if (mLabels.containsKey(label)) {
+                throw new IllegalInstructionException("duplicate label " + label);
+            }
+            if (mOpcode != Opcodes.LABEL.value) {
+                throw new IllegalStateException("adding label to non-label instruction");
+            }
+            mLabel = label;
+            mLabels.put(label, this);
+        }
+
+        void setTargetLabel(String label) {
+            mTargetLabel = label;
+            mTargetLabelSize = 4; // May shrink later on in generate().
+        }
+
+        void setCompareBytes(byte[] bytes) {
+            if (mOpcode != Opcodes.JNEBS.value) {
+                throw new IllegalStateException("adding compare bytes to non-JNEBS instruction");
+            }
+            mCompareBytes = bytes;
+        }
+
+        /**
+         * @return size of instruction in bytes.
+         */
+        int size() {
+            if (mOpcode == Opcodes.LABEL.value) {
+                return 0;
+            }
+            int size = 1;
+            if (mHasImm) {
+                size += generatedImmSize();
+            }
+            if (mTargetLabel != null) {
+                size += generatedImmSize();
+            }
+            if (mCompareBytes != null) {
+                size += mCompareBytes.length;
+            }
+            return size;
+        }
+
+        /**
+         * Resize immediate value field so that it's only as big as required to
+         * contain the offset of the jump destination.
+         * @return {@code true} if shrunk.
+         */
+        boolean shrink() throws IllegalInstructionException {
+            if (mTargetLabel == null) {
+                return false;
+            }
+            int oldSize = size();
+            int oldTargetLabelSize = mTargetLabelSize;
+            mTargetLabelSize = calculateImmSize(calculateTargetLabelOffset(), false);
+            if (mTargetLabelSize > oldTargetLabelSize) {
+                throw new IllegalStateException("instruction grew");
+            }
+            return size() < oldSize;
+        }
+
+        /**
+         * Assemble value for instruction size field.
+         */
+        private byte generateImmSizeField() {
+            byte immSize = generatedImmSize();
+            // Encode size field to fit in 2 bits: 0->0, 1->1, 2->2, 3->4.
+            return immSize == 4 ? 3 : immSize;
+        }
+
+        /**
+         * Assemble first byte of generated instruction.
+         */
+        private byte generateInstructionByte() {
+            byte sizeField = generateImmSizeField();
+            return (byte)((mOpcode << 3) | (sizeField << 1) | mRegister);
+        }
+
+        /**
+         * Write {@code value} at offset {@code writingOffset} into {@code bytecode}.
+         * {@link generatedImmSize} bytes are written. {@code value} is truncated to
+         * {@code generatedImmSize} bytes. {@code value} is treated simply as a
+         * 32-bit value, so unsigned values should be zero extended and the truncation
+         * should simply throw away their zero-ed upper bits, and signed values should
+         * be sign extended and the truncation should simply throw away their signed
+         * upper bits.
+         */
+        private int writeValue(int value, byte[] bytecode, int writingOffset) {
+            for (int i = generatedImmSize() - 1; i >= 0; i--) {
+                bytecode[writingOffset++] = (byte)((value >> (i * 8)) & 255);
+            }
+            return writingOffset;
+        }
+
+        /**
+         * Generate bytecode for this instruction at offset {@link offset}.
+         */
+        void generate(byte[] bytecode) throws IllegalInstructionException {
+            if (mOpcode == Opcodes.LABEL.value) {
+                return;
+            }
+            int writingOffset = offset;
+            bytecode[writingOffset++] = generateInstructionByte();
+            if (mTargetLabel != null) {
+                writingOffset = writeValue(calculateTargetLabelOffset(), bytecode, writingOffset);
+            }
+            if (mHasImm) {
+                writingOffset = writeValue(mImm, bytecode, writingOffset);
+            }
+            if (mCompareBytes != null) {
+                System.arraycopy(mCompareBytes, 0, bytecode, writingOffset, mCompareBytes.length);
+                writingOffset += mCompareBytes.length;
+            }
+            if ((writingOffset - offset) != size()) {
+                throw new IllegalStateException("wrote " + (writingOffset - offset) +
+                        " but should have written " + size());
+            }
+        }
+
+        /**
+         * Calculate the size of either the immediate field or the target label field, if either is
+         * present. Most instructions have either an immediate or a target label field, but for the
+         * instructions that have both, the size of the target label field must be the same as the
+         * size of the immediate field, because there is only one length field in the instruction
+         * byte, hence why this function simply takes the maximum of the two sizes, so neither is
+         * truncated.
+         */
+        private byte generatedImmSize() {
+            return mImmSize > mTargetLabelSize ? mImmSize : mTargetLabelSize;
+        }
+
+        private int calculateTargetLabelOffset() throws IllegalInstructionException {
+            Instruction targetLabelInstruction;
+            if (mTargetLabel == DROP_LABEL) {
+                targetLabelInstruction = mDropLabel;
+            } else if (mTargetLabel == PASS_LABEL) {
+                targetLabelInstruction = mPassLabel;
+            } else {
+                targetLabelInstruction = mLabels.get(mTargetLabel);
+            }
+            if (targetLabelInstruction == null) {
+                throw new IllegalInstructionException("label not found: " + mTargetLabel);
+            }
+            // Calculate distance from end of this instruction to instruction.offset.
+            final int targetLabelOffset = targetLabelInstruction.offset - (offset + size());
+            if (targetLabelOffset < 0) {
+                throw new IllegalInstructionException("backward branches disallowed; label: " +
+                        mTargetLabel);
+            }
+            return targetLabelOffset;
+        }
+
+        private byte calculateImmSize(int imm, boolean signed) {
+            if (imm == 0) {
+                return 0;
+            }
+            if (signed && (imm >= -128 && imm <= 127) ||
+                    !signed && (imm >= 0 && imm <= 255)) {
+                return 1;
+            }
+            if (signed && (imm >= -32768 && imm <= 32767) ||
+                    !signed && (imm >= 0 && imm <= 65535)) {
+                return 2;
+            }
+            return 4;
+        }
+    }
+
+    /**
+     * Jump to this label to terminate the program and indicate the packet
+     * should be dropped.
+     */
+    public static final String DROP_LABEL = "__DROP__";
+
+    /**
+     * Jump to this label to terminate the program and indicate the packet
+     * should be passed to the AP.
+     */
+    public static final String PASS_LABEL = "__PASS__";
+
+    /**
+     * Number of memory slots available for access via APF stores to memory and loads from memory.
+     * The memory slots are numbered 0 to {@code MEMORY_SLOTS} - 1. This must be kept in sync with
+     * the APF interpreter.
+     */
+    public static final int MEMORY_SLOTS = 16;
+
+    /**
+     * Memory slot number that is prefilled with the IPv4 header length.
+     * Note that this memory slot may be overwritten by a program that
+     * executes stores to this memory slot. This must be kept in sync with
+     * the APF interpreter.
+     */
+    public static final int IPV4_HEADER_SIZE_MEMORY_SLOT = 13;
+
+    /**
+     * Memory slot number that is prefilled with the size of the packet being filtered in bytes.
+     * Note that this memory slot may be overwritten by a program that
+     * executes stores to this memory slot. This must be kept in sync with the APF interpreter.
+     */
+    public static final int PACKET_SIZE_MEMORY_SLOT = 14;
+
+    /**
+     * Memory slot number that is prefilled with the age of the filter in seconds. The age of the
+     * filter is the time since the filter was installed until now.
+     * Note that this memory slot may be overwritten by a program that
+     * executes stores to this memory slot. This must be kept in sync with the APF interpreter.
+     */
+    public static final int FILTER_AGE_MEMORY_SLOT = 15;
+
+    /**
+     * First memory slot containing prefilled values. Can be used in range comparisons to determine
+     * if memory slot index is within prefilled slots.
+     */
+    public static final int FIRST_PREFILLED_MEMORY_SLOT = IPV4_HEADER_SIZE_MEMORY_SLOT;
+
+    /**
+     * Last memory slot containing prefilled values. Can be used in range comparisons to determine
+     * if memory slot index is within prefilled slots.
+     */
+    public static final int LAST_PREFILLED_MEMORY_SLOT = FILTER_AGE_MEMORY_SLOT;
+
+    private final ArrayList<Instruction> mInstructions = new ArrayList<Instruction>();
+    private final HashMap<String, Instruction> mLabels = new HashMap<String, Instruction>();
+    private final Instruction mDropLabel = new Instruction(Opcodes.LABEL);
+    private final Instruction mPassLabel = new Instruction(Opcodes.LABEL);
+    private boolean mGenerated;
+
+    /**
+     * Set version of APF instruction set to generate instructions for. Returns {@code true}
+     * if generating for this version is supported, {@code false} otherwise.
+     */
+    public boolean setApfVersion(int version) {
+        // This version number syncs up with APF_VERSION in hardware/google/apf/apf_interpreter.h
+        return version == 2;
+    }
+
+    private void addInstruction(Instruction instruction) {
+        if (mGenerated) {
+            throw new IllegalStateException("Program already generated");
+        }
+        mInstructions.add(instruction);
+    }
+
+    /**
+     * Define a label at the current end of the program. Jumps can jump to this label. Labels are
+     * their own separate instructions, though with size 0. This facilitates having labels with
+     * no corresponding code to execute, for example a label at the end of a program. For example
+     * an {@link ApfGenerator} might be passed to a function that adds a filter like so:
+     * <pre>
+     *   load from packet
+     *   compare loaded data, jump if not equal to "next_filter"
+     *   load from packet
+     *   compare loaded data, jump if not equal to "next_filter"
+     *   jump to drop label
+     *   define "next_filter" here
+     * </pre>
+     * In this case "next_filter" may not have any generated code associated with it.
+     */
+    public ApfGenerator defineLabel(String name) throws IllegalInstructionException {
+        Instruction instruction = new Instruction(Opcodes.LABEL);
+        instruction.setLabel(name);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an unconditional jump instruction to the end of the program.
+     */
+    public ApfGenerator addJump(String target) {
+        Instruction instruction = new Instruction(Opcodes.JMP);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to load the byte at offset {@code offset}
+     * bytes from the begining of the packet into {@code register}.
+     */
+    public ApfGenerator addLoad8(Register register, int offset) {
+        Instruction instruction = new Instruction(Opcodes.LDB, register);
+        instruction.setUnsignedImm(offset);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to load 16-bits at offset {@code offset}
+     * bytes from the begining of the packet into {@code register}.
+     */
+    public ApfGenerator addLoad16(Register register, int offset) {
+        Instruction instruction = new Instruction(Opcodes.LDH, register);
+        instruction.setUnsignedImm(offset);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to load 32-bits at offset {@code offset}
+     * bytes from the begining of the packet into {@code register}.
+     */
+    public ApfGenerator addLoad32(Register register, int offset) {
+        Instruction instruction = new Instruction(Opcodes.LDW, register);
+        instruction.setUnsignedImm(offset);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to load a byte from the packet into
+     * {@code register}. The offset of the loaded byte from the begining of the packet is
+     * the sum of {@code offset} and the value in register R1.
+     */
+    public ApfGenerator addLoad8Indexed(Register register, int offset) {
+        Instruction instruction = new Instruction(Opcodes.LDBX, register);
+        instruction.setUnsignedImm(offset);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to load 16-bits from the packet into
+     * {@code register}. The offset of the loaded 16-bits from the begining of the packet is
+     * the sum of {@code offset} and the value in register R1.
+     */
+    public ApfGenerator addLoad16Indexed(Register register, int offset) {
+        Instruction instruction = new Instruction(Opcodes.LDHX, register);
+        instruction.setUnsignedImm(offset);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to load 32-bits from the packet into
+     * {@code register}. The offset of the loaded 32-bits from the begining of the packet is
+     * the sum of {@code offset} and the value in register R1.
+     */
+    public ApfGenerator addLoad32Indexed(Register register, int offset) {
+        Instruction instruction = new Instruction(Opcodes.LDWX, register);
+        instruction.setUnsignedImm(offset);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to add {@code value} to register R0.
+     */
+    public ApfGenerator addAdd(int value) {
+        Instruction instruction = new Instruction(Opcodes.ADD);
+        instruction.setSignedImm(value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to multiply register R0 by {@code value}.
+     */
+    public ApfGenerator addMul(int value) {
+        Instruction instruction = new Instruction(Opcodes.MUL);
+        instruction.setSignedImm(value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to divide register R0 by {@code value}.
+     */
+    public ApfGenerator addDiv(int value) {
+        Instruction instruction = new Instruction(Opcodes.DIV);
+        instruction.setSignedImm(value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to logically and register R0 with {@code value}.
+     */
+    public ApfGenerator addAnd(int value) {
+        Instruction instruction = new Instruction(Opcodes.AND);
+        instruction.setUnsignedImm(value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to logically or register R0 with {@code value}.
+     */
+    public ApfGenerator addOr(int value) {
+        Instruction instruction = new Instruction(Opcodes.OR);
+        instruction.setUnsignedImm(value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to shift left register R0 by {@code value} bits.
+     */
+    public ApfGenerator addLeftShift(int value) {
+        Instruction instruction = new Instruction(Opcodes.SH);
+        instruction.setSignedImm(value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to shift right register R0 by {@code value}
+     * bits.
+     */
+    public ApfGenerator addRightShift(int value) {
+        Instruction instruction = new Instruction(Opcodes.SH);
+        instruction.setSignedImm(-value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to add register R1 to register R0.
+     */
+    public ApfGenerator addAddR1() {
+        Instruction instruction = new Instruction(Opcodes.ADD, Register.R1);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to multiply register R0 by register R1.
+     */
+    public ApfGenerator addMulR1() {
+        Instruction instruction = new Instruction(Opcodes.MUL, Register.R1);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to divide register R0 by register R1.
+     */
+    public ApfGenerator addDivR1() {
+        Instruction instruction = new Instruction(Opcodes.DIV, Register.R1);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to logically and register R0 with register R1
+     * and store the result back into register R0.
+     */
+    public ApfGenerator addAndR1() {
+        Instruction instruction = new Instruction(Opcodes.AND, Register.R1);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to logically or register R0 with register R1
+     * and store the result back into register R0.
+     */
+    public ApfGenerator addOrR1() {
+        Instruction instruction = new Instruction(Opcodes.OR, Register.R1);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to shift register R0 left by the value in
+     * register R1.
+     */
+    public ApfGenerator addLeftShiftR1() {
+        Instruction instruction = new Instruction(Opcodes.SH, Register.R1);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to move {@code value} into {@code register}.
+     */
+    public ApfGenerator addLoadImmediate(Register register, int value) {
+        Instruction instruction = new Instruction(Opcodes.LI, register);
+        instruction.setSignedImm(value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value equals {@code value}.
+     */
+    public ApfGenerator addJumpIfR0Equals(int value, String target) {
+        Instruction instruction = new Instruction(Opcodes.JEQ);
+        instruction.setUnsignedImm(value);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value does not equal {@code value}.
+     */
+    public ApfGenerator addJumpIfR0NotEquals(int value, String target) {
+        Instruction instruction = new Instruction(Opcodes.JNE);
+        instruction.setUnsignedImm(value);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value is greater than {@code value}.
+     */
+    public ApfGenerator addJumpIfR0GreaterThan(int value, String target) {
+        Instruction instruction = new Instruction(Opcodes.JGT);
+        instruction.setUnsignedImm(value);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value is less than {@code value}.
+     */
+    public ApfGenerator addJumpIfR0LessThan(int value, String target) {
+        Instruction instruction = new Instruction(Opcodes.JLT);
+        instruction.setUnsignedImm(value);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value has any bits set that are also set in {@code value}.
+     */
+    public ApfGenerator addJumpIfR0AnyBitsSet(int value, String target) {
+        Instruction instruction = new Instruction(Opcodes.JSET);
+        instruction.setUnsignedImm(value);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value equals register R1's value.
+     */
+    public ApfGenerator addJumpIfR0EqualsR1(String target) {
+        Instruction instruction = new Instruction(Opcodes.JEQ, Register.R1);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value does not equal register R1's value.
+     */
+    public ApfGenerator addJumpIfR0NotEqualsR1(String target) {
+        Instruction instruction = new Instruction(Opcodes.JNE, Register.R1);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value is greater than register R1's value.
+     */
+    public ApfGenerator addJumpIfR0GreaterThanR1(String target) {
+        Instruction instruction = new Instruction(Opcodes.JGT, Register.R1);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value is less than register R1's value.
+     */
+    public ApfGenerator addJumpIfR0LessThanR1(String target) {
+        Instruction instruction = new Instruction(Opcodes.JLT, Register.R1);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if register R0's
+     * value has any bits set that are also set in R1's value.
+     */
+    public ApfGenerator addJumpIfR0AnyBitsSetR1(String target) {
+        Instruction instruction = new Instruction(Opcodes.JSET, Register.R1);
+        instruction.setTargetLabel(target);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to jump to {@code target} if the bytes of the
+     * packet at, an offset specified by {@code register}, match {@code bytes}.
+     */
+    public ApfGenerator addJumpIfBytesNotEqual(Register register, byte[] bytes, String target) {
+        Instruction instruction = new Instruction(Opcodes.JNEBS, register);
+        instruction.setUnsignedImm(bytes.length);
+        instruction.setTargetLabel(target);
+        instruction.setCompareBytes(bytes);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to load memory slot {@code slot} into
+     * {@code register}.
+     */
+    public ApfGenerator addLoadFromMemory(Register register, int slot)
+            throws IllegalInstructionException {
+        if (slot < 0 || slot > (MEMORY_SLOTS - 1)) {
+            throw new IllegalInstructionException("illegal memory slot number: " + slot);
+        }
+        Instruction instruction = new Instruction(Opcodes.EXT, register);
+        instruction.setUnsignedImm(ExtendedOpcodes.LDM.value + slot);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to store {@code register} into memory slot
+     * {@code slot}.
+     */
+    public ApfGenerator addStoreToMemory(Register register, int slot)
+            throws IllegalInstructionException {
+        if (slot < 0 || slot > (MEMORY_SLOTS - 1)) {
+            throw new IllegalInstructionException("illegal memory slot number: " + slot);
+        }
+        Instruction instruction = new Instruction(Opcodes.EXT, register);
+        instruction.setUnsignedImm(ExtendedOpcodes.STM.value + slot);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to logically not {@code register}.
+     */
+    public ApfGenerator addNot(Register register) {
+        Instruction instruction = new Instruction(Opcodes.EXT, register);
+        instruction.setUnsignedImm(ExtendedOpcodes.NOT.value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to negate {@code register}.
+     */
+    public ApfGenerator addNeg(Register register) {
+        Instruction instruction = new Instruction(Opcodes.EXT, register);
+        instruction.setUnsignedImm(ExtendedOpcodes.NEG.value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to swap the values in register R0 and register R1.
+     */
+    public ApfGenerator addSwap() {
+        Instruction instruction = new Instruction(Opcodes.EXT);
+        instruction.setUnsignedImm(ExtendedOpcodes.SWAP.value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Add an instruction to the end of the program to move the value into
+     * {@code register} from the other register.
+     */
+    public ApfGenerator addMove(Register register) {
+        Instruction instruction = new Instruction(Opcodes.EXT, register);
+        instruction.setUnsignedImm(ExtendedOpcodes.MOVE.value);
+        addInstruction(instruction);
+        return this;
+    }
+
+    /**
+     * Updates instruction offset fields using latest instruction sizes.
+     * @return current program length in bytes.
+     */
+    private int updateInstructionOffsets() {
+        int offset = 0;
+        for (Instruction instruction : mInstructions) {
+            instruction.offset = offset;
+            offset += instruction.size();
+        }
+        return offset;
+    }
+
+    /**
+     * Returns an overestimate of the size of the generated program. {@link #generate} may return
+     * a program that is smaller.
+     */
+    public int programLengthOverEstimate() {
+        return updateInstructionOffsets();
+    }
+
+    /**
+     * Generate the bytecode for the APF program.
+     * @return the bytecode.
+     * @throws IllegalStateException if a label is referenced but not defined.
+     */
+    public byte[] generate() throws IllegalInstructionException {
+        // Enforce that we can only generate once because we cannot unshrink instructions and
+        // PASS/DROP labels may move further away requiring unshrinking if we add further
+        // instructions.
+        if (mGenerated) {
+            throw new IllegalStateException("Can only generate() once!");
+        }
+        mGenerated = true;
+        int total_size;
+        boolean shrunk;
+        // Shrink the immediate value fields of instructions.
+        // As we shrink the instructions some branch offset
+        // fields may shrink also, thereby shrinking the
+        // instructions further. Loop until we've reached the
+        // minimum size. Rarely will this loop more than a few times.
+        // Limit iterations to avoid O(n^2) behavior.
+        int iterations_remaining = 10;
+        do {
+            total_size = updateInstructionOffsets();
+            // Update drop and pass label offsets.
+            mDropLabel.offset = total_size + 1;
+            mPassLabel.offset = total_size;
+            // Limit run-time in aberant circumstances.
+            if (iterations_remaining-- == 0) break;
+            // Attempt to shrink instructions.
+            shrunk = false;
+            for (Instruction instruction : mInstructions) {
+                if (instruction.shrink()) {
+                    shrunk = true;
+                }
+            }
+        } while (shrunk);
+        // Generate bytecode for instructions.
+        byte[] bytecode = new byte[total_size];
+        for (Instruction instruction : mInstructions) {
+            instruction.generate(bytecode);
+        }
+        return bytecode;
+    }
+}
+
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 87ac846..06b6ee7 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -17,15 +17,21 @@
 package android.net.ip;
 
 import android.content.Context;
+import android.net.BaseDhcpStateMachine;
 import android.net.DhcpResults;
+import android.net.DhcpStateMachine;
+import android.net.InterfaceConfiguration;
+import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.LinkProperties.ProvisioningChange;
 import android.net.RouteInfo;
 import android.net.StaticIpConfiguration;
+import android.net.dhcp.DhcpClient;
 import android.os.INetworkManagementService;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.provider.Settings;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -37,6 +43,7 @@
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
+import java.util.Objects;
 
 
 /**
@@ -84,10 +91,14 @@
          * as IpManager invokes them.
          */
 
+        // Implementations must call IpManager#completedPreDhcpAction().
+        public void onPreDhcpAction() {}
+        public void onPostDhcpAction() {}
+
         // TODO: Kill with fire once DHCP and static configuration are moved
         // out of WifiStateMachine.
-        public void onIPv4ProvisioningSuccess(DhcpResults dhcpResults, int reason) {}
-        public void onIPv4ProvisioningFailure(int reason) {}
+        public void onIPv4ProvisioningSuccess(DhcpResults dhcpResults) {}
+        public void onIPv4ProvisioningFailure() {}
 
         public void onProvisioningSuccess(LinkProperties newLp) {}
         public void onProvisioningFailure(LinkProperties newLp) {}
@@ -103,7 +114,7 @@
     private static final int CMD_STOP = 1;
     private static final int CMD_START = 2;
     private static final int CMD_CONFIRM = 3;
-    private static final int CMD_UPDATE_DHCPV4_RESULTS = 4;
+    private static final int EVENT_PRE_DHCP_ACTION_COMPLETE = 4;
     // Sent by NetlinkTracker to communicate netlink events.
     private static final int EVENT_NETLINK_LINKPROPERTIES_CHANGED = 5;
 
@@ -126,6 +137,7 @@
      * Non-final member variables accessed only from within our StateMachine.
      */
     private IpReachabilityMonitor mIpReachabilityMonitor;
+    private BaseDhcpStateMachine mDhcpStateMachine;
     private DhcpResults mDhcpResults;
     private StaticIpConfiguration mStaticIpConfig;
 
@@ -209,17 +221,16 @@
         sendMessage(CMD_CONFIRM);
     }
 
+    public void completedPreDhcpAction() {
+        sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE);
+    }
+
     public LinkProperties getLinkProperties() {
         synchronized (mLock) {
             return new LinkProperties(mLinkProperties);
         }
     }
 
-    // TODO: Kill with fire once DHCPv4/static config is moved into IpManager.
-    public void updateWithDhcpResults(DhcpResults dhcpResults, int reason) {
-        sendMessage(CMD_UPDATE_DHCPV4_RESULTS, reason, 0, dhcpResults);
-    }
-
 
     /**
      * Internals.
@@ -274,6 +285,12 @@
         return delta;
     }
 
+    private boolean linkPropertiesUnchanged(LinkProperties newLp) {
+        synchronized (mLock) {
+            return Objects.equals(newLp, mLinkProperties);
+        }
+    }
+
     private LinkProperties assembleLinkProperties() {
         // [1] Create a new LinkProperties object to populate.
         LinkProperties newLp = new LinkProperties();
@@ -322,6 +339,29 @@
         return newLp;
     }
 
+    private void clearIPv4Address() {
+        try {
+            final InterfaceConfiguration ifcg = new InterfaceConfiguration();
+            ifcg.setLinkAddress(new LinkAddress("0.0.0.0/0"));
+            mNwService.setInterfaceConfig(mInterfaceName, ifcg);
+        } catch (RemoteException e) {
+            Log.e(TAG, "ALERT: Failed to clear IPv4 address on interface " + mInterfaceName, e);
+        }
+    }
+
+    private void handleIPv4Success(DhcpResults dhcpResults) {
+        mDhcpResults = new DhcpResults(dhcpResults);
+        setLinkProperties(assembleLinkProperties());
+        mCallback.onIPv4ProvisioningSuccess(dhcpResults);
+    }
+
+    private void handleIPv4Failure() {
+        clearIPv4Address();
+        mDhcpResults = null;
+        setLinkProperties(assembleLinkProperties());
+        mCallback.onIPv4ProvisioningFailure();
+    }
+
     class StoppedState extends State {
         @Override
         public void enter() {
@@ -350,6 +390,16 @@
                     setLinkProperties(assembleLinkProperties());
                     break;
 
+                case DhcpStateMachine.CMD_ON_QUIT:
+                    // CMD_ON_QUIT is really more like "EVENT_ON_QUIT".
+                    // Shutting down DHCPv4 progresses simultaneously with
+                    // transitioning to StoppedState, so we can receive this
+                    // message after we've already transitioned here.
+                    //
+                    // TODO: Figure out if this is actually useful and if not
+                    // expunge it.
+                    break;
+
                 default:
                     return NOT_HANDLED;
             }
@@ -364,6 +414,7 @@
             try {
                 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
                 mNwService.enableIpv6(mInterfaceName);
+                // TODO: Perhaps clearIPv4Address() as well.
             } catch (RemoteException re) {
                 Log.e(TAG, "Unable to change interface settings: " + re);
             } catch (IllegalStateException ie) {
@@ -382,7 +433,20 @@
                         }
                     });
 
-            // TODO: Check mStaticIpConfig and handle accordingly.
+            // If we have a StaticIpConfiguration attempt to apply it and
+            // handle the result accordingly.
+            if (mStaticIpConfig != null) {
+                if (applyStaticIpConfig()) {
+                    handleIPv4Success(new DhcpResults(mStaticIpConfig));
+                } else {
+                    handleIPv4Failure();
+                }
+            } else {
+                // Start DHCPv4.
+                makeDhcpStateMachine();
+                mDhcpStateMachine.registerForPreDhcpNotification();
+                mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
+            }
         }
 
         @Override
@@ -390,6 +454,12 @@
             mIpReachabilityMonitor.stop();
             mIpReachabilityMonitor = null;
 
+            if (mDhcpStateMachine != null) {
+                mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
+                mDhcpStateMachine.doQuit();
+                mDhcpStateMachine = null;
+            }
+
             resetLinkProperties();
         }
 
@@ -401,34 +471,34 @@
                     break;
 
                 case CMD_START:
-                    // TODO: Defer this message to be delivered after a state transition
-                    // to StoppedState.  That way, receiving CMD_START in StartedState
-                    // effects a restart.
-                    Log.e(TAG, "ALERT: START received in StartedState.");
+                    Log.e(TAG, "ALERT: START received in StartedState. Please fix caller.");
                     break;
 
                 case CMD_CONFIRM:
+                    // TODO: Possibly introduce a second type of confirmation
+                    // that both probes (a) on-link neighbors and (b) does
+                    // a DHCPv4 RENEW.  We used to do this on Wi-Fi framework
+                    // roams.
                     if (mCallback.usingIpReachabilityMonitor()) {
                         mIpReachabilityMonitor.probeAll();
                     }
                     break;
 
-                case CMD_UPDATE_DHCPV4_RESULTS:
-                    final DhcpResults dhcpResults = (DhcpResults) msg.obj;
-                    final int reason = msg.arg1;
-                    if (dhcpResults != null) {
-                        mDhcpResults = new DhcpResults(dhcpResults);
-                        setLinkProperties(assembleLinkProperties());
-                        mCallback.onIPv4ProvisioningSuccess(dhcpResults, reason);
-                    } else {
-                        mDhcpResults = null;
-                        setLinkProperties(assembleLinkProperties());
-                        mCallback.onIPv4ProvisioningFailure(reason);
+                case EVENT_PRE_DHCP_ACTION_COMPLETE:
+                    // It's possible to reach here if, for example, someone
+                    // calls completedPreDhcpAction() after provisioning with
+                    // a static IP configuration.
+                    if (mDhcpStateMachine != null) {
+                        mDhcpStateMachine.sendMessage(
+                                DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE);
                     }
                     break;
 
-                case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
+                case EVENT_NETLINK_LINKPROPERTIES_CHANGED: {
                     final LinkProperties newLp = assembleLinkProperties();
+                    if (linkPropertiesUnchanged(newLp)) {
+                        break;
+                    }
                     final ProvisioningChange delta = setLinkProperties(newLp);
 
                     // NOTE: The only receiver of these callbacks currently
@@ -448,7 +518,39 @@
                             mCallback.onLinkPropertiesChange(newLp);
                             break;
                     }
+                    break;
+                }
 
+                case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+                    mCallback.onPreDhcpAction();
+                    break;
+
+                case DhcpStateMachine.CMD_POST_DHCP_ACTION: {
+                    // Note that onPostDhcpAction() is likely to be
+                    // asynchronous, and thus there is no guarantee that we
+                    // will be able to observe any of its effects here.
+                    mCallback.onPostDhcpAction();
+
+                    final DhcpResults dhcpResults = (DhcpResults) msg.obj;
+                    switch (msg.arg1) {
+                        case DhcpStateMachine.DHCP_SUCCESS:
+                            handleIPv4Success(dhcpResults);
+                            break;
+                        case DhcpStateMachine.DHCP_FAILURE:
+                            handleIPv4Failure();
+                            break;
+                        default:
+                            Log.e(TAG, "Unknown CMD_POST_DHCP_ACTION status:" + msg.arg1);
+                    }
+                    break;
+                }
+
+                case DhcpStateMachine.CMD_ON_QUIT:
+                    // CMD_ON_QUIT is really more like "EVENT_ON_QUIT".
+                    // Regardless, we ignore it.
+                    //
+                    // TODO: Figure out if this is actually useful and if not
+                    // expunge it.
                     break;
 
                 default:
@@ -457,5 +559,37 @@
             return HANDLED;
         }
 
+        private boolean applyStaticIpConfig() {
+            final InterfaceConfiguration ifcg = new InterfaceConfiguration();
+            ifcg.setLinkAddress(mStaticIpConfig.ipAddress);
+            ifcg.setInterfaceUp();
+            try {
+                mNwService.setInterfaceConfig(mInterfaceName, ifcg);
+                if (DBG) Log.d(TAG, "Static IP configuration succeeded");
+            } catch (IllegalStateException | RemoteException e) {
+                Log.e(TAG, "Static IP configuration failed: ", e);
+                return false;
+            }
+
+            return true;
+        }
+
+        private void makeDhcpStateMachine() {
+            final boolean usingLegacyDhcp = (Settings.Global.getInt(
+                    mContext.getContentResolver(),
+                    Settings.Global.LEGACY_DHCP_CLIENT, 0) == 1);
+
+            if (usingLegacyDhcp) {
+                mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(
+                        mContext,
+                        IpManager.this,
+                        mInterfaceName);
+            } else {
+                mDhcpStateMachine = DhcpClient.makeDhcpStateMachine(
+                        mContext,
+                        IpManager.this,
+                        mInterfaceName);
+            }
+        }
     }
 }
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 3ad26d3..071ec1b0 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -1,3 +1,7 @@
+#########################################################################
+# Build FrameworksServicesTests package
+#########################################################################
+
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -11,6 +15,7 @@
     services.core \
     services.devicepolicy \
     services.net \
+    services.usage \
     easymocklib \
     guava \
     android-support-test \
@@ -22,5 +27,38 @@
 
 LOCAL_CERTIFICATE := platform
 
+LOCAL_JNI_SHARED_LIBRARIES := \
+    libapfjni \
+    libnativehelper
+
 include $(BUILD_PACKAGE)
 
+#########################################################################
+# Build JNI Shared Library
+#########################################################################
+
+LOCAL_PATH:= $(LOCAL_PATH)/jni
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -Wall -Werror
+
+LOCAL_C_INCLUDES := \
+  libpcap \
+  hardware/google/apf
+
+LOCAL_SRC_FILES := apf_jni.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+  libnativehelper \
+  liblog
+
+LOCAL_STATIC_LIBRARIES := \
+  libpcap \
+  libapf
+
+LOCAL_MODULE := libapfjni
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/tests/servicestests/jni/apf_jni.cpp b/services/tests/servicestests/jni/apf_jni.cpp
new file mode 100644
index 0000000..7d142eb
--- /dev/null
+++ b/services/tests/servicestests/jni/apf_jni.cpp
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+#include <JNIHelp.h>
+#include <ScopedUtfChars.h>
+#include <jni.h>
+#include <pcap.h>
+#include <stdlib.h>
+#include <string>
+#include <utils/Log.h>
+
+#include "apf_interpreter.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+// JNI function acting as simply call-through to native APF interpreter.
+static jint com_android_server_ApfTest_apfSimulate(
+        JNIEnv* env, jclass, jbyteArray program, jbyteArray packet, jint filter_age) {
+    return accept_packet(
+            (uint8_t*)env->GetByteArrayElements(program, NULL),
+            env->GetArrayLength(program),
+            (uint8_t*)env->GetByteArrayElements(packet, NULL),
+            env->GetArrayLength(packet),
+            filter_age);
+}
+
+class ScopedPcap {
+  public:
+    ScopedPcap(pcap_t* pcap) : pcap_ptr(pcap) {}
+    ~ScopedPcap() {
+        pcap_close(pcap_ptr);
+    }
+
+    pcap_t* get() const { return pcap_ptr; };
+  private:
+    pcap_t* const pcap_ptr;
+};
+
+class ScopedFILE {
+  public:
+    ScopedFILE(FILE* fp) : file(fp) {}
+    ~ScopedFILE() {
+        fclose(file);
+    }
+
+    FILE* get() const { return file; };
+  private:
+    FILE* const file;
+};
+
+static void throwException(JNIEnv* env, const std::string& error) {
+    jclass newExcCls = env->FindClass("java/lang/IllegalStateException");
+    if (newExcCls == 0) {
+      abort();
+      return;
+    }
+    env->ThrowNew(newExcCls, error.c_str());
+}
+
+static jstring com_android_server_ApfTest_compileToBpf(JNIEnv* env, jclass, jstring jfilter) {
+    ScopedUtfChars filter(env, jfilter);
+    std::string bpf_string;
+    ScopedPcap pcap(pcap_open_dead(DLT_EN10MB, 65535));
+    if (pcap.get() == NULL) {
+        throwException(env, "pcap_open_dead failed");
+        return NULL;
+    }
+
+    // Compile "filter" to a BPF program
+    bpf_program bpf;
+    if (pcap_compile(pcap.get(), &bpf, filter.c_str(), 0, PCAP_NETMASK_UNKNOWN)) {
+        throwException(env, "pcap_compile failed");
+        return NULL;
+    }
+
+    // Translate BPF program to human-readable format
+    const struct bpf_insn* insn = bpf.bf_insns;
+    for (uint32_t i = 0; i < bpf.bf_len; i++) {
+        bpf_string += bpf_image(insn++, i);
+        bpf_string += "\n";
+    }
+
+    return env->NewStringUTF(bpf_string.c_str());
+}
+
+static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, jstring jfilter,
+        jstring jpcap_filename, jbyteArray japf_program) {
+    ScopedUtfChars filter(env, jfilter);
+    ScopedUtfChars pcap_filename(env, jpcap_filename);
+    const uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL);
+    const uint32_t apf_program_len = env->GetArrayLength(japf_program);
+
+    // Open pcap file for BPF filtering
+    ScopedFILE bpf_fp(fopen(pcap_filename.c_str(), "rb"));
+    char pcap_error[PCAP_ERRBUF_SIZE];
+    ScopedPcap bpf_pcap(pcap_fopen_offline(bpf_fp.get(), pcap_error));
+    if (bpf_pcap.get() == NULL) {
+        throwException(env, "pcap_fopen_offline failed: " + std::string(pcap_error));
+        return false;
+    }
+
+    // Open pcap file for APF filtering
+    ScopedFILE apf_fp(fopen(pcap_filename.c_str(), "rb"));
+    ScopedPcap apf_pcap(pcap_fopen_offline(apf_fp.get(), pcap_error));
+    if (apf_pcap.get() == NULL) {
+        throwException(env, "pcap_fopen_offline failed: " + std::string(pcap_error));
+        return false;
+    }
+
+    // Compile "filter" to a BPF program
+    bpf_program bpf;
+    if (pcap_compile(bpf_pcap.get(), &bpf, filter.c_str(), 0, PCAP_NETMASK_UNKNOWN)) {
+        throwException(env, "pcap_compile failed");
+        return false;
+    }
+
+    // Install BPF filter on bpf_pcap
+    if (pcap_setfilter(bpf_pcap.get(), &bpf)) {
+        throwException(env, "pcap_setfilter failed");
+        return false;
+    }
+
+    while (1) {
+        pcap_pkthdr bpf_header, apf_header;
+        // Run BPF filter to the next matching packet.
+        const uint8_t* bpf_packet = pcap_next(bpf_pcap.get(), &bpf_header);
+
+        // Run APF filter to the next matching packet.
+        const uint8_t* apf_packet;
+        do {
+            apf_packet = pcap_next(apf_pcap.get(), &apf_header);
+        } while (apf_packet != NULL && !accept_packet(
+                apf_program, apf_program_len, apf_packet, apf_header.len, 0));
+
+        // Make sure both filters matched the same packet.
+        if (apf_packet == NULL && bpf_packet == NULL)
+             break;
+        if (apf_packet == NULL || bpf_packet == NULL)
+             return false;
+        if (apf_header.len != bpf_header.len ||
+                apf_header.ts.tv_sec != bpf_header.ts.tv_sec ||
+                apf_header.ts.tv_usec != bpf_header.ts.tv_usec ||
+                memcmp(apf_packet, bpf_packet, apf_header.len))
+            return false;
+    }
+    return true;
+}
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+    JNIEnv *env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        ALOGE("ERROR: GetEnv failed");
+        return -1;
+    }
+
+    static JNINativeMethod gMethods[] = {
+            { "apfSimulate", "([B[BI)I",
+                    (void*)com_android_server_ApfTest_apfSimulate },
+            { "compileToBpf", "(Ljava/lang/String;)Ljava/lang/String;",
+                    (void*)com_android_server_ApfTest_compileToBpf },
+            { "compareBpfApf", "(Ljava/lang/String;Ljava/lang/String;[B)Z",
+                    (void*)com_android_server_ApfTest_compareBpfApf },
+    };
+
+    jniRegisterNativeMethods(env, "com/android/server/ApfTest",
+            gMethods, ARRAY_SIZE(gMethods));
+
+    return JNI_VERSION_1_6;
+}
diff --git a/services/tests/servicestests/res/raw/apf.pcap b/services/tests/servicestests/res/raw/apf.pcap
new file mode 100644
index 0000000..963165f
--- /dev/null
+++ b/services/tests/servicestests/res/raw/apf.pcap
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/ApfTest.java b/services/tests/servicestests/src/com/android/server/ApfTest.java
new file mode 100644
index 0000000..640a6c9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/ApfTest.java
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.frameworks.servicestests.R;
+import android.net.apf.ApfGenerator;
+import android.net.apf.ApfGenerator.IllegalInstructionException;
+import android.net.apf.ApfGenerator.Register;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+/**
+ * Tests for APF program generator and interpreter.
+ *
+ * Build, install and run with:
+ *  runtest frameworks-services -c com.android.server.ApfTest
+ */
+public class ApfTest extends AndroidTestCase {
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        // Load up native shared library containing APF interpreter exposed via JNI.
+        System.loadLibrary("apfjni");
+    }
+
+    // Expected return codes from APF interpreter.
+    private final static int PASS = 1;
+    private final static int DROP = 0;
+    // Interpreter will just accept packets without link layer headers, so pad fake packet to at
+    // least the minimum packet size.
+    private final static int MIN_PKT_SIZE = 15;
+
+    private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
+        assertEquals(expected, apfSimulate(program, packet, filterAge));
+    }
+
+    private void assertPass(byte[] program, byte[] packet, int filterAge) {
+        assertVerdict(PASS, program, packet, filterAge);
+    }
+
+    private void assertDrop(byte[] program, byte[] packet, int filterAge) {
+        assertVerdict(DROP, program, packet, filterAge);
+    }
+
+    private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
+            throws IllegalInstructionException {
+        assertEquals(expected, apfSimulate(gen.generate(), packet, filterAge));
+    }
+
+    private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
+            throws IllegalInstructionException {
+        assertVerdict(PASS, gen, packet, filterAge);
+    }
+
+    private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge)
+            throws IllegalInstructionException {
+        assertVerdict(DROP, gen, packet, filterAge);
+    }
+
+    private void assertPass(ApfGenerator gen)
+            throws IllegalInstructionException {
+        assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0);
+    }
+
+    private void assertDrop(ApfGenerator gen)
+            throws IllegalInstructionException {
+        assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0);
+    }
+
+    /**
+     * Test each instruction by generating a program containing the instruction,
+     * generating bytecode for that program and running it through the
+     * interpreter to verify it functions correctly.
+     */
+    @LargeTest
+    public void testApfInstructions() throws IllegalInstructionException {
+        // Empty program should pass because having the program counter reach the
+        // location immediately after the program indicates the packet should be
+        // passed to the AP.
+        ApfGenerator gen = new ApfGenerator();
+        assertPass(gen);
+
+        // Test jumping to pass label.
+        gen = new ApfGenerator();
+        gen.addJump(gen.PASS_LABEL);
+        byte[] program = gen.generate();
+        assertEquals(1, program.length);
+        assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
+        assertPass(program, new byte[MIN_PKT_SIZE], 0);
+
+        // Test jumping to drop label.
+        gen = new ApfGenerator();
+        gen.addJump(gen.DROP_LABEL);
+        program = gen.generate();
+        assertEquals(2, program.length);
+        assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
+        assertEquals(1, program[1]);
+        assertDrop(program, new byte[15], 15);
+
+        // Test jumping if equal to 0.
+        gen = new ApfGenerator();
+        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test jumping if not equal to 0.
+        gen = new ApfGenerator();
+        gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
+        assertPass(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1);
+        gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test jumping if registers equal.
+        gen = new ApfGenerator();
+        gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test jumping if registers not equal.
+        gen = new ApfGenerator();
+        gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
+        assertPass(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1);
+        gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test load immediate.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test add.
+        gen = new ApfGenerator();
+        gen.addAdd(1234567890);
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test subtract.
+        gen = new ApfGenerator();
+        gen.addAdd(-1234567890);
+        gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test or.
+        gen = new ApfGenerator();
+        gen.addOr(1234567890);
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test and.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addAnd(123456789);
+        gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test left shift.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLeftShift(1);
+        gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test right shift.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addRightShift(1);
+        gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test multiply.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addMul(2);
+        gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test divide.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addDiv(2);
+        gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test divide by zero.
+        gen = new ApfGenerator();
+        gen.addDiv(0);
+        gen.addJump(gen.DROP_LABEL);
+        assertPass(gen);
+
+        // Test add.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 1234567890);
+        gen.addAddR1();
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test subtract.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, -1234567890);
+        gen.addAddR1();
+        gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test or.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 1234567890);
+        gen.addOrR1();
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test and.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(Register.R1, 123456789);
+        gen.addAndR1();
+        gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test left shift.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(Register.R1, 1);
+        gen.addLeftShiftR1();
+        gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test right shift.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(Register.R1, -1);
+        gen.addLeftShiftR1();
+        gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test multiply.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(Register.R1, 2);
+        gen.addMulR1();
+        gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test divide.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(Register.R1, 2);
+        gen.addDivR1();
+        gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test divide by zero.
+        gen = new ApfGenerator();
+        gen.addDivR1();
+        gen.addJump(gen.DROP_LABEL);
+        assertPass(gen);
+
+        // Test byte load.
+        gen = new ApfGenerator();
+        gen.addLoad8(Register.R0, 1);
+        gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
+        assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
+
+        // Test out of bounds load.
+        gen = new ApfGenerator();
+        gen.addLoad8(Register.R0, 16);
+        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
+        assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
+
+        // Test half-word load.
+        gen = new ApfGenerator();
+        gen.addLoad16(Register.R0, 1);
+        gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
+        assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
+
+        // Test word load.
+        gen = new ApfGenerator();
+        gen.addLoad32(Register.R0, 1);
+        gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
+        assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
+
+        // Test byte indexed load.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 1);
+        gen.addLoad8Indexed(Register.R0, 0);
+        gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
+        assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
+
+        // Test out of bounds indexed load.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 8);
+        gen.addLoad8Indexed(Register.R0, 8);
+        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
+        assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
+
+        // Test half-word indexed load.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 1);
+        gen.addLoad16Indexed(Register.R0, 0);
+        gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
+        assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
+
+        // Test word indexed load.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 1);
+        gen.addLoad32Indexed(Register.R0, 0);
+        gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
+        assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
+
+        // Test jumping if greater than.
+        gen = new ApfGenerator();
+        gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
+        assertPass(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1);
+        gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test jumping if less than.
+        gen = new ApfGenerator();
+        gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
+        assertPass(gen);
+        gen = new ApfGenerator();
+        gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test jumping if any bits set.
+        gen = new ApfGenerator();
+        gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
+        assertPass(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1);
+        gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
+        assertDrop(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 3);
+        gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test jumping if register greater than.
+        gen = new ApfGenerator();
+        gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
+        assertPass(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 2);
+        gen.addLoadImmediate(Register.R1, 1);
+        gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test jumping if register less than.
+        gen = new ApfGenerator();
+        gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
+        assertPass(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 1);
+        gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test jumping if any bits set in register.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 3);
+        gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
+        assertPass(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 3);
+        gen.addLoadImmediate(Register.R0, 1);
+        gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
+        assertDrop(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 3);
+        gen.addLoadImmediate(Register.R0, 3);
+        gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test load from memory.
+        gen = new ApfGenerator();
+        gen.addLoadFromMemory(Register.R0, 0);
+        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test store to memory.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 1234567890);
+        gen.addStoreToMemory(Register.R1, 12);
+        gen.addLoadFromMemory(Register.R0, 12);
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test filter age pre-filled memory.
+        gen = new ApfGenerator();
+        gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
+
+        // Test packet size pre-filled memory.
+        gen = new ApfGenerator();
+        gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
+        gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test IPv4 header size pre-filled memory.
+        gen = new ApfGenerator();
+        gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+        gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
+        assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
+
+        // Test not.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addNot(Register.R0);
+        gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test negate.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addNeg(Register.R0);
+        gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test move.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 1234567890);
+        gen.addMove(Register.R0);
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addMove(Register.R1);
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test swap.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R1, 1234567890);
+        gen.addSwap();
+        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
+        assertDrop(gen);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addSwap();
+        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
+        assertDrop(gen);
+
+        // Test jump if bytes not equal.
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1);
+        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
+        program = gen.generate();
+        assertEquals(6, program.length);
+        assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
+        assertEquals(1, program[1]);
+        assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
+        assertEquals(1, program[3]);
+        assertEquals(1, program[4]);
+        assertEquals(123, program[5]);
+        assertDrop(program, new byte[MIN_PKT_SIZE], 0);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1);
+        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
+        byte[] packet123 = new byte[]{0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
+        assertPass(gen, packet123, 0);
+        gen = new ApfGenerator();
+        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
+        assertDrop(gen, packet123, 0);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1);
+        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
+        byte[] packet12345 = new byte[]{0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
+        assertDrop(gen, packet12345, 0);
+        gen = new ApfGenerator();
+        gen.addLoadImmediate(Register.R0, 1);
+        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
+        assertPass(gen, packet12345, 0);
+    }
+
+    /**
+     * Generate some BPF programs, translate them to APF, then run APF and BPF programs
+     * over packet traces and verify both programs filter out the same packets.
+     */
+    @LargeTest
+    public void testApfAgainstBpf() throws Exception {
+        String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
+                "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
+                "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000",
+                "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" };
+        String pcap_filename = stageFile(R.raw.apf);
+        for (String tcpdump_filter : tcpdump_filters) {
+            byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter));
+            assertTrue("Failed to match for filter: " + tcpdump_filter,
+                    compareBpfApf(tcpdump_filter, pcap_filename, apf_program));
+        }
+    }
+
+    /**
+     * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
+     * copy that resource into the app's data directory and return the path to it.
+     */
+    private String stageFile(int rawId) throws Exception {
+        File file = new File(getContext().getFilesDir(), "staged_file");
+        new File(file.getParent()).mkdirs();
+        InputStream in = null;
+        OutputStream out = null;
+        try {
+            in = getContext().getResources().openRawResource(rawId);
+            out = new FileOutputStream(file);
+            Streams.copy(in, out);
+        } finally {
+            if (in != null) in.close();
+            if (out != null) out.close();
+        }
+        return file.getAbsolutePath();
+    }
+
+    /**
+     * Call the APF interpreter the run {@code program} on {@code packet} pretending the
+     * filter was installed {@code filter_age} seconds ago.
+     */
+    private native static int apfSimulate(byte[] program, byte[] packet, int filter_age);
+
+    /**
+     * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
+     * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
+     */
+    private native static String compileToBpf(String filter);
+
+    /**
+     * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
+     * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
+     * at the same time using APF program {@code apf_program}.  Return {@code true} if
+     * both APF and BPF programs filter out exactly the same packets.
+     */
+    private native static boolean compareBpfApf(String filter, String pcap_filename,
+            byte[] apf_program);
+}
diff --git a/services/tests/servicestests/src/com/android/server/Bpf2Apf.java b/services/tests/servicestests/src/com/android/server/Bpf2Apf.java
new file mode 100644
index 0000000..29594a8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/Bpf2Apf.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.net.apf.ApfGenerator;
+import android.net.apf.ApfGenerator.IllegalInstructionException;
+import android.net.apf.ApfGenerator.Register;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * BPF to APF translator.
+ *
+ * Note: This is for testing purposes only and is not guaranteed to support
+ *       translation of all BPF programs.
+ *
+ * Example usage:
+ *   javac net/java/android/net/apf/ApfGenerator.java \
+ *         tests/servicestests/src/com/android/server/Bpf2Apf.java
+ *   sudo tcpdump -i em1 -d icmp | java -classpath tests/servicestests/src:net/java \
+ *                                      com.android.server.Bpf2Apf
+ */
+public class Bpf2Apf {
+    private static int parseImm(String line, String arg) {
+        if (!arg.startsWith("#0x")) {
+            throw new IllegalArgumentException("Unhandled instruction: " + line);
+        }
+        final long val_long = Long.parseLong(arg.substring(3), 16);
+        if (val_long < 0 || val_long > Long.parseLong("ffffffff", 16)) {
+            throw new IllegalArgumentException("Unhandled instruction: " + line);
+        }
+        return new Long((val_long << 32) >> 32).intValue();
+    }
+
+    /**
+     * Convert a single line of "tcpdump -d" (human readable BPF program dump) {@code line} into
+     * APF instruction(s) and append them to {@code gen}. Here's an example line:
+     * (001) jeq      #0x86dd          jt 2    jf 7
+     */
+    private static void convertLine(String line, ApfGenerator gen)
+            throws IllegalInstructionException {
+        if (line.indexOf("(") != 0 || line.indexOf(")") != 4 || line.indexOf(" ") != 5) {
+            throw new IllegalArgumentException("Unhandled instruction: " + line);
+        }
+        int label = Integer.parseInt(line.substring(1, 4));
+        gen.defineLabel(Integer.toString(label));
+        String opcode = line.substring(6, 10).trim();
+        String arg = line.substring(15, Math.min(32, line.length())).trim();
+        switch (opcode) {
+            case "ld":
+            case "ldh":
+            case "ldb":
+            case "ldx":
+            case "ldxb":
+            case "ldxh":
+                Register dest = opcode.contains("x") ? Register.R1 : Register.R0;
+                if (arg.equals("4*([14]&0xf)")) {
+                    if (!opcode.equals("ldxb")) {
+                        throw new IllegalArgumentException("Unhandled instruction: " + line);
+                    }
+                    gen.addLoadFromMemory(dest, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+                    break;
+                }
+                if (arg.equals("#pktlen")) {
+                    if (!opcode.equals("ld")) {
+                        throw new IllegalArgumentException("Unhandled instruction: " + line);
+                    }
+                    gen.addLoadFromMemory(dest, gen.PACKET_SIZE_MEMORY_SLOT);
+                    break;
+                }
+                if (arg.startsWith("#0x")) {
+                    if (!opcode.equals("ld")) {
+                        throw new IllegalArgumentException("Unhandled instruction: " + line);
+                    }
+                    gen.addLoadImmediate(dest, parseImm(line, arg));
+                    break;
+                }
+                if (arg.startsWith("M[")) {
+                    if (!opcode.startsWith("ld")) {
+                        throw new IllegalArgumentException("Unhandled instruction: " + line);
+                    }
+                    int memory_slot = Integer.parseInt(arg.substring(2, arg.length() - 1));
+                    if (memory_slot < 0 || memory_slot >= gen.MEMORY_SLOTS ||
+                            // Disallow use of pre-filled slots as BPF programs might
+                            // wrongfully assume they're initialized to 0.
+                            (memory_slot >= gen.FIRST_PREFILLED_MEMORY_SLOT &&
+                                    memory_slot <= gen.LAST_PREFILLED_MEMORY_SLOT)) {
+                        throw new IllegalArgumentException("Unhandled instruction: " + line);
+                    }
+                    gen.addLoadFromMemory(dest, memory_slot);
+                    break;
+                }
+                if (arg.startsWith("[x + ")) {
+                    int offset = Integer.parseInt(arg.substring(5, arg.length() - 1));
+                    switch (opcode) {
+                        case "ld":
+                        case "ldx":
+                            gen.addLoad32Indexed(dest, offset);
+                            break;
+                        case "ldh":
+                        case "ldxh":
+                            gen.addLoad16Indexed(dest, offset);
+                            break;
+                        case "ldb":
+                        case "ldxb":
+                            gen.addLoad8Indexed(dest, offset);
+                            break;
+                    }
+                } else {
+                    int offset = Integer.parseInt(arg.substring(1, arg.length() - 1));
+                    switch (opcode) {
+                        case "ld":
+                        case "ldx":
+                            gen.addLoad32(dest, offset);
+                            break;
+                        case "ldh":
+                        case "ldxh":
+                            gen.addLoad16(dest, offset);
+                            break;
+                        case "ldb":
+                        case "ldxb":
+                            gen.addLoad8(dest, offset);
+                            break;
+                    }
+                }
+                break;
+            case "st":
+            case "stx":
+                Register src = opcode.contains("x") ? Register.R1 : Register.R0;
+                if (!arg.startsWith("M[")) {
+                    throw new IllegalArgumentException("Unhandled instruction: " + line);
+                }
+                int memory_slot = Integer.parseInt(arg.substring(2, arg.length() - 1));
+                if (memory_slot < 0 || memory_slot >= gen.MEMORY_SLOTS ||
+                        // Disallow overwriting pre-filled slots
+                        (memory_slot >= gen.FIRST_PREFILLED_MEMORY_SLOT &&
+                                memory_slot <= gen.LAST_PREFILLED_MEMORY_SLOT)) {
+                    throw new IllegalArgumentException("Unhandled instruction: " + line);
+                }
+                gen.addStoreToMemory(src, memory_slot);
+                break;
+            case "add":
+            case "and":
+            case "or":
+            case "sub":
+                if (arg.equals("x")) {
+                    switch(opcode) {
+                        case "add":
+                            gen.addAddR1();
+                            break;
+                        case "and":
+                            gen.addAndR1();
+                            break;
+                        case "or":
+                            gen.addOrR1();
+                            break;
+                        case "sub":
+                            gen.addNeg(Register.R1);
+                            gen.addAddR1();
+                            gen.addNeg(Register.R1);
+                            break;
+                    }
+                } else {
+                    int imm = parseImm(line, arg);
+                    switch(opcode) {
+                        case "add":
+                            gen.addAdd(imm);
+                            break;
+                        case "and":
+                            gen.addAnd(imm);
+                            break;
+                        case "or":
+                            gen.addOr(imm);
+                            break;
+                        case "sub":
+                            gen.addAdd(-imm);
+                            break;
+                    }
+                }
+                break;
+            case "jeq":
+            case "jset":
+            case "jgt":
+            case "jge":
+                int val = 0;
+                boolean reg_compare;
+                if (arg.startsWith("x")) {
+                    reg_compare = true;
+                } else {
+                    reg_compare = false;
+                    val = parseImm(line, arg);
+                }
+                int jt_offset = line.indexOf("jt");
+                int jf_offset = line.indexOf("jf");
+                String true_label = line.substring(jt_offset + 2, jf_offset).trim();
+                String false_label = line.substring(jf_offset + 2).trim();
+                boolean true_label_is_fallthrough = Integer.parseInt(true_label) == label + 1;
+                boolean false_label_is_fallthrough = Integer.parseInt(false_label) == label + 1;
+                if (true_label_is_fallthrough && false_label_is_fallthrough)
+                    break;
+                switch (opcode) {
+                    case "jeq":
+                        if (!true_label_is_fallthrough) {
+                            if (reg_compare) {
+                                gen.addJumpIfR0EqualsR1(true_label);
+                            } else {
+                                gen.addJumpIfR0Equals(val, true_label);
+                            }
+                        }
+                        if (!false_label_is_fallthrough) {
+                            if (!true_label_is_fallthrough) {
+                                gen.addJump(false_label);
+                            } else if (reg_compare) {
+                                gen.addJumpIfR0NotEqualsR1(false_label);
+                            } else {
+                                gen.addJumpIfR0NotEquals(val, false_label);
+                            }
+                        }
+                        break;
+                    case "jset":
+                        if (reg_compare) {
+                            gen.addJumpIfR0AnyBitsSetR1(true_label);
+                        } else {
+                            gen.addJumpIfR0AnyBitsSet(val, true_label);
+                        }
+                        if (!false_label_is_fallthrough) {
+                            gen.addJump(false_label);
+                        }
+                        break;
+                    case "jgt":
+                        if (!true_label_is_fallthrough ||
+                                // We have no less-than-or-equal-to register to register
+                                // comparison instruction, so in this case we'll jump
+                                // around an unconditional jump.
+                                (!false_label_is_fallthrough && reg_compare)) {
+                            if (reg_compare) {
+                                gen.addJumpIfR0GreaterThanR1(true_label);
+                            } else {
+                                gen.addJumpIfR0GreaterThan(val, true_label);
+                            }
+                        }
+                        if (!false_label_is_fallthrough) {
+                            if (!true_label_is_fallthrough || reg_compare) {
+                                gen.addJump(false_label);
+                            } else {
+                                gen.addJumpIfR0LessThan(val + 1, false_label);
+                            }
+                        }
+                        break;
+                    case "jge":
+                        if (!false_label_is_fallthrough ||
+                                // We have no greater-than-or-equal-to register to register
+                                // comparison instruction, so in this case we'll jump
+                                // around an unconditional jump.
+                                (!true_label_is_fallthrough && reg_compare)) {
+                            if (reg_compare) {
+                                gen.addJumpIfR0LessThanR1(false_label);
+                            } else {
+                                gen.addJumpIfR0LessThan(val, false_label);
+                            }
+                        }
+                        if (!true_label_is_fallthrough) {
+                            if (!false_label_is_fallthrough || reg_compare) {
+                                gen.addJump(true_label);
+                            } else {
+                                gen.addJumpIfR0GreaterThan(val - 1, true_label);
+                            }
+                        }
+                        break;
+                }
+                break;
+            case "ret":
+                if (arg.equals("#0")) {
+                    gen.addJump(gen.DROP_LABEL);
+                } else {
+                    gen.addJump(gen.PASS_LABEL);
+                }
+                break;
+            case "tax":
+                gen.addMove(Register.R1);
+                break;
+            case "txa":
+                gen.addMove(Register.R0);
+                break;
+            default:
+                throw new IllegalArgumentException("Unhandled instruction: " + line);
+        }
+    }
+
+    /**
+     * Convert the output of "tcpdump -d" (human readable BPF program dump) {@code bpf} into an APF
+     * program and return it.
+     */
+    public static byte[] convert(String bpf) throws IllegalInstructionException {
+        ApfGenerator gen = new ApfGenerator();
+        for (String line : bpf.split("\\n")) convertLine(line, gen);
+        return gen.generate();
+    }
+
+    /**
+     * Convert the output of "tcpdump -d" (human readable BPF program dump) piped in stdin into an
+     * APF program and output it via stdout.
+     */
+    public static void main(String[] args) throws Exception {
+        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+        String line = null;
+        StringBuilder responseData = new StringBuilder();
+        ApfGenerator gen = new ApfGenerator();
+        while ((line = in.readLine()) != null) convertLine(line, gen);
+        System.out.write(gen.generate());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
index c174a92..313dc8b 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
@@ -20,6 +20,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Bundle;
+import android.os.PersistableBundle;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.AndroidTestCase;
@@ -65,10 +66,6 @@
                 SyncOperation.REASON_PERIODIC,
                 "authority1",
                 b1,
-                100, /* run time from now*/
-                10, /* flex */
-                1000,
-                10000,
                 false);
 
         // Same as op1 but different time infos
@@ -77,10 +74,6 @@
                 SyncOperation.REASON_PERIODIC,
                 "authority1",
                 b1,
-                200,
-                20,
-                2000,
-                20000,
                 false);
 
         // Same as op1 but different authority
@@ -89,10 +82,6 @@
                 SyncOperation.REASON_PERIODIC,
                 "authority2",
                 b1,
-                100,
-                10,
-                1000,
-                10000,
                 false);
 
         // Same as op1 but different account
@@ -101,10 +90,6 @@
                 SyncOperation.REASON_PERIODIC,
                 "authority1",
                 b1,
-                100,
-                10,
-                1000,
-                10000,
                 false);
 
         // Same as op1 but different bundle
@@ -113,10 +98,6 @@
                 SyncOperation.REASON_PERIODIC,
                 "authority1",
                 b2,
-                100,
-                10,
-                1000,
-                10000,
                 false);
 
         assertEquals(op1.key, op2.key);
@@ -126,66 +107,52 @@
     }
 
     @SmallTest
-    public void testCompareTo() {
-        long soon = 1000;
-        long soonFlex = 50;
-        long after = 1500;
-        long afterFlex = 100;
-        SyncOperation op1 = new SyncOperation(mDummy, 0, 0, "foo", 0, SyncOperation.REASON_PERIODIC,
-                "authority1", mEmpty, soon, soonFlex, mUnimportantLong, mUnimportantLong, true);
+    public void testConversionToExtras() {
+        Account account1 = new Account("account1", "type1");
+        Bundle b1 = new Bundle();
+        b1.putParcelable("acc", account1);
+        b1.putString("str", "String");
 
-        // Interval disjoint from and after op1.
-        SyncOperation op2 = new SyncOperation(mDummy, 0, 0, "foo", 0, SyncOperation.REASON_PERIODIC,
-                "authority1", mEmpty, after, afterFlex, mUnimportantLong, mUnimportantLong, true);
+        SyncOperation op1 = new SyncOperation(account1, 0,
+                1, "foo", 0,
+                SyncOperation.REASON_PERIODIC,
+                "authority1",
+                b1,
+                false);
 
-        // Interval equivalent to op1, but expedited.
-        Bundle b2 = new Bundle();
-        b2.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
-        SyncOperation op3 = new SyncOperation(mDummy, 0, 0, "foo", 0, 0,
-                "authority1", b2, -1, soonFlex, mUnimportantLong, mUnimportantLong, true);
+        PersistableBundle pb = op1.toJobInfoExtras();
+        SyncOperation op2 = SyncOperation.maybeCreateFromJobExtras(pb);
 
-        // Interval overlaps but not equivalent to op1.
-        SyncOperation op4 = new SyncOperation(mDummy, 0, 0, "foo", 0, SyncOperation.REASON_PERIODIC,
-                "authority1", mEmpty, soon + 100, soonFlex + 100, mUnimportantLong, mUnimportantLong, true);
-
-        assertTrue(op1.compareTo(op2) == -1);
-        assertTrue("less than not transitive.", op2.compareTo(op1) == 1);
-        assertTrue("Expedited sync not smaller than non-expedited.", op1.compareTo(op3) == 1);
-        assertTrue("greater than not transitive. ", op3.compareTo(op1) == -1);
-        assertTrue("overlapping intervals not correctly compared.", op1.compareTo(op4) == -1);
-        assertTrue("equality not transitive.", op4.compareTo(op1) == 1);
+        assertTrue("Account fields in extras not persisted.",
+                account1.equals(op2.extras.get("acc")));
+        assertTrue("Fields in extras not persisted", "String".equals(op2.extras.getString("str")));
     }
 
     @SmallTest
-    public void testCopyConstructor() {
-        long fiveSecondsFromNow = 5 * 1000L;
-        long twoSecondsFlex = 2 * 1000L;
-        long eightSeconds = 8 * 1000L;
-        long fourSeconds = 4 * 1000L;
+    public void testConversionFromExtras() {
+        PersistableBundle extras = new PersistableBundle();
+        SyncOperation op = SyncOperation.maybeCreateFromJobExtras(extras);
+        assertTrue("Non sync operation bundle falsely converted to SyncOperation.", op == null);
+    }
 
-        Bundle withExpedited = new Bundle();
-        withExpedited.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
-        SyncOperation op = new SyncOperation(mDummy, 0, 0, "foo", 0,
-                SyncOperation.REASON_USER_START,
-                mAuthority, withExpedited, fiveSecondsFromNow, twoSecondsFlex,
-                eightSeconds /* backoff */, fourSeconds /* delayUntil */, true);
-        // Create another sync op to be rerun in 5 minutes.
-        long now = SystemClock.elapsedRealtime();
-        SyncOperation copy = new SyncOperation(op, fiveSecondsFromNow * 60);
-        // Copying an expedited sync to be re-run should not keep expedited property.
-        assertFalse("A rescheduled sync based off an expedited should not be expedited!",
-                copy.isExpedited());
-        assertFalse("A rescheduled sync based off an expedited should not have expedited=true in"
-                + "its bundle.",
-                copy.extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false));
-        assertTrue("Copied sync is not respecting new provided run-time.",
-                copy.latestRunTime == (now + fiveSecondsFromNow * 60));
-        assertTrue("A rescheduled sync should not have any flex.",
-                copy.flexTime == 0L);
-        assertTrue("A rescheduled op should honour the old op's backoff.",
-                copy.backoff == eightSeconds);
-        assertTrue("A rescheduled op should honour the old op's delayUntil param.",
-                copy.delayUntil == fourSeconds);
-
+    /**
+     * Tests whether a failed periodic sync operation is converted correctly into a one time
+     * sync operation, and whether the periodic sync can be re-created from the one-time operation.
+     */
+    @SmallTest
+    public void testFailedPeriodicConversion() {
+        SyncStorageEngine.EndPoint ep = new SyncStorageEngine.EndPoint(new Account("name", "type"),
+                "provider", 0);
+        Bundle extras = new Bundle();
+        SyncOperation periodic = new SyncOperation(ep, 0, "package", 0, 0, extras, false, true,
+                SyncOperation.NO_JOB_ID);
+        periodic.periodMillis = 60000;
+        periodic.flexMillis = 10000;
+        SyncOperation oneoff = periodic.createOneTimeSyncOperation();
+        assertFalse("Conversion to oneoff sync failed.", oneoff.isPeriodic);
+        SyncOperation recreated = oneoff.createPeriodicSyncOperation();
+        assertTrue("Conversion to periodic sync failed.", oneoff.isPeriodic);
+        assertEquals("Period not restored", periodic.periodMillis, recreated.periodMillis);
+        assertEquals("Flex not restored", periodic.flexMillis, recreated.flexMillis);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java b/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
index b22eb53..91c0de6 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
@@ -98,288 +98,18 @@
                 SyncOperation.REASON_PERIODIC,
                 SyncStorageEngine.SOURCE_LOCAL,
                 authority,
-                Bundle.EMPTY, time0, 0 /* flex*/, 0, 0, true);
+                Bundle.EMPTY, true);
         long historyId = engine.insertStartSyncEvent(op, time0);
         long time1 = time0 + SyncStorageEngine.MILLIS_IN_4WEEKS * 2;
         engine.stopSyncEvent(historyId, time1 - time0, "yay", 0, 0);
     }
 
-    /**
-     * Test persistence of pending operations.
-     */
-    @MediumTest
-    public void testAppendPending() throws Exception {
-        SyncOperation sop = new SyncOperation(account1,
-                DEFAULT_USER, 0, "foo",
-                SyncOperation.REASON_PERIODIC,
-                SyncStorageEngine.SOURCE_LOCAL, authority1, Bundle.EMPTY,
-                0 /* runtime */, 0 /* flex */, 0 /* backoff */, 0 /* delayuntil */,
-                true /* expedited */);
-        engine.insertIntoPending(sop);
-
-        // Force engine to read from disk.
-        engine.clearAndReadState();
-
-        assertTrue(engine.getPendingOperationCount() == 1);
-        List<SyncStorageEngine.PendingOperation> pops = engine.getPendingOperations();
-        SyncStorageEngine.PendingOperation popRetrieved = pops.get(0);
-        assertEquals(sop.target.account, popRetrieved.target.account);
-        assertEquals(sop.target.provider, popRetrieved.target.provider);
-        assertEquals(sop.target.service, popRetrieved.target.service);
-        assertEquals(sop.target.userId, popRetrieved.target.userId);
-        assertEquals(sop.reason, popRetrieved.reason);
-        assertEquals(sop.syncSource, popRetrieved.syncSource);
-        assertEquals(sop.isExpedited(), popRetrieved.expedited);
-        assert(android.content.PeriodicSync.syncExtrasEquals(sop.extras, popRetrieved.extras));
-    }
-
-    /**
-     * Verify {@link com.android.server.content.SyncStorageEngine#writePendingOperationsLocked()}
-     */
-    public void testWritePendingOperationsLocked() throws Exception {
-        SyncOperation sop = new SyncOperation(account1,
-                DEFAULT_USER, 0, "foo",
-                SyncOperation.REASON_IS_SYNCABLE,
-                SyncStorageEngine.SOURCE_LOCAL, authority1, Bundle.EMPTY,
-                1000L /* runtime */, 57L /* flex */, 0 /* backoff */, 0 /* delayuntil */,
-                true /* expedited */);
-        SyncOperation sop1 = new SyncOperation(account2,
-                DEFAULT_USER, 0, "foo",
-                SyncOperation.REASON_PERIODIC,
-                SyncStorageEngine.SOURCE_LOCAL, authority1, defaultBundle,
-                0 /* runtime */, 0 /* flex */, 20L /* backoff */, 100L /* delayuntil */,
-                false /* expedited */);
-        SyncOperation deleted = new SyncOperation(account2,
-                DEFAULT_USER, 0, "foo",
-                SyncOperation.REASON_SYNC_AUTO,
-                SyncStorageEngine.SOURCE_LOCAL, authority1, Bundle.EMPTY,
-                0 /* runtime */, 0 /* flex */, 20L /* backoff */, 100L /* delayuntil */,
-                false /* expedited */);
-        engine.insertIntoPending(sop);
-        engine.insertIntoPending(sop1);
-        engine.insertIntoPending(deleted);
-
-        SyncStorageEngine.PendingOperation popDeleted = engine.getPendingOperations().get(2);
-        // Free verifying, going to delete it anyway.
-        assertEquals(deleted.target.account, popDeleted.target.account);
-        assertEquals(deleted.target.provider, popDeleted.target.provider);
-        assertEquals(deleted.target.service, popDeleted.target.service);
-        assertEquals(deleted.target.userId, popDeleted.target.userId);
-        assertEquals(deleted.reason, popDeleted.reason);
-        assertEquals(deleted.syncSource, popDeleted.syncSource);
-        assertEquals(deleted.isExpedited(), popDeleted.expedited);
-        assert(android.content.PeriodicSync.syncExtrasEquals(deleted.extras, popDeleted.extras));
-        // Delete one to force write-all
-        engine.deleteFromPending(popDeleted);
-        assertEquals("Delete of pending op failed.", 2, engine.getPendingOperationCount());
-        // If there's dirty pending data (which there is because we deleted a pending op) this
-        // re-writes the entire file.
-        engine.writeAllState();
-
-        engine.clearAndReadState();
-
-        // Validate state read back out.
-        assertEquals("Delete of pending op failed.", 2, engine.getPendingOperationCount());
-
-        List<SyncStorageEngine.PendingOperation> pops = engine.getPendingOperations();
-
-        SyncStorageEngine.PendingOperation popRetrieved = pops.get(0);
-        assertEquals(sop.target.account, popRetrieved.target.account);
-        assertEquals(sop.target.provider, popRetrieved.target.provider);
-        assertEquals(sop.target.service, popRetrieved.target.service);
-        assertEquals(sop.target.userId, popRetrieved.target.userId);
-        assertEquals(sop.reason, popRetrieved.reason);
-        assertEquals(sop.syncSource, popRetrieved.syncSource);
-        assertEquals(sop.isExpedited(), popRetrieved.expedited);
-        assert(android.content.PeriodicSync.syncExtrasEquals(sop.extras, popRetrieved.extras));
-
-        popRetrieved = pops.get(1);
-        assertEquals(sop1.target.account, popRetrieved.target.account);
-        assertEquals(sop1.target.provider, popRetrieved.target.provider);
-        assertEquals(sop1.target.service, popRetrieved.target.service);
-        assertEquals(sop1.target.userId, popRetrieved.target.userId);
-        assertEquals(sop1.reason, popRetrieved.reason);
-        assertEquals(sop1.syncSource, popRetrieved.syncSource);
-        assertEquals(sop1.isExpedited(), popRetrieved.expedited);
-        assert(android.content.PeriodicSync.syncExtrasEquals(sop1.extras, popRetrieved.extras));
-    }
-
-    /**
-     * Test that we can create, remove and retrieve periodic syncs. Backwards compatibility -
-     * periodic syncs with no flex time are no longer used.
-     */
-    @MediumTest
-    public void testPeriodics() throws Exception {
-        final Account account1 = new Account("a@example.com", "example.type");
-        final Account account2 = new Account("b@example.com", "example.type.2");
-        final String authority = "testprovider";
-        final Bundle extras1 = new Bundle();
-        extras1.putString("a", "1");
-        final Bundle extras2 = new Bundle();
-        extras2.putString("a", "2");
-        final int period1 = 200;
-        final int period2 = 1000;
-
-        PeriodicSync sync1 = new PeriodicSync(account1, authority, extras1, period1);
-        EndPoint end1 = new EndPoint(account1, authority, 0);
-
-        PeriodicSync sync2 = new PeriodicSync(account1, authority, extras2, period1);
-        PeriodicSync sync3 = new PeriodicSync(account1, authority, extras2, period2);
-        PeriodicSync sync4 = new PeriodicSync(account2, authority, extras2, period2);
-
-
-
-        removePeriodicSyncs(engine, account1, 0, authority);
-        removePeriodicSyncs(engine, account2, 0, authority);
-        removePeriodicSyncs(engine, account1, 1, authority);
-
-        // this should add two distinct periodic syncs for account1 and one for account2
-        engine.updateOrAddPeriodicSync(new EndPoint(account1, authority, 0), period1, 0, extras1);
-        engine.updateOrAddPeriodicSync(new EndPoint(account1, authority, 0), period1, 0, extras2);
-        engine.updateOrAddPeriodicSync(new EndPoint(account1, authority, 0), period2, 0, extras2);
-        engine.updateOrAddPeriodicSync(new EndPoint(account2, authority, 0), period2, 0, extras2);
-        // add a second user
-        engine.updateOrAddPeriodicSync(new EndPoint(account1, authority, 1), period1, 0, extras2);
-
-        List<PeriodicSync> syncs = engine.getPeriodicSyncs(new EndPoint(account1, authority, 0));
-
-        assertEquals(2, syncs.size());
-
-        assertEquals(sync1, syncs.get(0));
-        assertEquals(sync3, syncs.get(1));
-
-        engine.removePeriodicSync(new EndPoint(account1, authority, 0), extras1);
-
-        syncs = engine.getPeriodicSyncs(new EndPoint(account1, authority, 0));
-        assertEquals(1, syncs.size());
-        assertEquals(sync3, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(new EndPoint(account2, authority, 0));
-        assertEquals(1, syncs.size());
-        assertEquals(sync4, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(new EndPoint(sync2.account, sync2.authority, 1));
-        assertEquals(1, syncs.size());
-        assertEquals(sync2, syncs.get(0));
-    }
-
-    /**
-     * Test that we can create, remove and retrieve periodic syncs with a provided flex time.
-     */
-    @MediumTest
-    public void testPeriodicsV2() throws Exception {
-        final Account account1 = new Account("a@example.com", "example.type");
-        final Account account2 = new Account("b@example.com", "example.type.2");
-        final String authority = "testprovider";
-        final Bundle extras1 = new Bundle();
-        extras1.putString("a", "1");
-        final Bundle extras2 = new Bundle();
-        extras2.putString("a", "2");
-        final int period1 = 200;
-        final int period2 = 1000;
-        final int flex1 = 10;
-        final int flex2 = 100;
-        EndPoint point1 = new EndPoint(account1, authority, 0);
-        EndPoint point2 = new EndPoint(account2, authority, 0);
-        EndPoint point1User2 = new EndPoint(account1, authority, 1);
-
-        PeriodicSync sync1 = new PeriodicSync(account1, authority, extras1, period1, flex1);
-        PeriodicSync sync2 = new PeriodicSync(account1, authority, extras2, period1, flex1);
-        PeriodicSync sync3 = new PeriodicSync(account1, authority, extras2, period2, flex2);
-        PeriodicSync sync4 = new PeriodicSync(account2, authority, extras2, period2, flex2);
-
-        EndPoint target1 = new EndPoint(account1, authority, 0);
-        EndPoint target2 = new EndPoint(account2, authority, 0);
-        EndPoint target1UserB = new EndPoint(account1, authority, 1);
-
-        MockContentResolver mockResolver = new MockContentResolver();
-
-        SyncStorageEngine engine = SyncStorageEngine.newTestInstance(
-                new TestContext(mockResolver, getContext()));
-
-        removePeriodicSyncs(engine, account1, 0, authority);
-        removePeriodicSyncs(engine, account2, 0, authority);
-        removePeriodicSyncs(engine, account1, 1, authority);
-
-        // This should add two distinct periodic syncs for account1 and one for account2
-        engine.updateOrAddPeriodicSync(target1, period1, flex1, extras1);
-        engine.updateOrAddPeriodicSync(target1, period1, flex1, extras2);
-        // Edit existing sync and update the period and flex.
-        engine.updateOrAddPeriodicSync(target1, period2, flex2, extras2);
-        engine.updateOrAddPeriodicSync(target2, period2, flex2, extras2);
-        // add a target for a second user.
-        engine.updateOrAddPeriodicSync(target1UserB, period1, flex1, extras2);
-
-        List<PeriodicSync> syncs = engine.getPeriodicSyncs(target1);
-
-        assertEquals(2, syncs.size());
-
-        assertEquals(sync1, syncs.get(0));
-        assertEquals(sync3, syncs.get(1));
-
-        engine.removePeriodicSync(target1, extras1);
-
-        syncs = engine.getPeriodicSyncs(target1);
-        assertEquals(1, syncs.size());
-        assertEquals(sync3, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target2);
-        assertEquals(1, syncs.size());
-        assertEquals(sync4, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target1UserB);
-        assertEquals(1, syncs.size());
-        assertEquals(sync2, syncs.get(0));
-    }
-
-    private void removePeriodicSyncs(SyncStorageEngine engine, Account account, int userId, String authority) {
-        EndPoint target = new EndPoint(account, authority, userId);
-        engine.setIsSyncable(account, userId, authority, engine.getIsSyncable(account, userId, authority));
-        List<PeriodicSync> syncs = engine.getPeriodicSyncs(target);
-        for (PeriodicSync sync : syncs) {
-            engine.removePeriodicSync(target, sync.extras);
-        }
-    }
-
     @LargeTest
     public void testAuthorityPersistence() throws Exception {
         final Account account1 = new Account("a@example.com", "example.type");
         final Account account2 = new Account("b@example.com", "example.type.2");
         final String authority1 = "testprovider1";
         final String authority2 = "testprovider2";
-        final Bundle extras1 = new Bundle();
-        extras1.putString("a", "1");
-        final Bundle extras2 = new Bundle();
-        extras2.putString("a", "2");
-        extras2.putLong("b", 2);
-        extras2.putInt("c", 1);
-        extras2.putBoolean("d", true);
-        extras2.putDouble("e", 1.2);
-        extras2.putFloat("f", 4.5f);
-        extras2.putParcelable("g", account1);
-        final int period1 = 200;
-        final int period2 = 1000;
-        final int flex1 = 10;
-        final int flex2 = 100;
-
-        EndPoint point1 = new EndPoint(account1, authority1, 0);
-        EndPoint point2 = new EndPoint(account1, authority2, 0);
-        EndPoint point3 = new EndPoint(account2, authority1, 0);
-
-        PeriodicSync sync1 = new PeriodicSync(account1, authority1, extras1, period1, flex1);
-        PeriodicSync sync2 = new PeriodicSync(account1, authority1, extras2, period1, flex1);
-        PeriodicSync sync3 = new PeriodicSync(account1, authority2, extras1, period1, flex1);
-        PeriodicSync sync4 = new PeriodicSync(account1, authority2, extras2, period2, flex2);
-        PeriodicSync sync5 = new PeriodicSync(account2, authority1, extras1, period1, flex1);
-
-        EndPoint target1 = new EndPoint(account1, authority1, 0);
-        EndPoint target2 = new EndPoint(account1, authority2, 0);
-        EndPoint target3 = new EndPoint(account2, authority1, 0);
-
-        removePeriodicSyncs(engine, account1, 0, authority1);
-        removePeriodicSyncs(engine, account2, 0, authority1);
-        removePeriodicSyncs(engine, account1, 0, authority2);
-        removePeriodicSyncs(engine, account2, 0, authority2);
 
         engine.setMasterSyncAutomatically(false, 0);
 
@@ -395,29 +125,9 @@
         engine.setIsSyncable(account2, 0, authority2, 0);
         engine.setSyncAutomatically(account2, 0, authority2, true);
 
-        engine.updateOrAddPeriodicSync(target1, period1, flex1, extras1);
-        engine.updateOrAddPeriodicSync(target1, period1, flex1, extras2);
-        engine.updateOrAddPeriodicSync(target2, period1, flex1, extras1);
-        engine.updateOrAddPeriodicSync(target2, period2, flex2, extras2);
-        engine.updateOrAddPeriodicSync(target3, period1, flex1, extras1);
-
         engine.writeAllState();
         engine.clearAndReadState();
 
-        List<PeriodicSync> syncs = engine.getPeriodicSyncs(target1);
-        assertEquals(2, syncs.size());
-        assertEquals(sync1, syncs.get(0));
-        assertEquals(sync2, syncs.get(1));
-
-        syncs = engine.getPeriodicSyncs(target2);
-        assertEquals(2, syncs.size());
-        assertEquals(sync3, syncs.get(0));
-        assertEquals(sync4, syncs.get(1));
-
-        syncs = engine.getPeriodicSyncs(target3);
-        assertEquals(1, syncs.size());
-        assertEquals(sync5, syncs.get(0));
-
         assertEquals(true, engine.getSyncAutomatically(account1, 0, authority1));
         assertEquals(true, engine.getSyncAutomatically(account2, 0, authority1));
         assertEquals(false, engine.getSyncAutomatically(account1, 0, authority2));
@@ -429,290 +139,6 @@
         assertEquals(0, engine.getIsSyncable(account2, 0, authority2));
     }
 
-    @SmallTest
-    public void testComponentParsing() throws Exception {
-
-        byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
-                + "<accounts version=\"2\" >\n"
-                + "<authority id=\"0\" user=\"0\" package=\"" + syncService1.getPackageName() + "\""
-                + " class=\"" + syncService1.getClassName() + "\" syncable=\"true\">"
-                + "\n<periodicSync period=\"" + dayPoll + "\" flex=\"" + dayFuzz + "\"/>"
-                + "\n</authority>"
-                + "</accounts>").getBytes();
-
-        File syncDir = getSyncDir();
-        syncDir.mkdirs();
-        AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
-        FileOutputStream fos = accountInfoFile.startWrite();
-        fos.write(accountsFileData);
-        accountInfoFile.finishWrite(fos);
-
-        engine.clearAndReadState();
-
-        SyncStorageEngine.AuthorityInfo aInfo = engine.getAuthority(0);
-        assertNotNull(aInfo);
-
-        // Test service component read
-        List<PeriodicSync> syncs = engine.getPeriodicSyncs(
-                new SyncStorageEngine.EndPoint(syncService1, 0, 0));
-        assertEquals(1, syncs.size());
-        assertEquals(true, engine.getIsTargetServiceActive(syncService1, 0));
-    }
-
-    @SmallTest
-    public void testComponentSettings() throws Exception {
-        EndPoint target1 = new EndPoint(syncService1, 0, 0);
-        engine.updateOrAddPeriodicSync(target1, dayPoll, dayFuzz, Bundle.EMPTY);
-        
-        engine.setIsTargetServiceActive(target1.service, 0, true);
-        boolean active = engine.getIsTargetServiceActive(target1.service, 0);
-        assert(active);
-
-        engine.setIsTargetServiceActive(target1.service, 1, false);
-        active = engine.getIsTargetServiceActive(target1.service, 1);
-        assert(!active);
-    }
-
-    @MediumTest
-    /**
-     * V2 introduces flex time as well as service components.
-     * @throws Exception
-     */
-    public void testAuthorityParsingV2() throws Exception {
-        final Account account = new Account("account1", "type1");
-        final String authority1 = "auth1";
-        final String authority2 = "auth2";
-        final String authority3 = "auth3";
-
-        EndPoint target1 = new EndPoint(account, authority1, 0);
-        EndPoint target2 = new EndPoint(account, authority2, 0);
-        EndPoint target3 = new EndPoint(account, authority3, 0);
-        EndPoint target4 = new EndPoint(account, authority3, 1);
-
-        PeriodicSync sync1 = new PeriodicSync(account, authority1, Bundle.EMPTY, dayPoll, dayFuzz);
-        PeriodicSync sync2 = new PeriodicSync(account, authority2, Bundle.EMPTY, dayPoll, dayFuzz);
-        PeriodicSync sync3 = new PeriodicSync(account, authority3, Bundle.EMPTY, dayPoll, dayFuzz);
-        PeriodicSync sync1s = new PeriodicSync(account, authority1, Bundle.EMPTY, thousandSecs,
-                thousandSecsFuzz);
-        PeriodicSync sync2s = new PeriodicSync(account, authority2, Bundle.EMPTY, thousandSecs,
-                thousandSecsFuzz);
-        PeriodicSync sync3s = new PeriodicSync(account, authority3, Bundle.EMPTY, thousandSecs,
-                thousandSecsFuzz);
-
-        byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
-                + "<accounts version=\"2\" >\n"
-                + "<authority id=\"0\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" >"
-                + "\n<periodicSync period=\"" + dayPoll + "\" flex=\"" + dayFuzz + "\"/>"
-                + "\n</authority>"
-                + "<authority id=\"1\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth2\" >"
-                + "\n<periodicSync period=\"" + dayPoll + "\" flex=\"" + dayFuzz + "\"/>"
-                + "\n</authority>"
-                // No user defaults to user 0 - all users.
-                + "<authority id=\"2\"            account=\"account1\" type=\"type1\" authority=\"auth3\" >"
-                + "\n<periodicSync period=\"" + dayPoll + "\" flex=\"" + dayFuzz + "\"/>"
-                + "\n</authority>"
-                + "<authority id=\"3\" user=\"1\" account=\"account1\" type=\"type1\" authority=\"auth3\" >"
-                + "\n<periodicSync period=\"" + dayPoll + "\" flex=\"" + dayFuzz + "\"/>"
-                + "\n</authority>"
-                + "</accounts>").getBytes();
-
-        File syncDir = getSyncDir();
-        syncDir.mkdirs();
-        AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
-        FileOutputStream fos = accountInfoFile.startWrite();
-        fos.write(accountsFileData);
-        accountInfoFile.finishWrite(fos);
-
-        engine.clearAndReadState();
-
-        List<PeriodicSync> syncs = engine.getPeriodicSyncs(target1);
-        assertEquals("Got incorrect # of syncs", 1, syncs.size());
-        assertEquals(sync1, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target2);
-        assertEquals(1, syncs.size());
-        assertEquals(sync2, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target3);
-        assertEquals(1, syncs.size());
-        assertEquals(sync3, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target4);
-
-        assertEquals(1, syncs.size());
-        assertEquals(sync3, syncs.get(0));
-
-        // Test empty periodic data.
-        accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
-                + "<accounts version=\"2\">\n"
-                + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
-                + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n"
-                + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
-                + "</accounts>\n").getBytes();
-
-        accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
-        fos = accountInfoFile.startWrite();
-        fos.write(accountsFileData);
-        accountInfoFile.finishWrite(fos);
-
-        engine.clearAndReadState();
-
-        syncs = engine.getPeriodicSyncs(target1);
-        assertEquals(0, syncs.size());
-
-        syncs = engine.getPeriodicSyncs(target2);
-        assertEquals(0, syncs.size());
-
-        syncs = engine.getPeriodicSyncs(target3);
-        assertEquals(0, syncs.size());
-
-        accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
-                + "<accounts version=\"2\">\n"
-                + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\">\n"
-                + "<periodicSync period=\"1000\" />\n"
-                + "</authority>"
-                + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\">\n"
-                + "<periodicSync period=\"1000\" />\n"
-                + "</authority>"
-                + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\">\n"
-                + "<periodicSync period=\"1000\" />\n"
-                + "</authority>"
-                + "</accounts>\n").getBytes();
-
-        accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
-        fos = accountInfoFile.startWrite();
-        fos.write(accountsFileData);
-        accountInfoFile.finishWrite(fos);
-
-        engine.clearAndReadState();
-
-        syncs = engine.getPeriodicSyncs(target1);
-        assertEquals(1, syncs.size());
-        assertEquals(sync1s, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target2);
-        assertEquals(1, syncs.size());
-        assertEquals(sync2s, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target3);
-        assertEquals(1, syncs.size());
-        assertEquals(sync3s, syncs.get(0));
-    }
-
-    @MediumTest
-    public void testAuthorityParsing() throws Exception {
-        final Account account = new Account("account1", "type1");
-        final String authority1 = "auth1";
-        final String authority2 = "auth2";
-        final String authority3 = "auth3";
-        final Bundle extras = new Bundle();
-
-        EndPoint target1 = new EndPoint(account, authority1, 0);
-        EndPoint target2 = new EndPoint(account, authority2, 0);
-        EndPoint target3 = new EndPoint(account, authority3, 0);
-        EndPoint target4 = new EndPoint(account, authority3, 1);
-
-        PeriodicSync sync1 = new PeriodicSync(account, authority1, extras, (long) (60 * 60 * 24));
-        PeriodicSync sync2 = new PeriodicSync(account, authority2, extras, (long) (60 * 60 * 24));
-        PeriodicSync sync3 = new PeriodicSync(account, authority3, extras, (long) (60 * 60 * 24));
-        PeriodicSync sync1s = new PeriodicSync(account, authority1, extras, 1000);
-        PeriodicSync sync2s = new PeriodicSync(account, authority2, extras, 1000);
-        PeriodicSync sync3s = new PeriodicSync(account, authority3, extras, 1000);
-
-        MockContentResolver mockResolver = new MockContentResolver();
-
-        final TestContext testContext = new TestContext(mockResolver, getContext());
-
-        byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
-                + "<accounts>\n"
-                + "<authority id=\"0\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
-                + "<authority id=\"1\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n"
-                + "<authority id=\"2\"            account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
-                + "<authority id=\"3\" user=\"1\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
-                + "</accounts>\n").getBytes();
-
-        File syncDir = getSyncDir();
-        syncDir.mkdirs();
-        AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
-        FileOutputStream fos = accountInfoFile.startWrite();
-        fos.write(accountsFileData);
-        accountInfoFile.finishWrite(fos);
-
-        SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
-
-        List<PeriodicSync> syncs = engine.getPeriodicSyncs(target1);
-        assertEquals(1, syncs.size());
-        assertEquals("expected sync1: " + sync1.toString() + " == sync 2" + syncs.get(0).toString(), sync1, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target2);
-        assertEquals(1, syncs.size());
-        assertEquals(sync2, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target3);
-        assertEquals(1, syncs.size());
-        assertEquals(sync3, syncs.get(0));
-        syncs = engine.getPeriodicSyncs(target4);
-
-
-        assertEquals(1, syncs.size());
-        assertEquals(sync3, syncs.get(0));
-
-        accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
-                + "<accounts version=\"2\">\n"
-                + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
-                + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n"
-                + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
-                + "</accounts>\n").getBytes();
-
-        accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
-        fos = accountInfoFile.startWrite();
-        fos.write(accountsFileData);
-        accountInfoFile.finishWrite(fos);
-
-        engine.clearAndReadState();
-
-        syncs = engine.getPeriodicSyncs(target1);
-        assertEquals(0, syncs.size());
-
-        syncs = engine.getPeriodicSyncs(target2);
-        assertEquals(0, syncs.size());
-
-        syncs = engine.getPeriodicSyncs(target3);
-        assertEquals(0, syncs.size());
-
-        accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
-                + "<accounts version=\"2\">\n"
-                + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\">\n"
-                + "<periodicSync period=\"1000\" />\n"
-                + "</authority>"
-                + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\">\n"
-                + "<periodicSync period=\"1000\" />\n"
-                + "</authority>"
-                + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\">\n"
-                + "<periodicSync period=\"1000\" />\n"
-                + "</authority>"
-                + "</accounts>\n").getBytes();
-
-        accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
-        fos = accountInfoFile.startWrite();
-        fos.write(accountsFileData);
-        accountInfoFile.finishWrite(fos);
-
-        engine.clearAndReadState();
-
-        syncs = engine.getPeriodicSyncs(target1);
-        assertEquals(1, syncs.size());
-        assertEquals(sync1s, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target2);
-        assertEquals(1, syncs.size());
-        assertEquals(sync2s, syncs.get(0));
-
-        syncs = engine.getPeriodicSyncs(target3);
-        assertEquals(1, syncs.size());
-        assertEquals(sync3s, syncs.get(0));
-    }
-
     @MediumTest
     public void testListenForTicklesParsing() throws Exception {
         byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 90e4acf..db2a9ad 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -281,5 +281,25 @@
         void settingsGlobalPutString(String name, String value) {
             context.settings.settingsGlobalPutString(name, value);
         }
+
+        @Override
+        int settingsGlobalGetInt(String name, int def) {
+            return context.settings.settingsGlobalGetInt(name, def);
+        }
+
+        @Override
+        void securityLogSetLoggingEnabledProperty(boolean enabled) {
+            context.settings.securityLogSetLoggingEnabledProperty(enabled);
+        }
+
+        @Override
+        boolean securityLogGetLoggingEnabledProperty() {
+            return context.settings.securityLogGetLoggingEnabledProperty();
+        }
+
+        @Override
+        boolean securityLogIsLoggingEnabled() {
+            return context.settings.securityLogIsLoggingEnabled();
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 87569b7..64f60d93 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -559,6 +559,10 @@
                     expected.getMessage().contains("already has a device owner"));
         }
 
+        // DO admin can't be deactivated.
+        dpm.removeActiveAdmin(admin1);
+        assertTrue(dpm.isAdminActive(admin1));
+
         // TODO Test getDeviceOwnerName() too.  To do so, we need to change
         // DPMS.getApplicationLabel() because Context.createPackageContextAsUser() is not mockable.
     }
@@ -763,6 +767,11 @@
 
         assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
 
+        dpm.addUserRestriction(admin1, UserManager.DISALLOW_ADD_USER);
+
+        assertTrue(dpm.isAdminActive(admin1));
+        assertFalse(dpm.isRemovingAdmin(admin1, UserHandle.USER_SYSTEM));
+
         // Set up other mocks.
         when(mContext.userManager.getUserRestrictions()).thenReturn(new Bundle());
 
@@ -770,11 +779,21 @@
         doReturn(DpmMockContext.CALLER_SYSTEM_USER_UID).when(mContext.packageManager).getPackageUidAsUser(
                 eq(admin1.getPackageName()),
                 anyInt());
+        reset(mContext.userManagerInternal);
         dpm.clearDeviceOwnerApp(admin1.getPackageName());
 
         // Now DO shouldn't be set.
         assertNull(dpm.getDeviceOwnerComponentOnAnyUser());
 
+        verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
+                eq(UserHandle.USER_SYSTEM),
+                MockUtils.checkUserRestrictions(),
+                MockUtils.checkUserRestrictions()
+        );
+
+        assertTrue(dpm.isAdminActive(admin1));
+        assertTrue(dpm.isRemovingAdmin(admin1, UserHandle.USER_SYSTEM));
+
         // TODO Check other calls.
     }
 
@@ -823,6 +842,10 @@
     public void testSetProfileOwner() throws Exception {
         setAsProfileOwner(admin1);
 
+        // PO admin can't be deactivated.
+        dpm.removeActiveAdmin(admin1);
+        assertTrue(dpm.isAdminActive(admin1));
+
         // Try setting DO on the same user, which should fail.
         setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID);
         dpm.setActiveAdmin(admin2, /* refreshing= */ true, DpmMockContext.CALLER_USER_HANDLE);
@@ -835,6 +858,22 @@
         }
     }
 
+    public void testClearProfileOwner() throws Exception {
+        setAsProfileOwner(admin1);
+
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+
+        assertTrue(dpm.isProfileOwnerApp(admin1.getPackageName()));
+        assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+        // Clear
+        dpm.clearProfileOwner(admin1);
+
+        // Check
+        assertFalse(dpm.isProfileOwnerApp(admin1.getPackageName()));
+        assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+    }
+
     public void testSetProfileOwner_failures() throws Exception {
         // TODO Test more failure cases.  Basically test all chacks in enforceCanSetProfileOwner().
     }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 56667e5..7a00098 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -191,6 +191,21 @@
 
         void settingsGlobalPutString(String name, String value) {
         }
+
+        int settingsGlobalGetInt(String name, int def) {
+            return 0;
+        }
+
+        void securityLogSetLoggingEnabledProperty(boolean enabled) {
+        }
+
+        public boolean securityLogGetLoggingEnabledProperty() {
+            return false;
+        }
+
+        public boolean securityLogIsLoggingEnabled() {
+            return false;
+        }
     }
 
     public final Context realTestContext;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index 3dc1a9a..53ca45d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -29,6 +29,7 @@
 import java.io.File;
 import java.util.List;
 
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 
@@ -135,8 +136,7 @@
 
         doReturn(realResolveInfo).when(mMockContext.packageManager).queryBroadcastReceiversAsUser(
                 MockUtils.checkIntentComponent(admin),
-                eq(PackageManager.GET_META_DATA
-                        | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+                anyInt(),
                 eq(UserHandle.getUserId(packageUid)));
 
         // Set up getPackageInfo().
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
new file mode 100644
index 0000000..9ccb1a6
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usage;
+
+import android.os.FileUtils;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+
+public class AppIdleHistoryTests extends AndroidTestCase {
+
+    File mStorageDir;
+
+    final static String PACKAGE_1 = "com.android.testpackage1";
+    final static String PACKAGE_2 = "com.android.testpackage2";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mStorageDir = new File(getContext().getFilesDir(), "appidle");
+        mStorageDir.mkdirs();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        FileUtils.deleteContents(mStorageDir);
+        super.tearDown();
+    }
+
+    public void testFilesCreation() {
+        final int userId = 0;
+        AppIdleHistory aih = new AppIdleHistory(mStorageDir, 0);
+
+        aih.updateDisplayLocked(true, /* elapsedRealtime= */ 1000);
+        aih.updateDisplayLocked(false, /* elapsedRealtime= */ 2000);
+        // Screen On time file should be written right away
+        assertTrue(aih.getScreenOnTimeFile().exists());
+
+        aih.writeAppIdleTimesLocked(userId);
+        // stats file should be written now
+        assertTrue(new File(new File(mStorageDir, "users/" + userId),
+                AppIdleHistory.APP_IDLE_FILENAME).exists());
+    }
+
+    public void testScreenOnTime() {
+        AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
+        aih.updateDisplayLocked(false, 2000);
+        assertEquals(aih.getScreenOnTimeLocked(2000), 0);
+        aih.updateDisplayLocked(true, 3000);
+        assertEquals(aih.getScreenOnTimeLocked(4000), 1000);
+        assertEquals(aih.getScreenOnTimeLocked(5000), 2000);
+        aih.updateDisplayLocked(false, 6000);
+        // Screen on time should not keep progressing with screen is off
+        assertEquals(aih.getScreenOnTimeLocked(7000), 3000);
+        assertEquals(aih.getScreenOnTimeLocked(8000), 3000);
+        aih.writeElapsedTimeLocked();
+
+        // Check if the screen on time is persisted across instantiations
+        AppIdleHistory aih2 = new AppIdleHistory(mStorageDir, 0);
+        assertEquals(aih2.getScreenOnTimeLocked(11000), 3000);
+        aih2.updateDisplayLocked(true, 4000);
+        aih2.updateDisplayLocked(false, 5000);
+        assertEquals(aih2.getScreenOnTimeLocked(13000), 4000);
+    }
+
+    public void testPackageEvents() {
+        AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
+        aih.setThresholds(4000, 1000);
+        aih.updateDisplayLocked(true, 1000);
+        // App is not-idle by default
+        assertFalse(aih.isIdleLocked(PACKAGE_1, 0, 1500));
+        // Still not idle
+        assertFalse(aih.isIdleLocked(PACKAGE_1, 0, 3000));
+        // Idle now
+        assertTrue(aih.isIdleLocked(PACKAGE_1, 0, 8000));
+        // Not idle
+        assertFalse(aih.isIdleLocked(PACKAGE_2, 0, 9000));
+
+        // Screen off
+        aih.updateDisplayLocked(false, 9100);
+        // Still idle after 10 seconds because screen hasn't been on long enough
+        assertFalse(aih.isIdleLocked(PACKAGE_2, 0, 20000));
+        aih.updateDisplayLocked(true, 21000);
+        assertTrue(aih.isIdleLocked(PACKAGE_2, 0, 23000));
+    }
+}
\ No newline at end of file
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index e3c0868..3e2b43d 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -16,19 +16,45 @@
 
 package com.android.server.usage;
 
+import android.os.Environment;
+import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Slog;
 import android.util.SparseArray;
+import android.util.TimeUtils;
+import android.util.Xml;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
 /**
  * Keeps track of recent active state changes in apps.
  * Access should be guarded by a lock by the caller.
  */
 public class AppIdleHistory {
 
-    private SparseArray<ArrayMap<String,byte[]>> mIdleHistory = new SparseArray<>();
-    private long lastPeriod = 0;
+    private static final String TAG = "AppIdleHistory";
+
+    // History for all users and all packages
+    private SparseArray<ArrayMap<String,PackageHistory>> mIdleHistory = new SparseArray<>();
+    private long mLastPeriod = 0;
     private static final long ONE_MINUTE = 60 * 1000;
     private static final int HISTORY_SIZE = 100;
     private static final int FLAG_LAST_STATE = 2;
@@ -36,77 +62,353 @@
     private static final long PERIOD_DURATION = UsageStatsService.COMPRESS_TIME ? ONE_MINUTE
             : 60 * ONE_MINUTE;
 
-    public void addEntry(String packageName, int userId, boolean idle, long timeNow) {
-        ArrayMap<String, byte[]> userHistory = getUserHistory(userId);
-        byte[] packageHistory = getPackageHistory(userHistory, packageName);
+    @VisibleForTesting
+    static final String APP_IDLE_FILENAME = "app_idle_stats.xml";
+    private static final String TAG_PACKAGES = "packages";
+    private static final String TAG_PACKAGE = "package";
+    private static final String ATTR_NAME = "name";
+    // Screen on timebase time when app was last used
+    private static final String ATTR_SCREEN_IDLE = "screenIdleTime";
+    // Elapsed timebase time when app was last used
+    private static final String ATTR_ELAPSED_IDLE = "elapsedIdleTime";
 
-        long thisPeriod = timeNow / PERIOD_DURATION;
+    // device on time = mElapsedDuration + (timeNow - mElapsedSnapshot)
+    private long mElapsedSnapshot; // Elapsed time snapshot when last write of mDeviceOnDuration
+    private long mElapsedDuration; // Total device on duration since device was "born"
+
+    // screen on time = mScreenOnDuration + (timeNow - mScreenOnSnapshot)
+    private long mScreenOnSnapshot; // Elapsed time snapshot when last write of mScreenOnDuration
+    private long mScreenOnDuration; // Total screen on duration since device was "born"
+
+    private long mElapsedTimeThreshold;
+    private long mScreenOnTimeThreshold;
+    private final File mStorageDir;
+
+    private boolean mScreenOn;
+
+    private static class PackageHistory {
+        final byte[] recent = new byte[HISTORY_SIZE];
+        long lastUsedElapsedTime;
+        long lastUsedScreenTime;
+    }
+
+    AppIdleHistory(long elapsedRealtime) {
+        this(Environment.getDataSystemDirectory(), elapsedRealtime);
+    }
+
+    @VisibleForTesting
+    AppIdleHistory(File storageDir, long elapsedRealtime) {
+        mElapsedSnapshot = elapsedRealtime;
+        mScreenOnSnapshot = elapsedRealtime;
+        mStorageDir = storageDir;
+        readScreenOnTimeLocked();
+    }
+
+    public void setThresholds(long elapsedTimeThreshold, long screenOnTimeThreshold) {
+        mElapsedTimeThreshold = elapsedTimeThreshold;
+        mScreenOnTimeThreshold = screenOnTimeThreshold;
+    }
+
+    public void updateDisplayLocked(boolean screenOn, long elapsedRealtime) {
+        if (screenOn == mScreenOn) return;
+
+        mScreenOn = screenOn;
+        if (mScreenOn) {
+            mScreenOnSnapshot = elapsedRealtime;
+        } else {
+            mScreenOnDuration += elapsedRealtime - mScreenOnSnapshot;
+            mElapsedDuration += elapsedRealtime - mElapsedSnapshot;
+            writeScreenOnTimeLocked();
+            mElapsedSnapshot = elapsedRealtime;
+        }
+    }
+
+    public long getScreenOnTimeLocked(long elapsedRealtime) {
+        long screenOnTime = mScreenOnDuration;
+        if (mScreenOn) {
+            screenOnTime += elapsedRealtime - mScreenOnSnapshot;
+        }
+        return screenOnTime;
+    }
+
+    @VisibleForTesting
+    File getScreenOnTimeFile() {
+        return new File(mStorageDir, "screen_on_time");
+    }
+
+    private void readScreenOnTimeLocked() {
+        File screenOnTimeFile = getScreenOnTimeFile();
+        if (screenOnTimeFile.exists()) {
+            try {
+                BufferedReader reader = new BufferedReader(new FileReader(screenOnTimeFile));
+                mScreenOnDuration = Long.parseLong(reader.readLine());
+                mElapsedDuration = Long.parseLong(reader.readLine());
+                reader.close();
+            } catch (IOException | NumberFormatException e) {
+            }
+        } else {
+            writeScreenOnTimeLocked();
+        }
+    }
+
+    private void writeScreenOnTimeLocked() {
+        AtomicFile screenOnTimeFile = new AtomicFile(getScreenOnTimeFile());
+        FileOutputStream fos = null;
+        try {
+            fos = screenOnTimeFile.startWrite();
+            fos.write((Long.toString(mScreenOnDuration) + "\n"
+                    + Long.toString(mElapsedDuration) + "\n").getBytes());
+            screenOnTimeFile.finishWrite(fos);
+        } catch (IOException ioe) {
+            screenOnTimeFile.failWrite(fos);
+        }
+    }
+
+    /**
+     * To be called periodically to keep track of elapsed time when app idle times are written
+     */
+    public void writeElapsedTimeLocked() {
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        // Only bump up and snapshot the elapsed time. Don't change screen on duration.
+        mElapsedDuration += elapsedRealtime - mElapsedSnapshot;
+        mElapsedSnapshot = elapsedRealtime;
+        writeScreenOnTimeLocked();
+    }
+
+    public void reportUsageLocked(String packageName, int userId, long elapsedRealtime) {
+        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+        PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+                elapsedRealtime);
+
+        shiftHistoryToNow(userHistory, elapsedRealtime);
+
+        packageHistory.lastUsedElapsedTime = mElapsedDuration
+                + (elapsedRealtime - mElapsedSnapshot);
+        packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime);
+        packageHistory.recent[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
+    }
+
+    public void setIdle(String packageName, int userId, long elapsedRealtime) {
+        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+        PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+                elapsedRealtime);
+
+        shiftHistoryToNow(userHistory, elapsedRealtime);
+
+        packageHistory.recent[HISTORY_SIZE - 1] &= ~FLAG_LAST_STATE;
+    }
+
+    private void shiftHistoryToNow(ArrayMap<String, PackageHistory> userHistory,
+            long elapsedRealtime) {
+        long thisPeriod = elapsedRealtime / PERIOD_DURATION;
         // Has the period switched over? Slide all users' package histories
-        if (lastPeriod != 0 && lastPeriod < thisPeriod
-                && (thisPeriod - lastPeriod) < HISTORY_SIZE - 1) {
-            int diff = (int) (thisPeriod - lastPeriod);
+        if (mLastPeriod != 0 && mLastPeriod < thisPeriod
+                && (thisPeriod - mLastPeriod) < HISTORY_SIZE - 1) {
+            int diff = (int) (thisPeriod - mLastPeriod);
             final int NUSERS = mIdleHistory.size();
             for (int u = 0; u < NUSERS; u++) {
                 userHistory = mIdleHistory.valueAt(u);
-                for (byte[] history : userHistory.values()) {
+                for (PackageHistory idleState : userHistory.values()) {
                     // Shift left
-                    System.arraycopy(history, diff, history, 0, HISTORY_SIZE - diff);
+                    System.arraycopy(idleState.recent, diff, idleState.recent, 0,
+                            HISTORY_SIZE - diff);
                     // Replicate last state across the diff
                     for (int i = 0; i < diff; i++) {
-                        history[HISTORY_SIZE - i - 1] =
-                                (byte) (history[HISTORY_SIZE - diff - 1] & FLAG_LAST_STATE);
+                        idleState.recent[HISTORY_SIZE - i - 1] =
+                            (byte) (idleState.recent[HISTORY_SIZE - diff - 1] & FLAG_LAST_STATE);
                     }
                 }
             }
         }
-        lastPeriod = thisPeriod;
-        if (!idle) {
-            packageHistory[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
-        } else {
-            packageHistory[HISTORY_SIZE - 1] &= ~FLAG_LAST_STATE;
-        }
+        mLastPeriod = thisPeriod;
     }
 
-    private ArrayMap<String, byte[]> getUserHistory(int userId) {
-        ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId);
+    private ArrayMap<String, PackageHistory> getUserHistoryLocked(int userId) {
+        ArrayMap<String, PackageHistory> userHistory = mIdleHistory.get(userId);
         if (userHistory == null) {
             userHistory = new ArrayMap<>();
             mIdleHistory.put(userId, userHistory);
+            readAppIdleTimesLocked(userId, userHistory);
         }
         return userHistory;
     }
 
-    private byte[] getPackageHistory(ArrayMap<String, byte[]> userHistory, String packageName) {
-        byte[] packageHistory = userHistory.get(packageName);
+    private PackageHistory getPackageHistoryLocked(ArrayMap<String, PackageHistory> userHistory,
+            String packageName, long elapsedRealtime) {
+        PackageHistory packageHistory = userHistory.get(packageName);
         if (packageHistory == null) {
-            packageHistory = new byte[HISTORY_SIZE];
+            packageHistory = new PackageHistory();
+            packageHistory.lastUsedElapsedTime = getElapsedTimeLocked(elapsedRealtime);
+            packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime);
             userHistory.put(packageName, packageHistory);
         }
         return packageHistory;
     }
 
-    public void removeUser(int userId) {
+    public void onUserRemoved(int userId) {
         mIdleHistory.remove(userId);
     }
 
-    public boolean isIdle(int userId, String packageName) {
-        ArrayMap<String, byte[]> userHistory = getUserHistory(userId);
-        byte[] packageHistory = getPackageHistory(userHistory, packageName);
-        return (packageHistory[HISTORY_SIZE - 1] & FLAG_LAST_STATE) == 0;
+    public boolean isIdleLocked(String packageName, int userId, long elapsedRealtime) {
+        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+        PackageHistory packageHistory =
+                getPackageHistoryLocked(userHistory, packageName, elapsedRealtime);
+        if (packageHistory == null) {
+            return false; // Default to not idle
+        } else {
+            return hasPassedThresholdsLocked(packageHistory, elapsedRealtime);
+        }
+    }
+
+    private long getElapsedTimeLocked(long elapsedRealtime) {
+        return (elapsedRealtime - mElapsedSnapshot + mElapsedDuration);
+    }
+
+    public void setIdleLocked(String packageName, int userId, boolean idle, long elapsedRealtime) {
+        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+        PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+                elapsedRealtime);
+        packageHistory.lastUsedElapsedTime = getElapsedTimeLocked(elapsedRealtime)
+                - mElapsedTimeThreshold;
+        packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime)
+                - (idle ? mScreenOnTimeThreshold : 0) - 1000 /* just a second more */;
+    }
+
+    private boolean hasPassedThresholdsLocked(PackageHistory packageHistory, long elapsedRealtime) {
+        return (packageHistory.lastUsedScreenTime
+                    <= getScreenOnTimeLocked(elapsedRealtime) - mScreenOnTimeThreshold)
+                && (packageHistory.lastUsedElapsedTime
+                        <= getElapsedTimeLocked(elapsedRealtime) - mElapsedTimeThreshold);
+    }
+
+    private File getUserFile(int userId) {
+        return new File(new File(new File(mStorageDir, "users"),
+                Integer.toString(userId)), APP_IDLE_FILENAME);
+    }
+
+    private void readAppIdleTimesLocked(int userId, ArrayMap<String, PackageHistory> userHistory) {
+        FileInputStream fis = null;
+        try {
+            AtomicFile appIdleFile = new AtomicFile(getUserFile(userId));
+            fis = appIdleFile.openRead();
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(fis, StandardCharsets.UTF_8.name());
+
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+                // Skip
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                Slog.e(TAG, "Unable to read app idle file for user " + userId);
+                return;
+            }
+            if (!parser.getName().equals(TAG_PACKAGES)) {
+                return;
+            }
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                if (type == XmlPullParser.START_TAG) {
+                    final String name = parser.getName();
+                    if (name.equals(TAG_PACKAGE)) {
+                        final String packageName = parser.getAttributeValue(null, ATTR_NAME);
+                        PackageHistory packageHistory = new PackageHistory();
+                        packageHistory.lastUsedElapsedTime =
+                                Long.parseLong(parser.getAttributeValue(null, ATTR_ELAPSED_IDLE));
+                        packageHistory.lastUsedScreenTime =
+                                Long.parseLong(parser.getAttributeValue(null, ATTR_SCREEN_IDLE));
+                        userHistory.put(packageName, packageHistory);
+                    }
+                }
+            }
+        } catch (IOException | XmlPullParserException e) {
+            Slog.e(TAG, "Unable to read app idle file for user " + userId);
+        } finally {
+            IoUtils.closeQuietly(fis);
+        }
+    }
+
+    public void writeAppIdleTimesLocked(int userId) {
+        FileOutputStream fos = null;
+        AtomicFile appIdleFile = new AtomicFile(getUserFile(userId));
+        try {
+            fos = appIdleFile.startWrite();
+            final BufferedOutputStream bos = new BufferedOutputStream(fos);
+
+            FastXmlSerializer xml = new FastXmlSerializer();
+            xml.setOutput(bos, StandardCharsets.UTF_8.name());
+            xml.startDocument(null, true);
+            xml.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+
+            xml.startTag(null, TAG_PACKAGES);
+
+            ArrayMap<String,PackageHistory> userHistory = getUserHistoryLocked(userId);
+            final int N = userHistory.size();
+            for (int i = 0; i < N; i++) {
+                String packageName = userHistory.keyAt(i);
+                PackageHistory history = userHistory.valueAt(i);
+                xml.startTag(null, TAG_PACKAGE);
+                xml.attribute(null, ATTR_NAME, packageName);
+                xml.attribute(null, ATTR_ELAPSED_IDLE,
+                        Long.toString(history.lastUsedElapsedTime));
+                xml.attribute(null, ATTR_SCREEN_IDLE,
+                        Long.toString(history.lastUsedScreenTime));
+                xml.endTag(null, TAG_PACKAGE);
+            }
+
+            xml.endTag(null, TAG_PACKAGES);
+            xml.endDocument();
+            appIdleFile.finishWrite(fos);
+        } catch (Exception e) {
+            appIdleFile.failWrite(fos);
+            Slog.e(TAG, "Error writing app idle file for user " + userId);
+        }
     }
 
     public void dump(IndentingPrintWriter idpw, int userId) {
-        ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId);
+        idpw.println("Package idle stats:");
+        idpw.increaseIndent();
+        ArrayMap<String, PackageHistory> userHistory = mIdleHistory.get(userId);
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long totalElapsedTime = getElapsedTimeLocked(elapsedRealtime);
+        final long screenOnTime = getScreenOnTimeLocked(elapsedRealtime);
         if (userHistory == null) return;
         final int P = userHistory.size();
         for (int p = 0; p < P; p++) {
             final String packageName = userHistory.keyAt(p);
-            final byte[] history = userHistory.valueAt(p);
+            final PackageHistory packageHistory = userHistory.valueAt(p);
+            idpw.print("package=" + packageName);
+            idpw.print(" lastUsedElapsed=");
+            TimeUtils.formatDuration(totalElapsedTime - packageHistory.lastUsedElapsedTime, idpw);
+            idpw.print(" lastUsedScreenOn=");
+            TimeUtils.formatDuration(screenOnTime - packageHistory.lastUsedScreenTime, idpw);
+            idpw.print(" idle=" + (isIdleLocked(packageName, userId, elapsedRealtime) ? "y" : "n"));
+            idpw.println();
+        }
+        idpw.println();
+        idpw.print("totalElapsedTime=");
+        TimeUtils.formatDuration(getElapsedTimeLocked(elapsedRealtime), idpw);
+        idpw.println();
+        idpw.print("totalScreenOnTime=");
+        TimeUtils.formatDuration(getScreenOnTimeLocked(elapsedRealtime), idpw);
+        idpw.println();
+        idpw.decreaseIndent();
+    }
+
+    public void dumpHistory(IndentingPrintWriter idpw, int userId) {
+        ArrayMap<String, PackageHistory> userHistory = mIdleHistory.get(userId);
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        if (userHistory == null) return;
+        final int P = userHistory.size();
+        for (int p = 0; p < P; p++) {
+            final String packageName = userHistory.keyAt(p);
+            final byte[] history = userHistory.valueAt(p).recent;
             for (int i = 0; i < HISTORY_SIZE; i++) {
                 idpw.print(history[i] == 0 ? '.' : 'A');
             }
+            idpw.print(" idle=" + (isIdleLocked(packageName, userId, elapsedRealtime) ? "y" : "n"));
             idpw.print("  " + packageName);
             idpw.println();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 7f379fe..f541f70 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -48,7 +48,6 @@
             usageStats.mPackageName = getCachedStringRef(packageName);
             usageStats.mBeginTimeStamp = beginTime;
             usageStats.mEndTimeStamp = endTime;
-            usageStats.mBeginIdleTime = 0;
             packageStats.put(usageStats.mPackageName, usageStats);
         }
         return usageStats;
@@ -113,7 +112,6 @@
         if (eventType != UsageEvents.Event.SYSTEM_INTERACTION) {
             usageStats.mLastTimeUsed = timeStamp;
         }
-        usageStats.mLastTimeSystemUsed = timeStamp;
         usageStats.mEndTimeStamp = timeStamp;
 
         if (eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
@@ -123,22 +121,6 @@
         endTime = timeStamp;
     }
 
-    /**
-     * Updates the last active time for the package. The timestamp uses a timebase that
-     * tracks the device usage time.
-     * @param packageName
-     * @param timeStamp
-     */
-    void updateBeginIdleTime(String packageName, long timeStamp) {
-        UsageStats usageStats = getOrCreateUsageStats(packageName);
-        usageStats.mBeginIdleTime = timeStamp;
-    }
-
-    void updateSystemLastUsedTime(String packageName, long lastUsedTime) {
-        UsageStats usageStats = getOrCreateUsageStats(packageName);
-        usageStats.mLastTimeSystemUsed = lastUsedTime;
-    }
-
     void updateConfigurationStats(Configuration config, long timeStamp) {
         if (activeConfiguration != null) {
             ConfigurationStats activeStats = configurations.get(activeConfiguration);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 77740387..46ad8a1 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -40,6 +40,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.hardware.display.DisplayManager;
@@ -62,7 +63,6 @@
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.util.ArraySet;
-import android.util.AtomicFile;
 import android.util.KeyValueListParser;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -77,12 +77,8 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemService;
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -106,7 +102,7 @@
     private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES;
     private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
 
-    long mAppIdleDurationMillis;
+    long mAppIdleScreenThresholdMillis;
     long mCheckIdleIntervalMillis;
     long mAppIdleWallclockThresholdMillis;
     long mAppIdleParoleIntervalMillis;
@@ -147,11 +143,8 @@
 
     private volatile boolean mPendingOneTimeCheckIdleStates;
 
-    long mScreenOnTime;
-    long mLastScreenOnEventRealtime;
-
     @GuardedBy("mLock")
-    private AppIdleHistory mAppIdleHistory = new AppIdleHistory();
+    private AppIdleHistory mAppIdleHistory;
 
     private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
             mPackageAccessListeners = new ArrayList<>();
@@ -191,8 +184,7 @@
 
         synchronized (mLock) {
             cleanUpRemovedUsersLocked();
-            mLastScreenOnEventRealtime = SystemClock.elapsedRealtime();
-            mScreenOnTime = readScreenOnTimeLocked();
+            mAppIdleHistory = new AppIdleHistory(SystemClock.elapsedRealtime());
         }
 
         mRealTimeSnapshot = SystemClock.elapsedRealtime();
@@ -221,7 +213,7 @@
 
             mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
             synchronized (mLock) {
-                updateDisplayLocked();
+                mAppIdleHistory.updateDisplayLocked(isDisplayOn(), SystemClock.elapsedRealtime());
             }
 
             if (mPendingOneTimeCheckIdleStates) {
@@ -232,6 +224,11 @@
         }
     }
 
+    private boolean isDisplayOn() {
+        return mDisplayManager
+                .getDisplay(Display.DEFAULT_DISPLAY).getState() == Display.STATE_ON;
+    }
+
     private class UserActionsReceiver extends BroadcastReceiver {
 
         @Override
@@ -274,7 +271,8 @@
         @Override public void onDisplayChanged(int displayId) {
             if (displayId == Display.DEFAULT_DISPLAY) {
                 synchronized (UsageStatsService.this.mLock) {
-                    updateDisplayLocked();
+                    mAppIdleHistory.updateDisplayLocked(isDisplayOn(),
+                            SystemClock.elapsedRealtime());
                 }
             }
         }
@@ -291,8 +289,25 @@
     }
 
     @Override
-    public long getAppIdleRollingWindowDurationMillis() {
-        return mAppIdleWallclockThresholdMillis * 2;
+    public void onNewUpdate(int userId) {
+        initializeDefaultsForSystemApps(userId);
+    }
+
+    private void initializeDefaultsForSystemApps(int userId) {
+        Slog.d(TAG, "Initializing defaults for system apps on user " + userId);
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        List<PackageInfo> packages = getContext().getPackageManager().getInstalledPackagesAsUser(
+                PackageManager.MATCH_DISABLED_COMPONENTS
+                | PackageManager.MATCH_UNINSTALLED_PACKAGES,
+                userId);
+        final int packageCount = packages.size();
+        for (int i = 0; i < packageCount; i++) {
+            final PackageInfo pi = packages.get(i);
+            String packageName = pi.packageName;
+            if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
+                mAppIdleHistory.reportUsageLocked(packageName, userId, elapsedRealtime);
+            }
+        }
     }
 
     private void cleanUpRemovedUsersLocked() {
@@ -350,7 +365,7 @@
         if (timeLeft < 0) {
             timeLeft = 0;
         }
-        mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft / 10);
+        mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft);
     }
 
     private void postParoleEndTimeout() {
@@ -400,28 +415,27 @@
             return;
         }
 
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
         for (int i = 0; i < userIds.length; i++) {
             final int userId = userIds[i];
             List<PackageInfo> packages =
                     getContext().getPackageManager().getInstalledPackagesAsUser(
-                            PackageManager.GET_DISABLED_COMPONENTS
-                                | PackageManager.GET_UNINSTALLED_PACKAGES,
+                            PackageManager.MATCH_DISABLED_COMPONENTS
+                                | PackageManager.MATCH_UNINSTALLED_PACKAGES,
                             userId);
             synchronized (mLock) {
-                final long timeNow = checkAndGetTimeLocked();
-                final long screenOnTime = getScreenOnTimeLocked();
-                UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId,
-                        timeNow);
                 final int packageCount = packages.size();
                 for (int p = 0; p < packageCount; p++) {
                     final PackageInfo pi = packages.get(p);
                     final String packageName = pi.packageName;
                     final boolean isIdle = isAppIdleFiltered(packageName,
                             UserHandle.getAppId(pi.applicationInfo.uid),
-                            userId, service, timeNow, screenOnTime);
+                            userId, elapsedRealtime);
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
                             userId, isIdle ? 1 : 0, packageName));
-                    mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow);
+                    if (isIdle) {
+                        mAppIdleHistory.setIdle(packageName, userId, elapsedRealtime);
+                    }
                 }
             }
         }
@@ -458,62 +472,6 @@
         }
     }
 
-    void updateDisplayLocked() {
-        boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState()
-                == Display.STATE_ON;
-
-        if (screenOn == mScreenOn) return;
-
-        mScreenOn = screenOn;
-        long now = SystemClock.elapsedRealtime();
-        if (mScreenOn) {
-            mLastScreenOnEventRealtime = now;
-        } else {
-            mScreenOnTime += now - mLastScreenOnEventRealtime;
-            writeScreenOnTimeLocked(mScreenOnTime);
-        }
-    }
-
-    long getScreenOnTimeLocked() {
-        long screenOnTime = mScreenOnTime;
-        if (mScreenOn) {
-            screenOnTime += SystemClock.elapsedRealtime() - mLastScreenOnEventRealtime;
-        }
-        return screenOnTime;
-    }
-
-    private File getScreenOnTimeFile() {
-        return new File(mUsageStatsDir, UserHandle.USER_SYSTEM + "/screen_on_time");
-    }
-
-    private long readScreenOnTimeLocked() {
-        long screenOnTime = 0;
-        File screenOnTimeFile = getScreenOnTimeFile();
-        if (screenOnTimeFile.exists()) {
-            try {
-                BufferedReader reader = new BufferedReader(new FileReader(screenOnTimeFile));
-                screenOnTime = Long.parseLong(reader.readLine());
-                reader.close();
-            } catch (IOException | NumberFormatException e) {
-            }
-        } else {
-            writeScreenOnTimeLocked(screenOnTime);
-        }
-        return screenOnTime;
-    }
-
-    private void writeScreenOnTimeLocked(long screenOnTime) {
-        AtomicFile screenOnTimeFile = new AtomicFile(getScreenOnTimeFile());
-        FileOutputStream fos = null;
-        try {
-            fos = screenOnTimeFile.startWrite();
-            fos.write(Long.toString(screenOnTime).getBytes());
-            screenOnTimeFile.finishWrite(fos);
-        } catch (IOException ioe) {
-            screenOnTimeFile.failWrite(fos);
-        }
-    }
-
     void onDeviceIdleModeChanged() {
         final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
         if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
@@ -549,7 +507,7 @@
         if (service == null) {
             service = new UserUsageStatsService(getContext(), userId,
                     new File(mUsageStatsDir, Integer.toString(userId)), this);
-            service.init(currentTimeMillis, getScreenOnTimeLocked());
+            service.init(currentTimeMillis);
             mUserState.put(userId, service);
         }
         return service;
@@ -569,8 +527,7 @@
             final int userCount = mUserState.size();
             for (int i = 0; i < userCount; i++) {
                 final UserUsageStatsService service = mUserState.valueAt(i);
-                service.onTimeChanged(expectedSystemTime, actualSystemTime, getScreenOnTimeLocked(),
-                        false);
+                service.onTimeChanged(expectedSystemTime, actualSystemTime);
             }
             mRealTimeSnapshot = actualRealtime;
             mSystemTimeSnapshot = actualSystemTime;
@@ -602,26 +559,26 @@
     void reportEvent(UsageEvents.Event event, int userId) {
         synchronized (mLock) {
             final long timeNow = checkAndGetTimeLocked();
-            final long screenOnTime = getScreenOnTimeLocked();
+            final long elapsedRealtime = SystemClock.elapsedRealtime();
             convertToSystemTimeLocked(event);
 
             final UserUsageStatsService service =
                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            final long beginIdleTime = service.getBeginIdleTime(event.mPackage);
-            final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage);
-            final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
-                    lastUsedTime, screenOnTime, timeNow);
-            service.reportEvent(event, screenOnTime);
+            // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
+            // about apps that are on some kind of whitelist anyway.
+            final boolean previouslyIdle = mAppIdleHistory.isIdleLocked(
+                    event.mPackage, userId, elapsedRealtime);
+            service.reportEvent(event);
             // Inform listeners if necessary
             if ((event.mEventType == Event.MOVE_TO_FOREGROUND
                     || event.mEventType == Event.MOVE_TO_BACKGROUND
                     || event.mEventType == Event.SYSTEM_INTERACTION
                     || event.mEventType == Event.USER_INTERACTION)) {
+                mAppIdleHistory.reportUsageLocked(event.mPackage, userId, elapsedRealtime);
                 if (previouslyIdle) {
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
                             /* idle = */ 0, event.mPackage));
                     notifyBatteryStats(event.mPackage, userId, false);
-                    mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow);
                 }
             }
         }
@@ -655,28 +612,23 @@
      * the threshold for idle.
      */
     void forceIdleState(String packageName, int userId, boolean idle) {
+        final int appId = getAppId(packageName);
+        if (appId < 0) return;
         synchronized (mLock) {
-            final long timeNow = checkAndGetTimeLocked();
-            final long screenOnTime = getScreenOnTimeLocked();
-            final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000;
+            final long elapsedRealtime = SystemClock.elapsedRealtime();
 
-            final UserUsageStatsService service =
-                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            final long beginIdleTime = service.getBeginIdleTime(packageName);
-            final long lastUsedTime = service.getSystemLastUsedTime(packageName);
-            final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
-                    lastUsedTime, screenOnTime, timeNow);
-            service.setBeginIdleTime(packageName, deviceUsageTime);
-            service.setSystemLastUsedTime(packageName,
-                    timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000);
+            final boolean previouslyIdle = isAppIdleFiltered(packageName, appId,
+                    userId, elapsedRealtime);
+            mAppIdleHistory.setIdleLocked(packageName, userId, idle, elapsedRealtime);
+            final boolean stillIdle = isAppIdleFiltered(packageName, appId,
+                    userId, elapsedRealtime);
             // Inform listeners if necessary
-            if (previouslyIdle != idle) {
+            if (previouslyIdle != stillIdle) {
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
-                        /* idle = */ idle ? 1 : 0, packageName));
-                if (!idle) {
+                        /* idle = */ stillIdle ? 1 : 0, packageName));
+                if (!stillIdle) {
                     notifyBatteryStats(packageName, userId, idle);
                 }
-                mAppIdleHistory.addEntry(packageName, userId, idle, timeNow);
             }
         }
     }
@@ -693,10 +645,11 @@
     /**
      * Called by the Binder stub.
      */
-    void removeUser(int userId) {
+    void onUserRemoved(int userId) {
         synchronized (mLock) {
             Slog.i(TAG, "Removing user " + userId + " and all data.");
             mUserState.remove(userId);
+            mAppIdleHistory.onUserRemoved(userId);
             cleanUpRemovedUsersLocked();
         }
     }
@@ -750,29 +703,12 @@
         }
     }
 
-    private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService,
-            long timeNow, long screenOnTime) {
+    private boolean isAppIdleUnfiltered(String packageName, int userId, long elapsedRealtime) {
         synchronized (mLock) {
-            long beginIdleTime = userService.getBeginIdleTime(packageName);
-            long lastUsedTime = userService.getSystemLastUsedTime(packageName);
-            return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime,
-                    timeNow);
+            return mAppIdleHistory.isIdleLocked(packageName, userId, elapsedRealtime);
         }
     }
 
-    /**
-     * @param beginIdleTime when the app was last used in device usage timebase
-     * @param lastUsedTime wallclock time of when the app was last used
-     * @param screenOnTime screen-on timebase time
-     * @param currentTime current time in device usage timebase
-     * @return whether it's been used far enough in the past to be considered inactive
-     */
-    boolean hasPassedIdleTimeoutLocked(long beginIdleTime, long lastUsedTime,
-            long screenOnTime, long currentTime) {
-        return (beginIdleTime <= screenOnTime - mAppIdleDurationMillis)
-                && (lastUsedTime <= currentTime - mAppIdleWallclockThresholdMillis);
-    }
-
     void addListener(AppIdleStateChangeListener listener) {
         synchronized (mLock) {
             if (!mPackageAccessListeners.contains(listener)) {
@@ -787,32 +723,22 @@
         }
     }
 
-    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long timeNow) {
+    int getAppId(String packageName) {
+        try {
+            ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(packageName,
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES
+                            | PackageManager.MATCH_DISABLED_COMPONENTS);
+            return ai.uid;
+        } catch (NameNotFoundException re) {
+            return -1;
+        }
+    }
+
+    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime) {
         if (mAppIdleParoled) {
             return false;
         }
-        try {
-            ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_UNINSTALLED_PACKAGES
-                            | PackageManager.GET_DISABLED_COMPONENTS);
-            return isAppIdleFiltered(packageName, ai.uid, userId, timeNow);
-        } catch (PackageManager.NameNotFoundException e) {
-        }
-        return false;
-    }
-
-    boolean isAppIdleFiltered(String packageName, int uidForAppId, int userId, long timeNow) {
-        final UserUsageStatsService userService;
-        final long screenOnTime;
-        synchronized (mLock) {
-            if (timeNow == -1) {
-                timeNow = checkAndGetTimeLocked();
-            }
-            userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            screenOnTime = getScreenOnTimeLocked();
-        }
-        return isAppIdleFiltered(packageName, UserHandle.getAppId(uidForAppId), userId,
-                userService, timeNow, screenOnTime);
+        return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
     }
 
     /**
@@ -822,7 +748,7 @@
      * Called by interface impls.
      */
     private boolean isAppIdleFiltered(String packageName, int appId, int userId,
-            UserUsageStatsService userService, long timeNow, long screenOnTime) {
+            long elapsedRealtime) {
         if (packageName == null) return false;
         // If not enabled at all, of course nobody is ever idle.
         if (!mAppIdleEnabled) {
@@ -864,7 +790,7 @@
             return false;
         }
 
-        return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime);
+        return isAppIdleUnfiltered(packageName, userId, elapsedRealtime);
     }
 
     int[] getIdleUidsForUser(int userId) {
@@ -872,14 +798,7 @@
             return new int[0];
         }
 
-        final long timeNow;
-        final UserUsageStatsService userService;
-        final long screenOnTime;
-        synchronized (mLock) {
-            timeNow = checkAndGetTimeLocked();
-            userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            screenOnTime = getScreenOnTimeLocked();
-        }
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
 
         List<ApplicationInfo> apps;
         try {
@@ -899,12 +818,12 @@
 
         // Now resolve all app state.  Iterating over all apps, keeping track of how many
         // we find for each uid and how many of those are idle.
-        for (int i = apps.size()-1; i >= 0; i--) {
+        for (int i = apps.size() - 1; i >= 0; i--) {
             ApplicationInfo ai = apps.get(i);
 
             // Check whether this app is idle.
             boolean idle = isAppIdleFiltered(ai.packageName, UserHandle.getAppId(ai.uid),
-                    userId, userService, timeNow, screenOnTime);
+                    userId, elapsedRealtime);
 
             int index = uidStates.indexOfKey(ai.uid);
             if (index < 0) {
@@ -990,8 +909,11 @@
         for (int i = 0; i < userCount; i++) {
             UserUsageStatsService service = mUserState.valueAt(i);
             service.persistActiveStats();
+            mAppIdleHistory.writeAppIdleTimesLocked(mUserState.keyAt(i));
         }
-
+        // Persist elapsed time periodically, in case screen doesn't get toggled
+        // until the next boot
+        mAppIdleHistory.writeElapsedTimeLocked();
         mHandler.removeMessages(MSG_FLUSH_TO_DISK);
     }
 
@@ -1000,7 +922,6 @@
      */
     void dump(String[] args, PrintWriter pw) {
         synchronized (mLock) {
-            final long screenOnTime = getScreenOnTimeLocked();
             IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
             ArraySet<String> argSet = new ArraySet<>();
             argSet.addAll(Arrays.asList(args));
@@ -1011,27 +932,28 @@
                 idpw.println();
                 idpw.increaseIndent();
                 if (argSet.contains("--checkin")) {
-                    mUserState.valueAt(i).checkin(idpw, screenOnTime);
+                    mUserState.valueAt(i).checkin(idpw);
                 } else {
-                    mUserState.valueAt(i).dump(idpw, screenOnTime);
+                    mUserState.valueAt(i).dump(idpw);
                     idpw.println();
-                    if (args.length > 0 && "history".equals(args[0])) {
-                        mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
+                    if (args.length > 0) {
+                        if ("history".equals(args[0])) {
+                            mAppIdleHistory.dumpHistory(idpw, mUserState.keyAt(i));
+                        } else if ("flush".equals(args[0])) {
+                            UsageStatsService.this.flushToDiskLocked();
+                            pw.println("Flushed stats to disk");
+                        }
                     }
                 }
+                mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
                 idpw.decreaseIndent();
             }
-            pw.print("Screen On Timebase: ");
-            pw.print(screenOnTime);
-            pw.print(" (");
-            TimeUtils.formatDuration(screenOnTime, pw);
-            pw.println(")");
 
             pw.println();
             pw.println("Settings:");
 
             pw.print("  mAppIdleDurationMillis=");
-            TimeUtils.formatDuration(mAppIdleDurationMillis, pw);
+            TimeUtils.formatDuration(mAppIdleScreenThresholdMillis, pw);
             pw.println();
 
             pw.print("  mAppIdleWallclockThresholdMillis=");
@@ -1057,11 +979,6 @@
             pw.print("mLastAppIdleParoledTime=");
             TimeUtils.formatDuration(mLastAppIdleParoledTime, pw);
             pw.println();
-            pw.print("mScreenOnTime="); TimeUtils.formatDuration(mScreenOnTime, pw);
-            pw.println();
-            pw.print("mLastScreenOnEventRealtime=");
-            TimeUtils.formatDuration(mLastScreenOnEventRealtime, pw);
-            pw.println();
         }
     }
 
@@ -1082,7 +999,7 @@
                     break;
 
                 case MSG_REMOVE_USER:
-                    removeUser(msg.arg1);
+                    onUserRemoved(msg.arg1);
                     break;
 
                 case MSG_INFORM_LISTENERS:
@@ -1179,13 +1096,13 @@
                 }
 
                 // Default: 12 hours of screen-on time sans dream-time
-                mAppIdleDurationMillis = mParser.getLong(KEY_IDLE_DURATION,
+                mAppIdleScreenThresholdMillis = mParser.getLong(KEY_IDLE_DURATION,
                        COMPRESS_TIME ? ONE_MINUTE * 4 : 12 * 60 * ONE_MINUTE);
 
                 mAppIdleWallclockThresholdMillis = mParser.getLong(KEY_WALLCLOCK_THRESHOLD,
                         COMPRESS_TIME ? ONE_MINUTE * 8 : 2L * 24 * 60 * ONE_MINUTE); // 2 days
 
-                mCheckIdleIntervalMillis = Math.min(mAppIdleDurationMillis / 4,
+                mCheckIdleIntervalMillis = Math.min(mAppIdleScreenThresholdMillis / 4,
                         COMPRESS_TIME ? ONE_MINUTE : 8 * 60 * ONE_MINUTE); // 8 hours
 
                 // Default: 24 hours between paroles
@@ -1194,6 +1111,8 @@
 
                 mAppIdleParoleDurationMillis = mParser.getLong(KEY_PAROLE_DURATION,
                         COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE); // 10 minutes
+                mAppIdleHistory.setThresholds(mAppIdleWallclockThresholdMillis,
+                        mAppIdleScreenThresholdMillis);
             }
         }
     }
@@ -1284,7 +1203,8 @@
             }
             final long token = Binder.clearCallingIdentity();
             try {
-                return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId, -1);
+                return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId,
+                        SystemClock.elapsedRealtime());
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1304,11 +1224,9 @@
                     "No permission to change app idle state");
             final long token = Binder.clearCallingIdentity();
             try {
-                PackageInfo pi = AppGlobals.getPackageManager().getPackageInfo(packageName,
-                        PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
-                if (pi == null) return;
+                final int appId = getAppId(packageName);
+                if (appId < 0) return;
                 UsageStatsService.this.setAppIdle(packageName, idle, userId);
-            } catch (RemoteException re) {
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1335,8 +1253,6 @@
             }
             UsageStatsService.this.dump(args, pw);
         }
-
-
     }
 
     /**
@@ -1411,7 +1327,8 @@
 
         @Override
         public boolean isAppIdle(String packageName, int uidForAppId, int userId) {
-            return UsageStatsService.this.isAppIdleFiltered(packageName, uidForAppId, userId, -1);
+            return UsageStatsService.this.isAppIdleFiltered(packageName, uidForAppId, userId,
+                    SystemClock.elapsedRealtime());
         }
 
         @Override
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index f2ca3a4..c95ff23 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -26,7 +26,6 @@
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
-import android.text.TextUtils;
 
 import java.io.IOException;
 import java.net.ProtocolException;
@@ -55,13 +54,11 @@
 
     // Time attributes stored as an offset of the beginTime.
     private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
-    private static final String LAST_TIME_ACTIVE_SYSTEM_ATTR = "lastTimeActiveSystem";
-    private static final String BEGIN_IDLE_TIME_ATTR = "beginIdleTime";
     private static final String END_TIME_ATTR = "endTime";
     private static final String TIME_ATTR = "time";
 
     private static void loadUsageStats(XmlPullParser parser, IntervalStats statsOut)
-            throws XmlPullParserException, IOException {
+            throws IOException {
         final String pkg = parser.getAttributeValue(null, PACKAGE_ATTR);
         if (pkg == null) {
             throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
@@ -72,20 +69,6 @@
         // Apply the offset to the beginTime to find the absolute time.
         stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
                 parser, LAST_TIME_ACTIVE_ATTR);
-
-        final String lastTimeUsedSystem = parser.getAttributeValue(null,
-                LAST_TIME_ACTIVE_SYSTEM_ATTR);
-        if (TextUtils.isEmpty(lastTimeUsedSystem)) {
-            // If the field isn't present, use the old one.
-            stats.mLastTimeSystemUsed = stats.mLastTimeUsed;
-        } else {
-            stats.mLastTimeSystemUsed = statsOut.beginTime + Long.parseLong(lastTimeUsedSystem);
-        }
-
-        final String beginIdleTime = parser.getAttributeValue(null, BEGIN_IDLE_TIME_ATTR);
-        if (!TextUtils.isEmpty(beginIdleTime)) {
-            stats.mBeginIdleTime = Long.parseLong(beginIdleTime);
-        }
         stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
         stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR);
     }
@@ -141,13 +124,10 @@
         // Write the time offset.
         XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
                 usageStats.mLastTimeUsed - stats.beginTime);
-        XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_SYSTEM_ATTR,
-                usageStats.mLastTimeSystemUsed - stats.beginTime);
 
         XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
         XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
         XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent);
-        XmlUtils.writeLongAttribute(xml, BEGIN_IDLE_TIME_ATTR, usageStats.mBeginIdleTime);
 
         xml.endTag(null, PACKAGE_TAG);
     }
@@ -255,7 +235,6 @@
         }
         xml.endTag(null, PACKAGES_TAG);
 
-
         xml.startTag(null, CONFIGURATIONS_TAG);
         final int configCount = stats.configurations.size();
         for (int i = 0; i < configCount; i++) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index f2045d3..7d003f3 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -59,7 +59,6 @@
     private final Context mContext;
     private final UsageStatsDatabase mDatabase;
     private final IntervalStats[] mCurrentStats;
-    private IntervalStats mAppIdleRollingWindow;
     private boolean mStatsChanged = false;
     private final UnixCalendar mDailyExpiryDate;
     private final StatsUpdatedListener mListener;
@@ -74,7 +73,11 @@
     interface StatsUpdatedListener {
         void onStatsUpdated();
         void onStatsReloaded();
-        long getAppIdleRollingWindowDurationMillis();
+        /**
+         * Callback that a system update was detected
+         * @param mUserId user that needs to be initialized
+         */
+        void onNewUpdate(int mUserId);
     }
 
     UserUsageStatsService(Context context, int userId, File usageStatsDir,
@@ -88,7 +91,7 @@
         mUserId = userId;
     }
 
-    void init(final long currentTimeMillis, final long deviceUsageTime) {
+    void init(final long currentTimeMillis) {
         mDatabase.init(currentTimeMillis);
 
         int nullCount = 0;
@@ -112,7 +115,7 @@
 
             // By calling loadActiveStats, we will
             // generate new stats for each bucket.
-            loadActiveStats(currentTimeMillis, /*resetBeginIdleTime=*/ false);
+            loadActiveStats(currentTimeMillis);
         } else {
             // Set up the expiry date to be one day from the latest daily stat.
             // This may actually be today and we will rollover on the first event
@@ -136,54 +139,18 @@
             stat.updateConfigurationStats(null, stat.lastTimeSaved);
         }
 
-        refreshAppIdleRollingWindow(currentTimeMillis, deviceUsageTime);
-
         if (mDatabase.isNewUpdate()) {
-            initializeDefaultsForApps(currentTimeMillis, deviceUsageTime,
-                    mDatabase.isFirstUpdate());
+            notifyNewUpdate();
         }
     }
 
-    /**
-     * If any of the apps don't have a last-used entry, add one now.
-     * @param currentTimeMillis the current time
-     * @param firstUpdate if it is the first update, touch all installed apps, otherwise only
-     *        touch the system apps
-     */
-    private void initializeDefaultsForApps(long currentTimeMillis, long deviceUsageTime,
-            boolean firstUpdate) {
-        PackageManager pm = mContext.getPackageManager();
-        List<PackageInfo> packages = pm.getInstalledPackagesAsUser(0, mUserId);
-        final int packageCount = packages.size();
-        for (int i = 0; i < packageCount; i++) {
-            final PackageInfo pi = packages.get(i);
-            String packageName = pi.packageName;
-            if (pi.applicationInfo != null && (firstUpdate || pi.applicationInfo.isSystemApp())
-                    && getBeginIdleTime(packageName) == -1) {
-                for (IntervalStats stats : mCurrentStats) {
-                    stats.update(packageName, currentTimeMillis, Event.SYSTEM_INTERACTION);
-                    stats.updateBeginIdleTime(packageName, deviceUsageTime);
-                }
-
-                mAppIdleRollingWindow.update(packageName, currentTimeMillis,
-                        Event.SYSTEM_INTERACTION);
-                mAppIdleRollingWindow.updateBeginIdleTime(packageName, deviceUsageTime);
-                mStatsChanged = true;
-            }
-        }
-        // Persist the new OTA-related access stats.
-        persistActiveStats();
-    }
-
-    void onTimeChanged(long oldTime, long newTime, long deviceUsageTime,
-                       boolean resetBeginIdleTime) {
+    void onTimeChanged(long oldTime, long newTime) {
         persistActiveStats();
         mDatabase.onTimeChanged(newTime - oldTime);
-        loadActiveStats(newTime, resetBeginIdleTime);
-        refreshAppIdleRollingWindow(newTime, deviceUsageTime);
+        loadActiveStats(newTime);
     }
 
-    void reportEvent(UsageEvents.Event event, long deviceUsageTime) {
+    void reportEvent(UsageEvents.Event event) {
         if (DEBUG) {
             Slog.d(TAG, mLogPrefix + "Got usage event for " + event.mPackage
                     + "[" + event.mTimeStamp + "]: "
@@ -192,7 +159,7 @@
 
         if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
             // Need to rollover
-            rolloverStats(event.mTimeStamp, deviceUsageTime);
+            rolloverStats(event.mTimeStamp);
         }
 
         final IntervalStats currentDailyStats = mCurrentStats[UsageStatsManager.INTERVAL_DAILY];
@@ -218,35 +185,9 @@
                 stats.updateConfigurationStats(newFullConfig, event.mTimeStamp);
             } else {
                 stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
-                stats.updateBeginIdleTime(event.mPackage, deviceUsageTime);
             }
         }
 
-        if (event.mEventType != Event.CONFIGURATION_CHANGE) {
-            mAppIdleRollingWindow.update(event.mPackage, event.mTimeStamp, event.mEventType);
-            mAppIdleRollingWindow.updateBeginIdleTime(event.mPackage, deviceUsageTime);
-        }
-
-        notifyStatsChanged();
-    }
-
-    /**
-     * Sets the beginIdleTime for each of the intervals.
-     * @param beginIdleTime
-     */
-    void setBeginIdleTime(String packageName, long beginIdleTime) {
-        for (IntervalStats stats : mCurrentStats) {
-            stats.updateBeginIdleTime(packageName, beginIdleTime);
-        }
-        mAppIdleRollingWindow.updateBeginIdleTime(packageName, beginIdleTime);
-        notifyStatsChanged();
-    }
-
-    void setSystemLastUsedTime(String packageName, long lastUsedTime) {
-        for (IntervalStats stats : mCurrentStats) {
-            stats.updateSystemLastUsedTime(packageName, lastUsedTime);
-        }
-        mAppIdleRollingWindow.updateSystemLastUsedTime(packageName, lastUsedTime);
         notifyStatsChanged();
     }
 
@@ -404,24 +345,6 @@
         return new UsageEvents(results, table);
     }
 
-    long getBeginIdleTime(String packageName) {
-        UsageStats packageUsage;
-        if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) {
-            return -1;
-        } else {
-            return packageUsage.getBeginIdleTime();
-        }
-    }
-
-    long getSystemLastUsedTime(String packageName) {
-        UsageStats packageUsage;
-        if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) {
-            return -1;
-        } else {
-            return packageUsage.getLastTimeSystemUsed();
-        }
-    }
-
     void persistActiveStats() {
         if (mStatsChanged) {
             Slog.i(TAG, mLogPrefix + "Flushing usage stats to disk");
@@ -436,7 +359,7 @@
         }
     }
 
-    private void rolloverStats(final long currentTimeMillis, final long deviceUsageTime) {
+    private void rolloverStats(final long currentTimeMillis) {
         final long startTime = SystemClock.elapsedRealtime();
         Slog.i(TAG, mLogPrefix + "Rolling over usage stats");
 
@@ -463,7 +386,7 @@
 
         persistActiveStats();
         mDatabase.prune(currentTimeMillis);
-        loadActiveStats(currentTimeMillis, /*resetBeginIdleTime=*/ false);
+        loadActiveStats(currentTimeMillis);
 
         final int continueCount = continuePreviousDay.size();
         for (int i = 0; i < continueCount; i++) {
@@ -477,8 +400,6 @@
         }
         persistActiveStats();
 
-        refreshAppIdleRollingWindow(currentTimeMillis, deviceUsageTime);
-
         final long totalTime = SystemClock.elapsedRealtime() - startTime;
         Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime
                 + " milliseconds");
@@ -491,7 +412,11 @@
         }
     }
 
-    private void loadActiveStats(final long currentTimeMillis, boolean resetBeginIdleTime) {
+    private void notifyNewUpdate() {
+        mListener.onNewUpdate(mUserId);
+    }
+
+    private void loadActiveStats(final long currentTimeMillis) {
         for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) {
             final IntervalStats stats = mDatabase.getLatestUsageStats(intervalType);
             if (stats != null && currentTimeMillis - 500 >= stats.endTime &&
@@ -514,12 +439,6 @@
                 mCurrentStats[intervalType].beginTime = currentTimeMillis;
                 mCurrentStats[intervalType].endTime = currentTimeMillis + 1;
             }
-
-            if (resetBeginIdleTime) {
-                for (UsageStats usageStats : mCurrentStats[intervalType].packageStats.values()) {
-                    usageStats.mBeginIdleTime = 0;
-                }
-            }
         }
 
         mStatsChanged = false;
@@ -538,96 +457,28 @@
                 mDailyExpiryDate.getTimeInMillis() + ")");
     }
 
-    private static void mergePackageStats(IntervalStats dst, IntervalStats src,
-                                          final long deviceUsageTime) {
-        dst.endTime = Math.max(dst.endTime, src.endTime);
-
-        final int srcPackageCount = src.packageStats.size();
-        for (int i = 0; i < srcPackageCount; i++) {
-            final String packageName = src.packageStats.keyAt(i);
-            final UsageStats srcStats = src.packageStats.valueAt(i);
-            UsageStats dstStats = dst.packageStats.get(packageName);
-            if (dstStats == null) {
-                dstStats = new UsageStats(srcStats);
-                dst.packageStats.put(packageName, dstStats);
-            } else {
-                dstStats.add(src.packageStats.valueAt(i));
-            }
-
-            // App idle times can not begin in the future. This happens if we had a time change.
-            if (dstStats.mBeginIdleTime > deviceUsageTime) {
-                dstStats.mBeginIdleTime = deviceUsageTime;
-            }
-        }
-    }
-
-    /**
-     * App idle operates on a rolling window of time. When we roll over time, we end up with a
-     * period of time where in-memory stats are empty and we don't hit the disk for older stats
-     * for performance reasons. Suddenly all apps will become idle.
-     *
-     * Instead, at times we do a deep query to find all the apps that have run in the past few
-     * days and keep the cached data up to date.
-     *
-     * @param currentTimeMillis
-     */
-    void refreshAppIdleRollingWindow(final long currentTimeMillis, final long deviceUsageTime) {
-        // Start the rolling window for AppIdle requests.
-        final long startRangeMillis = currentTimeMillis -
-                mListener.getAppIdleRollingWindowDurationMillis();
-
-        List<IntervalStats> stats = mDatabase.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
-                startRangeMillis, currentTimeMillis, new StatCombiner<IntervalStats>() {
-                    @Override
-                    public void combine(IntervalStats stats, boolean mutable,
-                                        List<IntervalStats> accumulatedResult) {
-                        IntervalStats accum;
-                        if (accumulatedResult.isEmpty()) {
-                            accum = new IntervalStats();
-                            accum.beginTime = stats.beginTime;
-                            accumulatedResult.add(accum);
-                        } else {
-                            accum = accumulatedResult.get(0);
-                        }
-
-                        mergePackageStats(accum, stats, deviceUsageTime);
-                    }
-                });
-
-        if (stats == null || stats.isEmpty()) {
-            mAppIdleRollingWindow = new IntervalStats();
-            mergePackageStats(mAppIdleRollingWindow,
-                    mCurrentStats[UsageStatsManager.INTERVAL_YEARLY], deviceUsageTime);
-        } else {
-            mAppIdleRollingWindow = stats.get(0);
-        }
-    }
-
     //
     // -- DUMP related methods --
     //
 
-    void checkin(final IndentingPrintWriter pw, final long screenOnTime) {
+    void checkin(final IndentingPrintWriter pw) {
         mDatabase.checkinDailyFiles(new UsageStatsDatabase.CheckinAction() {
             @Override
             public boolean checkin(IntervalStats stats) {
-                printIntervalStats(pw, stats, screenOnTime, false);
+                printIntervalStats(pw, stats, false);
                 return true;
             }
         });
     }
 
-    void dump(IndentingPrintWriter pw, final long screenOnTime) {
+    void dump(IndentingPrintWriter pw) {
         // This is not a check-in, only dump in-memory stats.
         for (int interval = 0; interval < mCurrentStats.length; interval++) {
             pw.print("In-memory ");
             pw.print(intervalToString(interval));
             pw.println(" stats");
-            printIntervalStats(pw, mCurrentStats[interval], screenOnTime, true);
+            printIntervalStats(pw, mCurrentStats[interval], true);
         }
-
-        pw.println("AppIdleRollingWindow cache");
-        printIntervalStats(pw, mAppIdleRollingWindow, screenOnTime, true);
     }
 
     private String formatDateTime(long dateTime, boolean pretty) {
@@ -644,7 +495,7 @@
         return Long.toString(elapsedTime);
     }
 
-    void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats, long screenOnTime,
+    void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats,
             boolean prettyDates) {
         if (prettyDates) {
             pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext,
@@ -665,10 +516,6 @@
             pw.printPair("totalTime",
                     formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates));
             pw.printPair("lastTime", formatDateTime(usageStats.mLastTimeUsed, prettyDates));
-            pw.printPair("lastTimeSystem",
-                    formatDateTime(usageStats.mLastTimeSystemUsed, prettyDates));
-            pw.printPair("inactiveTime",
-                    formatElapsedTime(screenOnTime - usageStats.mBeginIdleTime, prettyDates));
             pw.println();
         }
         pw.decreaseIndent();
diff --git a/services/usb/java/com/android/server/usb/MtpNotificationManager.java b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
index 203d35e..17039bb 100644
--- a/services/usb/java/com/android/server/usb/MtpNotificationManager.java
+++ b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
@@ -30,7 +30,6 @@
 import android.hardware.usb.UsbInterface;
 import android.hardware.usb.UsbManager;
 import android.os.UserHandle;
-import android.util.Log;
 
 /**
  * Manager for MTP storage notification.
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 597f915ec..354075e 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -298,6 +298,10 @@
         }
     }
 
+    public ModuleProperties getModuleProperties() {
+        return moduleProperties;
+    }
+
     //---- SoundTrigger.StatusListener methods
     @Override
     public void onRecognition(RecognitionEvent event) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
index 0a06bfa..7722876 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
@@ -44,9 +44,6 @@
     public static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR;
     public static final int STATUS_OK = SoundTrigger.STATUS_OK;
 
-    /** The {@link ModuleProperties} for the system, or null if none exists. */
-    private ModuleProperties moduleProperties;
-
     /**
      * Starts recognition for the given keyphraseId.
      *
@@ -76,9 +73,7 @@
      */
     public abstract void stopAllRecognitions();
 
-    public ModuleProperties getModuleProperties() {
-        return moduleProperties;
-    }
+    public abstract ModuleProperties getModuleProperties();
 
     public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
 }
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 5e8fe9e..682f4a4 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -23,6 +23,7 @@
 import android.hardware.soundtrigger.SoundTrigger;
 import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
 import android.os.Parcel;
 import android.os.ParcelUuid;
@@ -180,6 +181,11 @@
         }
 
         @Override
+        public ModuleProperties getModuleProperties() {
+            return mSoundTriggerHelper.getModuleProperties();
+        }
+
+        @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             mSoundTriggerHelper.dump(fd, pw, args);
         }
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 56eb7ec..d45938c 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -348,11 +348,6 @@
     }
 
     private void checkCallTree(ParcelableCall parcelableCall) {
-        if (parcelableCall.getParentCallId() != null &&
-                !mCallByTelecomCallId.containsKey(parcelableCall.getParentCallId())) {
-            Log.wtf(this, "ParcelableCall %s has nonexistent parent %s",
-                    parcelableCall.getId(), parcelableCall.getParentCallId());
-        }
         if (parcelableCall.getChildCallIds() != null) {
             for (int i = 0; i < parcelableCall.getChildCallIds().size(); i++) {
                 if (!mCallByTelecomCallId.containsKey(parcelableCall.getChildCallIds().get(i))) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 72ff272..c122c5a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1414,6 +1414,23 @@
         return result;
     }
 
+    /**
+     * 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.
+     */
+    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);
+            }
+        }
+    }
+
     private ITelecomService getTelecomService() {
         if (mTelecomServiceOverride != null) {
             return mTelecomServiceOverride;
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index af36b3e..95c8db5 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -243,4 +243,9 @@
      * @see TelecomServiceImpl#setDefaultDialer
      */
     boolean setDefaultDialer(in String packageName);
+
+    /**
+    * @see TelecomServiceImpl#launchManageBlockedNumbersActivity
+    **/
+    void launchManageBlockedNumbersActivity(in String callingPackageName);
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 4368b81..3ad7d34 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -591,6 +591,14 @@
     @SystemApi
     public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
 
+    /**
+     * The duration in seconds that platform call and message blocking is disabled after the user
+     * contacts emergency services. Platform considers values in the range 0 to 604800 (one week) as
+     * valid. See {@link android.provider.BlockedNumberContract#isBlocked(Context, String)}).
+     */
+    public static final String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT =
+            "duration_blocking_disabled_after_emergency_int";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -660,6 +668,7 @@
                 "max_retries=3, 5000, 5000, 5000");
         sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG, 20000);
         sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG, 3000);
+        sDefaults.putInt(KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, 7200);
 
         sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 8443490..9eb1304 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -187,6 +187,13 @@
      */
     public static final int CDMA_ALREADY_ACTIVATED         = 49;
 
+    /**
+     * The call was terminated because it is not possible to place a video call while TTY is
+     * enabled.
+     * {@hide}
+     */
+    public static final int VIDEO_CALL_NOT_ALLOWED_WHILE_TTY_ENABLED = 50;
+
     //*********************************************************************************************
     // When adding a disconnect type:
     // 1) Please assign the new type the next id value below.
@@ -202,7 +209,7 @@
     public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
 
     /** Largest valid value for call disconnect codes. */
-    public static final int MAXIMUM_VALID_VALUE = CDMA_ALREADY_ACTIVATED;
+    public static final int MAXIMUM_VALID_VALUE = VIDEO_CALL_NOT_ALLOWED_WHILE_TTY_ENABLED;
 
     /** Private constructor to avoid class instantiation. */
     private DisconnectCause() {
@@ -310,6 +317,8 @@
             return "IMS_MERGED_SUCCESSFULLY";
         case CDMA_ALREADY_ACTIVATED:
             return "CDMA_ALREADY_ACTIVATED";
+        case VIDEO_CALL_NOT_ALLOWED_WHILE_TTY_ENABLED:
+                return "VIDEO_CALL_NOT_ALLOWED_WHILE_TTY_ENABLED";
         default:
             return "INVALID: " + cause;
         }
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index d1d6e0d..6229ed9 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -25,6 +25,7 @@
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.Typeface;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.DisplayMetrics;
@@ -338,7 +339,7 @@
     public static String givePrintableIccid(String iccId) {
         String iccIdToPrint = null;
         if (iccId != null) {
-            if (iccId.length() > 9) {
+            if (iccId.length() > 9 && !Build.IS_DEBUGGABLE) {
                 iccIdToPrint = iccId.substring(0, 9) + "XXXXXXXXXXX";
             } else {
                 iccIdToPrint = iccId;
diff --git a/telephony/java/com/android/ims/ImsCallForwardInfo.java b/telephony/java/com/android/ims/ImsCallForwardInfo.java
index 3f8fd19..eeee0fc 100644
--- a/telephony/java/com/android/ims/ImsCallForwardInfo.java
+++ b/telephony/java/com/android/ims/ImsCallForwardInfo.java
@@ -31,6 +31,8 @@
     public int mStatus;
     // 0x91: International, 0x81: Unknown
     public int mToA;
+    // Service class
+    public int mServiceClass;
     // Number (it will not include the "sip" or "tel" URI scheme)
     public String mNumber;
     // No reply timer for CF
@@ -55,13 +57,16 @@
         out.writeInt(mToA);
         out.writeString(mNumber);
         out.writeInt(mTimeSeconds);
+        out.writeInt(mServiceClass);
     }
 
     @Override
     public String toString() {
         return super.toString() + ", Condition: " + mCondition
             + ", Status: " + ((mStatus == 0) ? "disabled" : "enabled")
-            + ", ToA: " + mToA + ", Number=" + mNumber
+            + ", ToA: " + mToA
+            + ", Service Class: " + mServiceClass
+            + ", Number=" + mNumber
             + ", Time (seconds): " + mTimeSeconds;
     }
 
@@ -71,6 +76,7 @@
         mToA = in.readInt();
         mNumber = in.readString();
         mTimeSeconds = in.readInt();
+        mServiceClass = in.readInt();
     }
 
     public static final Creator<ImsCallForwardInfo> CREATOR =
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index 2769a2b..c909c6d 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -84,6 +84,8 @@
     public static final int CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED = 147;
     // IMS call is already terminated (in TERMINATED state)
     public static final int CODE_LOCAL_CALL_TERMINATED = 148;
+    // Handover not feasible
+    public static final int CODE_LOCAL_HO_NOT_FEASIBLE = 149;
 
     /**
      * TIMEOUT (IMS -> Telephony)
@@ -153,6 +155,9 @@
     public static final int CODE_SIP_USER_REJECTED = 361;
     // Others
     public static final int CODE_SIP_GLOBAL_ERROR = 362;
+    // Emergency failure
+    public static final int CODE_EMERGENCY_TEMP_FAILURE = 363;
+    public static final int CODE_EMERGENCY_PERM_FAILURE = 364;
 
     /**
      * MEDIA (IMS -> Telephony)
@@ -236,6 +241,14 @@
     public static final int CODE_ANSWERED_ELSEWHERE = 1014;
 
     /**
+     * Supplementary services (HOLD/RESUME) failure error codes.
+     * Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision.
+     */
+    public static final int CODE_SUPP_SVC_FAILED = 1201;
+    public static final int CODE_SUPP_SVC_CANCELLED = 1202;
+    public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203;
+
+    /**
      * Network string error messages.
      * mExtraMessage may have these values.
      */
diff --git a/telephony/java/com/android/ims/ImsStreamMediaProfile.java b/telephony/java/com/android/ims/ImsStreamMediaProfile.java
index 5a99212..216cef5 100644
--- a/telephony/java/com/android/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/com/android/ims/ImsStreamMediaProfile.java
@@ -51,6 +51,16 @@
     public static final int AUDIO_QUALITY_GSM_EFR = 8;
     public static final int AUDIO_QUALITY_GSM_FR = 9;
     public static final int AUDIO_QUALITY_GSM_HR = 10;
+    public static final int AUDIO_QUALITY_G711U = 11;
+    public static final int AUDIO_QUALITY_G723 = 12;
+    public static final int AUDIO_QUALITY_G711A = 13;
+    public static final int AUDIO_QUALITY_G722 = 14;
+    public static final int AUDIO_QUALITY_G711AB = 15;
+    public static final int AUDIO_QUALITY_G729 = 16;
+    public static final int AUDIO_QUALITY_EVS_NB = 17;
+    public static final int AUDIO_QUALITY_EVS_WB = 18;
+    public static final int AUDIO_QUALITY_EVS_SWB = 19;
+    public static final int AUDIO_QUALITY_EVS_FB = 20;
 
    /**
      * Video information
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 7d5645e..429839f 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -77,6 +77,21 @@
     int SIM_SAP_MSG_SIZE_TOO_SMALL = 34;
     int SIM_SAP_CONNECT_OK_CALL_ONGOING = 35;
     int LCE_NOT_SUPPORTED = 36;               /* Link Capacity Estimation (LCE) not supported */
+    int NO_MEMORY = 37;                       /* Not sufficient memory to process the request */
+    int INTERNAL_ERR = 38;                    /* Hit unexpected vendor internal error scenario */
+    int SYSTEM_ERR = 39;                      /* Hit platform or system error */
+    int MODEM_ERR = 40;                       /* Hit unexpected modem error */
+    int INVALID_STATE = 41;                   /* Can not process the request as vendor RIL is in
+                                                   invalid state. */
+    int NO_RESOURCES = 42;                    /* Not sufficient resource to process the request */
+    int SIM_ERR = 43;                         /* Received error from SIM card */
+    int INVALID_ARGUMENTS = 44;               /* Received invalid arguments in request */
+    int INVALID_SIM_STATE = 45;               /* Can not process the request in current SIM state */
+    int INVALID_MODEM_STATE = 46;             /* Can not process the request in current Modem state */
+    int INVALID_CALL_ID = 47;                 /* Received invalid call id in request */
+    int NO_SMS_TO_ACK = 48;                   /* ACK received when there is no SMS to ack */
+    int NETWORK_ERR = 49;                     /* Received error from network */
+    int REQUEST_RATE_LIMITED = 50;            /* Operation denied due to overly-frequent requests */
 
 
     /* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index b028ce6..de7b9c2 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -356,6 +356,15 @@
         </activity>
 
         <activity
+                android:name="MovingSurfaceViewActivity"
+                android:label="SurfaceView/Animated Movement">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.hwui.TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="GLTextureViewActivity"
                 android:label="TextureView/OpenGL">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java
new file mode 100644
index 0000000..cd15ef1
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MovingSurfaceViewActivity.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.SurfaceHolder;
+import android.view.SurfaceHolder.Callback;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.animation.LinearInterpolator;
+import android.widget.FrameLayout;
+
+public class MovingSurfaceViewActivity extends Activity implements Callback {
+    static final String TAG = "MovingSurfaceView";
+    SurfaceView mSurfaceView;
+    ObjectAnimator mAnimator;
+
+    class MySurfaceView extends SurfaceView {
+        boolean mSlowToggled;
+
+        public MySurfaceView(Context context) {
+            super(context);
+            setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mSlowToggled = !mSlowToggled;
+                    Log.d(TAG, "SLOW MODE: " + mSlowToggled);
+                    invalidate();
+                }
+            });
+            setWillNotDraw(false);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            super.draw(canvas);
+            if (mSlowToggled) {
+                try {
+                    Thread.sleep(16);
+                } catch (InterruptedException e) {}
+            }
+        }
+
+        public void setMyTranslationY(float ty) {
+            setTranslationY(ty);
+            if (mSlowToggled) {
+                invalidate();
+            }
+        }
+
+        public float getMyTranslationY() {
+            return getTranslationY();
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        FrameLayout content = new FrameLayout(this);
+
+        mSurfaceView = new MySurfaceView(this);
+        mSurfaceView.getHolder().addCallback(this);
+
+        final float density = getResources().getDisplayMetrics().density;
+        int size = (int) (200 * density);
+
+        content.addView(mSurfaceView, new FrameLayout.LayoutParams(
+                size, size, Gravity.CENTER));
+        mAnimator = ObjectAnimator.ofFloat(mSurfaceView, "myTranslationY",
+                0, size);
+        mAnimator.setRepeatMode(ObjectAnimator.REVERSE);
+        mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
+        mAnimator.setDuration(200);
+        mAnimator.setInterpolator(new LinearInterpolator());
+        setContentView(content);
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        Canvas canvas = holder.lockCanvas();
+        canvas.drawARGB(0xFF, 0x00, 0xFF, 0x00);
+        holder.unlockCanvasAndPost(canvas);
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mAnimator.start();
+    }
+
+    @Override
+    protected void onPause() {
+        mAnimator.pause();
+        super.onPause();
+    }
+}
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 5ad3379..40466bd 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -873,14 +873,15 @@
 
 static void analyze_image(const char *imageName, image_info &imageInfo, int grayscaleTolerance,
                           png_colorp rgbPalette, png_bytep alphaPalette,
-                          int *paletteEntries, bool *hasTransparency, int *colorType,
-                          png_bytepp outRows)
+                          int *paletteEntries, int *alphaPaletteEntries, bool *hasTransparency,
+                          int *colorType, png_bytepp outRows)
 {
     int w = imageInfo.width;
     int h = imageInfo.height;
-    int i, j, rr, gg, bb, aa, idx;
-    uint32_t colors[256], col;
-    int num_colors = 0;
+    int i, j, rr, gg, bb, aa, idx;;
+    uint32_t opaqueColors[256], alphaColors[256];
+    uint32_t col;
+    int numOpaqueColors = 0, numAlphaColors = 0;
     int maxGrayDeviation = 0;
 
     bool isOpaque = true;
@@ -891,6 +892,10 @@
     // 1. Every pixel has R == G == B (grayscale)
     // 2. Every pixel has A == 255 (opaque)
     // 3. There are no more than 256 distinct RGBA colors
+    //        We will track opaque colors separately from colors with
+    //        alpha.  This allows us to reencode the color table more
+    //        efficiently (color tables entries without a corresponding
+    //        alpha value are assumed to be opaque).
 
     if (kIsDebug) {
         printf("Initial image data:\n");
@@ -901,10 +906,34 @@
         png_bytep row = imageInfo.rows[j];
         png_bytep out = outRows[j];
         for (i = 0; i < w; i++) {
-            rr = *row++;
-            gg = *row++;
-            bb = *row++;
-            aa = *row++;
+
+            // Make sure any zero alpha pixels are fully zeroed.  On average,
+            // each of our PNG assets seem to have about four distinct pixels
+            // with zero alpha.
+            // There are several advantages to setting these to zero:
+            // (1) Images are more likely able to be encodable with a palette.
+            // (2) Image palettes will be smaller.
+            // (3) Premultiplied and unpremultiplied PNG decodes can skip
+            //     writing zeros to memory, often saving significant numbers
+            //     of memory pages.
+            aa = *(row + 3);
+            if (aa == 0) {
+                rr = 0;
+                gg = 0;
+                bb = 0;
+
+                // Also set red, green, and blue to zero in "row".  If we later
+                // decide to encode the PNG as RGB or RGBA, we will use the
+                // values stored there.
+                *(row) = 0;
+                *(row + 1) = 0;
+                *(row + 2) = 0;
+            } else {
+                rr = *(row);
+                gg = *(row + 1);
+                bb = *(row + 2);
+            }
+            row += 4;
 
             int odev = maxGrayDeviation;
             maxGrayDeviation = MAX(ABS(rr - gg), maxGrayDeviation);
@@ -943,36 +972,68 @@
             if (isPalette) {
                 col = (uint32_t) ((rr << 24) | (gg << 16) | (bb << 8) | aa);
                 bool match = false;
-                for (idx = 0; idx < num_colors; idx++) {
-                    if (colors[idx] == col) {
-                        match = true;
-                        break;
+
+                if (aa == 0xff) {
+                    for (idx = 0; idx < numOpaqueColors; idx++) {
+                        if (opaqueColors[idx] == col) {
+                            match = true;
+                            break;
+                        }
                     }
+
+                    if (!match) {
+                        if (numOpaqueColors < 256) {
+                            opaqueColors[numOpaqueColors] = col;
+                        }
+                        numOpaqueColors++;
+                    }
+
+                    // Write the palette index for the pixel to outRows optimistically.
+                    // We might overwrite it later if we decide to encode as gray or
+                    // gray + alpha.  We may also need to overwrite it when we combine
+                    // into a single palette.
+                    *out++ = idx;
+                } else {
+                    for (idx = 0; idx < numAlphaColors; idx++) {
+                        if (alphaColors[idx] == col) {
+                            match = true;
+                            break;
+                        }
+                    }
+
+                    if (!match) {
+                        if (numAlphaColors < 256) {
+                            alphaColors[numAlphaColors] = col;
+                        }
+                        numAlphaColors++;
+                    }
+
+                    // Write the palette index for the pixel to outRows optimistically.
+                    // We might overwrite it later if we decide to encode as gray or
+                    // gray + alpha.
+                    *out++ = idx;
                 }
 
-                // Write the palette index for the pixel to outRows optimistically
-                // We might overwrite it later if we decide to encode as gray or
-                // gray + alpha
-                *out++ = idx;
-                if (!match) {
-                    if (num_colors == 256) {
-                        if (kIsDebug) {
-                            printf("Found 257th color at %d, %d\n", i, j);
-                        }
-                        isPalette = false;
-                    } else {
-                        colors[num_colors++] = col;
+                if (numOpaqueColors + numAlphaColors > 256) {
+                    if (kIsDebug) {
+                        printf("Found 257th color at %d, %d\n", i, j);
                     }
+                    isPalette = false;
                 }
             }
         }
     }
 
+    // If we decide to encode the image using a palette, we will reset these counts
+    // to the appropriate values later.  Initializing them here avoids compiler
+    // complaints about uses of possibly uninitialized variables.
     *paletteEntries = 0;
-    *hasTransparency = !isOpaque;
-    int bpp = isOpaque ? 3 : 4;
-    int paletteSize = w * h + bpp * num_colors;
+    *alphaPaletteEntries = 0;
 
+    *hasTransparency = !isOpaque;
+    int paletteSize = w * h + 3 * numOpaqueColors + 4 * numAlphaColors;
+
+    int bpp = isOpaque ? 3 : 4;
     if (kIsDebug) {
         printf("isGrayscale = %s\n", isGrayscale ? "true" : "false");
         printf("isOpaque = %s\n", isOpaque ? "true" : "false");
@@ -1017,16 +1078,37 @@
     // color type chosen
 
     if (*colorType == PNG_COLOR_TYPE_PALETTE) {
+        // Combine the alphaColors and the opaqueColors into a single palette.
+        // The alphaColors must be at the start of the palette.
+        uint32_t* colors = alphaColors;
+        memcpy(colors + numAlphaColors, opaqueColors, 4 * numOpaqueColors);
+
+        // Fix the indices of the opaque colors in the image.
+        for (j = 0; j < h; j++) {
+            png_bytep row = imageInfo.rows[j];
+            png_bytep out = outRows[j];
+            for (i = 0; i < w; i++) {
+                uint32_t pixel = ((uint32_t*) row)[i];
+                if (pixel >> 24 == 0xFF) {
+                    out[i] += numAlphaColors;
+                }
+            }
+        }
+
         // Create separate RGB and Alpha palettes and set the number of colors
-        *paletteEntries = num_colors;
+        int numColors = numOpaqueColors + numAlphaColors;
+        *paletteEntries = numColors;
+        *alphaPaletteEntries = numAlphaColors;
 
         // Create the RGB and alpha palettes
-        for (int idx = 0; idx < num_colors; idx++) {
+        for (int idx = 0; idx < numColors; idx++) {
             col = colors[idx];
             rgbPalette[idx].red   = (png_byte) ((col >> 24) & 0xff);
             rgbPalette[idx].green = (png_byte) ((col >> 16) & 0xff);
             rgbPalette[idx].blue  = (png_byte) ((col >>  8) & 0xff);
-            alphaPalette[idx]     = (png_byte)  (col        & 0xff);
+            if (idx < numAlphaColors) {
+                alphaPalette[idx] = (png_byte)  (col        & 0xff);
+            }
         }
     } else if (*colorType == PNG_COLOR_TYPE_GRAY || *colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
         // If the image is gray or gray + alpha, compact the pixels into outRows
@@ -1090,10 +1172,10 @@
     png_color rgbPalette[256];
     png_byte alphaPalette[256];
     bool hasTransparency;
-    int paletteEntries;
+    int paletteEntries, alphaPaletteEntries;
 
     analyze_image(imageName, imageInfo, grayscaleTolerance, rgbPalette, alphaPalette,
-                  &paletteEntries, &hasTransparency, &color_type, outRows);
+                  &paletteEntries, &alphaPaletteEntries, &hasTransparency, &color_type, outRows);
 
     if (kIsDebug) {
         switch (color_type) {
@@ -1124,7 +1206,8 @@
     if (color_type == PNG_COLOR_TYPE_PALETTE) {
         png_set_PLTE(write_ptr, write_info, rgbPalette, paletteEntries);
         if (hasTransparency) {
-            png_set_tRNS(write_ptr, write_info, alphaPalette, paletteEntries, (png_color_16p) 0);
+            png_set_tRNS(write_ptr, write_info, alphaPalette, alphaPaletteEntries,
+                    (png_color_16p) 0);
         }
        png_set_filter(write_ptr, 0, PNG_NO_FILTERS);
     } else {
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index a4f4ba9..f74b93a 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -30,6 +30,7 @@
 	compile/PseudolocaleGenerator.cpp \
 	compile/Pseudolocalizer.cpp \
 	compile/XmlIdCollector.cpp \
+	filter/ConfigFilter.cpp \
 	flatten/Archive.cpp \
 	flatten/TableFlattener.cpp \
 	flatten/XmlFlattener.cpp \
@@ -71,6 +72,7 @@
 	compile/PseudolocaleGenerator_test.cpp \
 	compile/Pseudolocalizer_test.cpp \
 	compile/XmlIdCollector_test.cpp \
+	filter/ConfigFilter_test.cpp \
 	flatten/FileExportWriter_test.cpp \
 	flatten/TableFlattener_test.cpp \
 	flatten/XmlFlattener_test.cpp \
diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp
index 0369156..6acf3b0 100644
--- a/tools/aapt2/Locale.cpp
+++ b/tools/aapt2/Locale.cpp
@@ -70,7 +70,7 @@
     return std::all_of(std::begin(str), std::end(str), ::isdigit);
 }
 
-bool LocaleValue::initFromFilterString(const std::string& str) {
+bool LocaleValue::initFromFilterString(const StringPiece& str) {
      // A locale (as specified in the filter) is an underscore separated name such
      // as "en_US", "en_Latn_US", or "en_US_POSIX".
      std::vector<std::string> parts = util::splitAndLowercase(str, '_');
diff --git a/tools/aapt2/Locale.h b/tools/aapt2/Locale.h
index ceec764..b1c80ab 100644
--- a/tools/aapt2/Locale.h
+++ b/tools/aapt2/Locale.h
@@ -17,6 +17,8 @@
 #ifndef AAPT_LOCALE_VALUE_H
 #define AAPT_LOCALE_VALUE_H
 
+#include "util/StringPiece.h"
+
 #include <androidfw/ResourceTypes.h>
 #include <string>
 #include <vector>
@@ -37,7 +39,7 @@
     /**
      * Initialize this LocaleValue from a config string.
      */
-    bool initFromFilterString(const std::string& config);
+    bool initFromFilterString(const StringPiece& config);
 
     /**
      * Initialize this LocaleValue from parts of a vector.
diff --git a/tools/aapt2/filter/ConfigFilter.cpp b/tools/aapt2/filter/ConfigFilter.cpp
new file mode 100644
index 0000000..68a017d
--- /dev/null
+++ b/tools/aapt2/filter/ConfigFilter.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ConfigDescription.h"
+#include "filter/ConfigFilter.h"
+
+#include <androidfw/ResourceTypes.h>
+
+namespace aapt {
+
+void AxisConfigFilter::addConfig(ConfigDescription config) {
+    uint32_t diffMask = ConfigDescription::defaultConfig().diff(config);
+
+    // Ignore the version
+    diffMask &= ~android::ResTable_config::CONFIG_VERSION;
+
+    // Ignore any densities. Those are best handled in --preferred-density
+    if ((diffMask & android::ResTable_config::CONFIG_DENSITY) != 0) {
+        config.density = 0;
+        diffMask &= ~android::ResTable_config::CONFIG_DENSITY;
+    }
+
+    mConfigs.insert(std::make_pair(config, diffMask));
+    mConfigMask |= diffMask;
+}
+
+bool AxisConfigFilter::match(const ConfigDescription& config) const {
+    const uint32_t mask = ConfigDescription::defaultConfig().diff(config);
+    if ((mConfigMask & mask) == 0) {
+        // The two configurations don't have any common axis.
+        return true;
+    }
+
+    uint32_t matchedAxis = 0;
+    for (const auto& entry : mConfigs) {
+        const ConfigDescription& target = entry.first;
+        const uint32_t diffMask = entry.second;
+        uint32_t diff = target.diff(config);
+        if ((diff & diffMask) == 0) {
+            // Mark the axis that was matched.
+            matchedAxis |= diffMask;
+        } else if ((diff & diffMask) == android::ResTable_config::CONFIG_LOCALE) {
+            // If the locales differ, but the languages are the same and
+            // the locale we are matching only has a language specified,
+            // we match.
+            if (config.language[0] &&
+                    memcmp(config.language, target.language, sizeof(config.language)) == 0) {
+                if (config.country[0] == 0) {
+                    matchedAxis |= android::ResTable_config::CONFIG_LOCALE;
+                }
+            }
+        } else if ((diff & diffMask) == android::ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) {
+            // Special case if the smallest screen width doesn't match. We check that the
+            // config being matched has a smaller screen width than the filter specified.
+            if (config.smallestScreenWidthDp != 0 &&
+                    config.smallestScreenWidthDp < target.smallestScreenWidthDp) {
+                matchedAxis |= android::ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE;
+            }
+        }
+    }
+    return matchedAxis == (mConfigMask & mask);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/filter/ConfigFilter.h b/tools/aapt2/filter/ConfigFilter.h
new file mode 100644
index 0000000..36e9c44
--- /dev/null
+++ b/tools/aapt2/filter/ConfigFilter.h
@@ -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.
+ */
+
+#ifndef AAPT_FILTER_CONFIGFILTER_H
+#define AAPT_FILTER_CONFIGFILTER_H
+
+#include "ConfigDescription.h"
+
+#include <set>
+#include <utility>
+
+namespace aapt {
+
+/**
+ * Matches ConfigDescriptions based on some pattern.
+ */
+class IConfigFilter {
+public:
+    virtual ~IConfigFilter() = default;
+
+    /**
+     * Returns true if the filter matches the configuration, false otherwise.
+     */
+    virtual bool match(const ConfigDescription& config) const = 0;
+};
+
+/**
+ * Implements config axis matching. An axis is one component of a configuration, like screen
+ * density or locale. If an axis is specified in the filter, and the axis is specified in
+ * the configuration to match, they must be compatible. Otherwise the configuration to match is
+ * accepted.
+ *
+ * Used when handling "-c" options.
+ */
+class AxisConfigFilter : public IConfigFilter {
+public:
+    void addConfig(ConfigDescription config);
+
+    bool match(const ConfigDescription& config) const override;
+
+private:
+    std::set<std::pair<ConfigDescription, uint32_t>> mConfigs;
+    uint32_t mConfigMask = 0;
+};
+
+} // namespace aapt
+
+#endif /* AAPT_FILTER_CONFIGFILTER_H */
diff --git a/tools/aapt2/filter/ConfigFilter_test.cpp b/tools/aapt2/filter/ConfigFilter_test.cpp
new file mode 100644
index 0000000..f6b4955
--- /dev/null
+++ b/tools/aapt2/filter/ConfigFilter_test.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 "filter/ConfigFilter.h"
+#include "test/Common.h"
+
+#include <gtest/gtest.h>
+
+namespace aapt {
+
+TEST(ConfigFilterTest, EmptyFilterMatchesAnything) {
+    AxisConfigFilter filter;
+
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("320dpi")));
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("fr")));
+}
+
+TEST(ConfigFilterTest, MatchesConfigWithUnrelatedAxis) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("fr"));
+
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("320dpi")));
+}
+
+TEST(ConfigFilterTest, MatchesConfigWithSameValueAxis) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("fr"));
+
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("fr")));
+}
+
+TEST(ConfigFilterTest, MatchesConfigWithSameValueAxisAndOtherUnrelatedAxis) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("fr"));
+
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("fr-320dpi")));
+}
+
+TEST(ConfigFilterTest, MatchesConfigWithOneMatchingAxis) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("fr-rFR"));
+    filter.addConfig(test::parseConfigOrDie("sw360dp"));
+    filter.addConfig(test::parseConfigOrDie("normal"));
+    filter.addConfig(test::parseConfigOrDie("en-rUS"));
+
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("en")));
+}
+
+TEST(ConfigFilterTest, DoesNotMatchConfigWithDifferentValueAxis) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("fr"));
+
+    EXPECT_FALSE(filter.match(test::parseConfigOrDie("de")));
+}
+
+TEST(ConfigFilterTest, DoesNotMatchWhenOneQualifierIsExplicitlyNotMatched) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("fr-rFR"));
+    filter.addConfig(test::parseConfigOrDie("en-rUS"));
+    filter.addConfig(test::parseConfigOrDie("normal"));
+    filter.addConfig(test::parseConfigOrDie("large"));
+    filter.addConfig(test::parseConfigOrDie("xxhdpi"));
+    filter.addConfig(test::parseConfigOrDie("sw320dp"));
+
+    EXPECT_FALSE(filter.match(test::parseConfigOrDie("fr-sw600dp-v13")));
+}
+
+TEST(ConfigFilterTest, MatchesSmallestWidthWhenSmaller) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("sw600dp"));
+
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("fr-sw320dp-v13")));
+}
+
+TEST(ConfigFilterTest, MatchesConfigWithSameLanguageButNoRegionSpecified) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("de-rDE"));
+
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("de")));
+}
+
+TEST(ConfigFilterTest, IgnoresVersion) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("normal-v4"));
+
+    // The configs don't match on any axis besides version, which should be ignored.
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("sw600dp-v13")));
+}
+
+TEST(ConfigFilterTest, MatchesConfigWithRegion) {
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("kok"));
+    filter.addConfig(test::parseConfigOrDie("kok-rIN"));
+    filter.addConfig(test::parseConfigOrDie("kok-v419"));
+
+    EXPECT_TRUE(filter.match(test::parseConfigOrDie("kok-rIN")));
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 3ecb2c4..fd76e88 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -17,8 +17,10 @@
 #include "AppInfo.h"
 #include "Debug.h"
 #include "Flags.h"
+#include "Locale.h"
 #include "NameMangler.h"
 #include "compile/IdAssigner.h"
+#include "filter/ConfigFilter.h"
 #include "flatten/Archive.h"
 #include "flatten/TableFlattener.h"
 #include "flatten/XmlFlattener.h"
@@ -64,7 +66,7 @@
     std::vector<std::string> extensionsToNotCompress;
     Maybe<std::u16string> privateSymbols;
     ManifestFixerOptions manifestFixerOptions;
-
+    IConfigFilter* configFilter = nullptr;
 };
 
 struct LinkContext : public IAaptContext {
@@ -97,8 +99,8 @@
 
 class LinkCommand {
 public:
-    LinkCommand(const LinkOptions& options) :
-            mOptions(options), mContext(), mFinalTable(), mFileCollection(nullptr) {
+    LinkCommand(LinkContext* context, const LinkOptions& options) :
+            mOptions(options), mContext(context), mFinalTable(), mFileCollection(nullptr) {
         std::unique_ptr<io::FileCollection> fileCollection =
                 util::make_unique<io::FileCollection>();
 
@@ -117,14 +119,14 @@
         AssetManagerSymbolTableBuilder builder;
         for (const std::string& path : mOptions.includePaths) {
             if (mOptions.verbose) {
-                mContext.getDiagnostics()->note(DiagMessage(path) << "loading include path");
+                mContext->getDiagnostics()->note(DiagMessage(path) << "loading include path");
             }
 
             std::unique_ptr<android::AssetManager> assetManager =
                     util::make_unique<android::AssetManager>();
             int32_t cookie = 0;
             if (!assetManager->addAssetPath(android::String8(path.data(), path.size()), &cookie)) {
-                mContext.getDiagnostics()->error(
+                mContext->getDiagnostics()->error(
                         DiagMessage(path) << "failed to load include path");
                 return {};
             }
@@ -135,7 +137,7 @@
 
     std::unique_ptr<ResourceTable> loadTable(const Source& source, const void* data, size_t len) {
         std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
-        BinaryResourceParser parser(&mContext, table.get(), source, data, len);
+        BinaryResourceParser parser(mContext, table.get(), source, data, len);
         if (!parser.parse()) {
             return {};
         }
@@ -207,7 +209,7 @@
                            IArchiveWriter* writer) {
         std::unique_ptr<io::IData> data = file->openAsData();
         if (!data) {
-            mContext.getDiagnostics()->error(DiagMessage(file->getSource())
+            mContext->getDiagnostics()->error(DiagMessage(file->getSource())
                                              << "failed to open file");
             return false;
         }
@@ -215,7 +217,7 @@
         std::string errorStr;
         ssize_t offset = getWrappedDataOffset(data->data(), data->size(), &errorStr);
         if (offset < 0) {
-            mContext.getDiagnostics()->error(DiagMessage(file->getSource()) << errorStr);
+            mContext->getDiagnostics()->error(DiagMessage(file->getSource()) << errorStr);
             return false;
         }
 
@@ -228,7 +230,7 @@
             }
         }
 
-        mContext.getDiagnostics()->error(
+        mContext->getDiagnostics()->error(
                 DiagMessage(mOptions.outputPath) << "failed to write file " << outPath);
         return false;
     }
@@ -252,9 +254,9 @@
      */
     bool verifyNoExternalPackages() {
         auto isExtPackageFunc = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
-            return mContext.getCompilationPackage() != pkg->name ||
+            return mContext->getCompilationPackage() != pkg->name ||
                     !pkg->id ||
-                    pkg->id.value() != mContext.getPackageId();
+                    pkg->id.value() != mContext->getPackageId();
         };
 
         bool error = false;
@@ -270,13 +272,13 @@
                             // 'android' package. This is due to legacy reasons.
                             if (valueCast<Id>(configValue.value.get()) &&
                                     package->name == u"android") {
-                                mContext.getDiagnostics()->warn(
+                                mContext->getDiagnostics()->warn(
                                         DiagMessage(configValue.value->getSource())
                                         << "generated id '" << resName
                                         << "' for external package '" << package->name
                                         << "'");
                             } else {
-                                mContext.getDiagnostics()->error(
+                                mContext->getDiagnostics()->error(
                                         DiagMessage(configValue.value->getSource())
                                         << "defined resource '" << resName
                                         << "' for external package '" << package->name
@@ -297,9 +299,9 @@
 
     std::unique_ptr<IArchiveWriter> makeArchiveWriter() {
         if (mOptions.outputToDirectory) {
-            return createDirectoryArchiveWriter(mContext.getDiagnostics(), mOptions.outputPath);
+            return createDirectoryArchiveWriter(mContext->getDiagnostics(), mOptions.outputPath);
         } else {
-            return createZipFileArchiveWriter(mContext.getDiagnostics(), mOptions.outputPath);
+            return createZipFileArchiveWriter(mContext->getDiagnostics(), mOptions.outputPath);
         }
     }
 
@@ -308,7 +310,7 @@
         TableFlattenerOptions options = {};
         options.useExtendedChunks = mOptions.staticLib;
         TableFlattener flattener(&buffer, options);
-        if (!flattener.consume(&mContext, table)) {
+        if (!flattener.consume(mContext, table)) {
             return false;
         }
 
@@ -320,7 +322,7 @@
             }
         }
 
-        mContext.getDiagnostics()->error(
+        mContext->getDiagnostics()->error(
                 DiagMessage() << "failed to write resources.arsc to archive");
         return false;
     }
@@ -332,7 +334,7 @@
         options.keepRawValues = mOptions.staticLib;
         options.maxSdkLevel = maxSdkLevel;
         XmlFlattener flattener(&buffer, options);
-        if (!flattener.consume(&mContext, xmlRes)) {
+        if (!flattener.consume(mContext, xmlRes)) {
             return false;
         }
 
@@ -343,7 +345,7 @@
                 }
             }
         }
-        mContext.getDiagnostics()->error(
+        mContext->getDiagnostics()->error(
                 DiagMessage() << "failed to write " << path << " to archive");
         return false;
     }
@@ -361,13 +363,13 @@
 
         std::ofstream fout(outPath, std::ofstream::binary);
         if (!fout) {
-            mContext.getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
             return false;
         }
 
         JavaClassGenerator generator(table, javaOptions);
         if (!generator.generate(packageNameToGenerate, outPackage, &fout)) {
-            mContext.getDiagnostics()->error(DiagMessage(outPath) << generator.getError());
+            mContext->getDiagnostics()->error(DiagMessage(outPath) << generator.getError());
             return false;
         }
         return true;
@@ -380,24 +382,24 @@
 
         std::string outPath = mOptions.generateJavaClassPath.value();
         file::appendPath(&outPath,
-                         file::packageToPath(util::utf16ToUtf8(mContext.getCompilationPackage())));
+                         file::packageToPath(util::utf16ToUtf8(mContext->getCompilationPackage())));
         file::mkdirs(outPath);
         file::appendPath(&outPath, "Manifest.java");
 
         std::ofstream fout(outPath, std::ofstream::binary);
         if (!fout) {
-            mContext.getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
             return false;
         }
 
         ManifestClassGenerator generator;
-        if (!generator.generate(mContext.getDiagnostics(), mContext.getCompilationPackage(),
+        if (!generator.generate(mContext->getDiagnostics(), mContext->getCompilationPackage(),
                                 manifestXml, &fout)) {
             return false;
         }
 
         if (!fout) {
-            mContext.getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
             return false;
         }
         return true;
@@ -410,13 +412,13 @@
 
         std::ofstream fout(mOptions.generateProguardRulesPath.value(), std::ofstream::binary);
         if (!fout) {
-            mContext.getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
             return false;
         }
 
         proguard::writeKeepSet(&fout, keepSet);
         if (!fout) {
-            mContext.getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
             return false;
         }
         return true;
@@ -425,7 +427,7 @@
     bool mergeStaticLibrary(const std::string& input) {
         // TODO(adamlesinski): Load resources from a static library APK and merge the table into
         // TableMerger.
-        mContext.getDiagnostics()->warn(DiagMessage()
+        mContext->getDiagnostics()->warn(DiagMessage()
                                         << "linking static libraries not supported yet: "
                                         << input);
         return true;
@@ -433,12 +435,12 @@
 
     bool mergeResourceTable(io::IFile* file, bool override) {
         if (mOptions.verbose) {
-            mContext.getDiagnostics()->note(DiagMessage() << "linking " << file->getSource());
+            mContext->getDiagnostics()->note(DiagMessage() << "linking " << file->getSource());
         }
 
         std::unique_ptr<io::IData> data = file->openAsData();
         if (!data) {
-            mContext.getDiagnostics()->error(DiagMessage(file->getSource())
+            mContext->getDiagnostics()->error(DiagMessage(file->getSource())
                                              << "failed to open file");
             return false;
         }
@@ -460,7 +462,7 @@
 
     bool mergeCompiledFile(io::IFile* file, std::unique_ptr<ResourceFile> fileDesc, bool overlay) {
         if (mOptions.verbose) {
-            mContext.getDiagnostics()->note(DiagMessage() << "adding " << file->getSource());
+            mContext->getDiagnostics()->note(DiagMessage() << "adding " << file->getSource());
         }
 
         bool result = false;
@@ -477,12 +479,12 @@
         // Add the exports of this file to the table.
         for (SourcedResourceName& exportedSymbol : fileDesc->exportedSymbols) {
             if (exportedSymbol.name.package.empty()) {
-                exportedSymbol.name.package = mContext.getCompilationPackage().toString();
+                exportedSymbol.name.package = mContext->getCompilationPackage().toString();
             }
 
             ResourceNameRef resName = exportedSymbol.name;
 
-            Maybe<ResourceName> mangledName = mContext.getNameMangler()->mangleName(
+            Maybe<ResourceName> mangledName = mContext->getNameMangler()->mangleName(
                     exportedSymbol.name);
             if (mangledName) {
                 resName = mangledName.value();
@@ -491,7 +493,7 @@
             std::unique_ptr<Id> id = util::make_unique<Id>();
             id->setSource(fileDesc->source.withLine(exportedSymbol.line));
             bool result = mFinalTable.addResourceAllowMangled(resName, {}, std::move(id),
-                                                              mContext.getDiagnostics());
+                                                              mContext->getDiagnostics());
             if (!result) {
                 return false;
             }
@@ -507,7 +509,7 @@
         std::unique_ptr<io::ZipFileCollection> collection = io::ZipFileCollection::create(
                 input, &errorStr);
         if (!collection) {
-            mContext.getDiagnostics()->error(DiagMessage(input) << errorStr);
+            mContext->getDiagnostics()->error(DiagMessage(input) << errorStr);
             return false;
         }
 
@@ -543,12 +545,12 @@
             // Try opening the file and looking for an Export header.
             std::unique_ptr<io::IData> data = file->openAsData();
             if (!data) {
-                mContext.getDiagnostics()->error(DiagMessage(src) << "failed to open");
+                mContext->getDiagnostics()->error(DiagMessage(src) << "failed to open");
                 return false;
             }
 
             std::unique_ptr<ResourceFile> resourceFile = loadFileExportHeader(
-                    src, data->data(), data->size(), mContext.getDiagnostics());
+                    src, data->data(), data->size(), mContext->getDiagnostics());
             if (resourceFile) {
                 return mergeCompiledFile(file, std::move(resourceFile), override);
             }
@@ -564,62 +566,63 @@
     int run(const std::vector<std::string>& inputFiles) {
         // Load the AndroidManifest.xml
         std::unique_ptr<xml::XmlResource> manifestXml = loadXml(mOptions.manifestPath,
-                                                                mContext.getDiagnostics());
+                                                                mContext->getDiagnostics());
         if (!manifestXml) {
             return 1;
         }
 
         if (Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get())) {
-            mContext.mCompilationPackage = maybeAppInfo.value().package;
+            mContext->mCompilationPackage = maybeAppInfo.value().package;
         } else {
-            mContext.getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
+            mContext->getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
                                              << "no package specified in <manifest> tag");
             return 1;
         }
 
-        if (!util::isJavaPackageName(mContext.mCompilationPackage)) {
-            mContext.getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
+        if (!util::isJavaPackageName(mContext->mCompilationPackage)) {
+            mContext->getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
                                              << "invalid package name '"
-                                             << mContext.mCompilationPackage
+                                             << mContext->mCompilationPackage
                                              << "'");
             return 1;
         }
 
-        mContext.mNameMangler = util::make_unique<NameMangler>(
-                NameManglerPolicy{ mContext.mCompilationPackage });
+        mContext->mNameMangler = util::make_unique<NameMangler>(
+                NameManglerPolicy{ mContext->mCompilationPackage });
 
-        if (mContext.mCompilationPackage == u"android") {
-            mContext.mPackageId = 0x01;
+        if (mContext->mCompilationPackage == u"android") {
+            mContext->mPackageId = 0x01;
         } else {
-            mContext.mPackageId = 0x7f;
+            mContext->mPackageId = 0x7f;
         }
 
-        mContext.mSymbols = createSymbolTableFromIncludePaths();
-        if (!mContext.mSymbols) {
+        mContext->mSymbols = createSymbolTableFromIncludePaths();
+        if (!mContext->mSymbols) {
             return 1;
         }
 
         TableMergerOptions tableMergerOptions;
         tableMergerOptions.autoAddOverlay = mOptions.autoAddOverlay;
-        mTableMerger = util::make_unique<TableMerger>(&mContext, &mFinalTable, tableMergerOptions);
+        tableMergerOptions.filter = mOptions.configFilter;
+        mTableMerger = util::make_unique<TableMerger>(mContext, &mFinalTable, tableMergerOptions);
 
         if (mOptions.verbose) {
-            mContext.getDiagnostics()->note(
-                    DiagMessage() << "linking package '" << mContext.mCompilationPackage << "' "
-                                  << "with package ID " << std::hex << (int) mContext.mPackageId);
+            mContext->getDiagnostics()->note(
+                    DiagMessage() << "linking package '" << mContext->mCompilationPackage << "' "
+                                  << "with package ID " << std::hex << (int) mContext->mPackageId);
         }
 
 
         for (const std::string& input : inputFiles) {
             if (!processFile(input, false)) {
-                mContext.getDiagnostics()->error(DiagMessage() << "failed parsing input");
+                mContext->getDiagnostics()->error(DiagMessage() << "failed parsing input");
                 return 1;
             }
         }
 
         for (const std::string& input : mOptions.overlayFiles) {
             if (!processFile(input, true)) {
-                mContext.getDiagnostics()->error(DiagMessage() << "failed parsing overlays");
+                mContext->getDiagnostics()->error(DiagMessage() << "failed parsing overlays");
                 return 1;
             }
         }
@@ -630,8 +633,8 @@
 
         if (!mOptions.staticLib) {
             PrivateAttributeMover mover;
-            if (!mover.consume(&mContext, &mFinalTable)) {
-                mContext.getDiagnostics()->error(
+            if (!mover.consume(mContext, &mFinalTable)) {
+                mContext->getDiagnostics()->error(
                         DiagMessage() << "failed moving private attributes");
                 return 1;
             }
@@ -639,23 +642,23 @@
 
         {
             IdAssigner idAssigner;
-            if (!idAssigner.consume(&mContext, &mFinalTable)) {
-                mContext.getDiagnostics()->error(DiagMessage() << "failed assigning IDs");
+            if (!idAssigner.consume(mContext, &mFinalTable)) {
+                mContext->getDiagnostics()->error(DiagMessage() << "failed assigning IDs");
                 return 1;
             }
         }
 
-        mContext.mNameMangler = util::make_unique<NameMangler>(NameManglerPolicy{
-                mContext.mCompilationPackage, mTableMerger->getMergedPackages() });
-        mContext.mSymbols = JoinedSymbolTableBuilder()
+        mContext->mNameMangler = util::make_unique<NameMangler>(NameManglerPolicy{
+                mContext->mCompilationPackage, mTableMerger->getMergedPackages() });
+        mContext->mSymbols = JoinedSymbolTableBuilder()
                 .addSymbolTable(util::make_unique<SymbolTableWrapper>(&mFinalTable))
-                .addSymbolTable(std::move(mContext.mSymbols))
+                .addSymbolTable(std::move(mContext->mSymbols))
                 .build();
 
         {
             ReferenceLinker linker;
-            if (!linker.consume(&mContext, &mFinalTable)) {
-                mContext.getDiagnostics()->error(DiagMessage() << "failed linking references");
+            if (!linker.consume(mContext, &mFinalTable)) {
+                mContext->getDiagnostics()->error(DiagMessage() << "failed linking references");
                 return 1;
             }
         }
@@ -664,24 +667,24 @@
 
         std::unique_ptr<IArchiveWriter> archiveWriter = makeArchiveWriter();
         if (!archiveWriter) {
-            mContext.getDiagnostics()->error(DiagMessage() << "failed to create archive");
+            mContext->getDiagnostics()->error(DiagMessage() << "failed to create archive");
             return 1;
         }
 
         bool error = false;
         {
             ManifestFixer manifestFixer(mOptions.manifestFixerOptions);
-            if (!manifestFixer.consume(&mContext, manifestXml.get())) {
+            if (!manifestFixer.consume(mContext, manifestXml.get())) {
                 error = true;
             }
 
             // AndroidManifest.xml has no resource name, but the CallSite is built from the name
             // (aka, which package the AndroidManifest.xml is coming from).
             // So we give it a package name so it can see local resources.
-            manifestXml->file.name.package = mContext.getCompilationPackage().toString();
+            manifestXml->file.name.package = mContext->getCompilationPackage().toString();
 
             XmlReferenceLinker manifestLinker;
-            if (manifestLinker.consume(&mContext, manifestXml.get())) {
+            if (manifestLinker.consume(mContext, manifestXml.get())) {
                 if (!proguard::collectProguardRulesForManifest(Source(mOptions.manifestPath),
                                                                manifestXml.get(),
                                                                &proguardKeepSet)) {
@@ -704,7 +707,7 @@
         }
 
         if (error) {
-            mContext.getDiagnostics()->error(DiagMessage() << "failed processing manifest");
+            mContext->getDiagnostics()->error(DiagMessage() << "failed processing manifest");
             return 1;
         }
 
@@ -718,13 +721,13 @@
                     (util::stringEndsWith<char>(path, ".xml.flat") ||
                     util::stringEndsWith<char>(path, ".xml"))) {
                 if (mOptions.verbose) {
-                    mContext.getDiagnostics()->note(DiagMessage() << "linking " << path);
+                    mContext->getDiagnostics()->note(DiagMessage() << "linking " << path);
                 }
 
                 io::IFile* file = fileToMerge.file;
                 std::unique_ptr<io::IData> data = file->openAsData();
                 if (!data) {
-                    mContext.getDiagnostics()->error(DiagMessage(file->getSource())
+                    mContext->getDiagnostics()->error(DiagMessage(file->getSource())
                                                      << "failed to open file");
                     return 1;
                 }
@@ -733,9 +736,9 @@
                 if (util::stringEndsWith<char>(path, ".flat")) {
                     xmlRes = loadBinaryXmlSkipFileExport(file->getSource(),
                                                          data->data(), data->size(),
-                                                         mContext.getDiagnostics());
+                                                         mContext->getDiagnostics());
                 } else {
-                    xmlRes = xml::inflate(data->data(), data->size(), mContext.getDiagnostics(),
+                    xmlRes = xml::inflate(data->data(), data->size(), mContext->getDiagnostics(),
                                           file->getSource());
                 }
 
@@ -751,7 +754,7 @@
                 };
 
                 XmlReferenceLinker xmlLinker;
-                if (xmlLinker.consume(&mContext, xmlRes.get())) {
+                if (xmlLinker.consume(mContext, xmlRes.get())) {
                     if (!proguard::collectProguardRules(xmlRes->file.source, xmlRes.get(),
                                                         &proguardKeepSet)) {
                         error = true;
@@ -778,14 +781,14 @@
                                 xmlRes->file.config.sdkVersion = sdkLevel;
 
                                 std::string genResourcePath = ResourceUtils::buildResourceFileName(
-                                        xmlRes->file, mContext.getNameMangler());
+                                        xmlRes->file, mContext->getNameMangler());
 
                                 bool added = mFinalTable.addFileReference(
                                         xmlRes->file.name,
                                         xmlRes->file.config,
                                         xmlRes->file.source,
                                         util::utf8ToUtf16(genResourcePath),
-                                        mContext.getDiagnostics());
+                                        mContext->getDiagnostics());
                                 if (!added) {
                                     error = true;
                                     continue;
@@ -804,7 +807,7 @@
                 }
             } else {
                 if (mOptions.verbose) {
-                    mContext.getDiagnostics()->note(DiagMessage() << "copying " << path);
+                    mContext->getDiagnostics()->note(DiagMessage() << "copying " << path);
                 }
 
                 if (!copyFileToArchive(fileToMerge.file, fileToMerge.dstPath,
@@ -815,20 +818,20 @@
         }
 
         if (error) {
-            mContext.getDiagnostics()->error(DiagMessage() << "failed linking file resources");
+            mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources");
             return 1;
         }
 
         if (!mOptions.noAutoVersion) {
             AutoVersioner versioner;
-            if (!versioner.consume(&mContext, &mFinalTable)) {
-                mContext.getDiagnostics()->error(DiagMessage() << "failed versioning styles");
+            if (!versioner.consume(mContext, &mFinalTable)) {
+                mContext->getDiagnostics()->error(DiagMessage() << "failed versioning styles");
                 return 1;
             }
         }
 
         if (!flattenTable(&mFinalTable, archiveWriter.get())) {
-            mContext.getDiagnostics()->error(DiagMessage() << "failed to write resources.arsc");
+            mContext->getDiagnostics()->error(DiagMessage() << "failed to write resources.arsc");
             return 1;
         }
 
@@ -840,8 +843,8 @@
                 options.useFinal = false;
             }
 
-            const StringPiece16 actualPackage = mContext.getCompilationPackage();
-            StringPiece16 outputPackage = mContext.getCompilationPackage();
+            const StringPiece16 actualPackage = mContext->getCompilationPackage();
+            StringPiece16 outputPackage = mContext->getCompilationPackage();
             if (mOptions.customJavaPackage) {
                 // Override the output java package to the custom one.
                 outputPackage = mOptions.customJavaPackage.value();
@@ -852,7 +855,7 @@
                 // to the original package, and private and public symbols to the private package.
 
                 options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
-                if (!writeJavaFile(&mFinalTable, mContext.getCompilationPackage(),
+                if (!writeJavaFile(&mFinalTable, mContext->getCompilationPackage(),
                                    outputPackage, options)) {
                     return 1;
                 }
@@ -886,7 +889,7 @@
 
 private:
     LinkOptions mOptions;
-    LinkContext mContext;
+    LinkContext* mContext;
     ResourceTable mFinalTable;
 
     ResourceTable mLocalFileTable;
@@ -907,6 +910,7 @@
     Maybe<std::string> versionCode, versionName;
     Maybe<std::string> customJavaPackage;
     std::vector<std::string> extraJavaPackages;
+    Maybe<std::string> configs;
     bool legacyXFlag = false;
     bool requireLocalization = false;
     Flags flags = Flags()
@@ -928,6 +932,8 @@
                             &legacyXFlag)
             .optionalSwitch("-z", "Require localization of strings marked 'suggested'",
                             &requireLocalization)
+            .optionalFlag("-c", "Comma separated list of configurations to include. The default\n"
+                                "is all configurations", &configs)
             .optionalSwitch("--output-to-dir", "Outputs the APK contents to a directory specified "
                             "by -o",
                             &options.outputToDirectory)
@@ -967,6 +973,8 @@
         return 1;
     }
 
+    LinkContext context;
+
     if (privateSymbolsPackage) {
         options.privateSymbols = util::utf8ToUtf16(privateSymbolsPackage.value());
     }
@@ -1011,7 +1019,31 @@
         }
     }
 
-    LinkCommand cmd(options);
+    AxisConfigFilter filter;
+    if (configs) {
+        for (const StringPiece& configStr : util::tokenize<char>(configs.value(), ',')) {
+            ConfigDescription config;
+            LocaleValue lv;
+            if (lv.initFromFilterString(configStr)) {
+                lv.writeTo(&config);
+            } else if (!ConfigDescription::parse(configStr, &config)) {
+                context.getDiagnostics()->error(
+                        DiagMessage() << "invalid config '" << configStr << "' for -c option");
+                return 1;
+            }
+
+            if (config.density != 0) {
+                context.getDiagnostics()->warn(
+                        DiagMessage() << "ignoring density '" << config << "' for -c option");
+            } else {
+                filter.addConfig(config);
+            }
+        }
+
+        options.configFilter = &filter;
+    }
+
+    LinkCommand cmd(&context, options);
     return cmd.run(flags.getArgs());
 }
 
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 27a23bd..e01a004 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -100,7 +100,7 @@
                 return false;
             }
 
-            mFilesToMerge[ResourceKeyRef{ name, config }] = FileToMerge{
+            mFilesToMerge[ResourceKeyRef(name, config)] = FileToMerge{
                     f, oldFile->getSource(), util::utf16ToUtf8(*newFile->path) };
             return true;
         };
@@ -201,6 +201,9 @@
                 auto iter = std::lower_bound(dstEntry->values.begin(), dstEntry->values.end(),
                                              srcValue.config, cmp::lessThanConfig);
 
+                const bool stripConfig = mOptions.filter ?
+                        !mOptions.filter->match(srcValue.config) : false;
+
                 if (iter != dstEntry->values.end() && iter->config == srcValue.config) {
                     const int collisionResult = ResourceTable::resolveValueCollision(
                             iter->value.get(), srcValue.value.get());
@@ -224,11 +227,15 @@
                         continue;
                     }
 
-                } else {
+                } else if (!stripConfig){
                     // Insert a place holder value. We will fill it in below.
                     iter = dstEntry->values.insert(iter, ResourceConfigValue{ srcValue.config });
                 }
 
+                if (stripConfig) {
+                    continue;
+                }
+
                 if (FileReference* f = valueCast<FileReference>(srcValue.value.get())) {
                     std::unique_ptr<FileReference> newFileRef;
                     if (manglePackage) {
@@ -287,7 +294,7 @@
 
     auto callback = [&](const ResourceNameRef& name, const ConfigDescription& config,
                        FileReference* newFile, FileReference* oldFile) -> bool {
-        mFilesToMerge[ResourceKeyRef{ name, config }] = FileToMerge{
+        mFilesToMerge[ResourceKeyRef(name, config)] = FileToMerge{
                 file, oldFile->getSource(), util::utf16ToUtf8(*newFile->path) };
         return true;
     };
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index e1be5d5..4539679 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -20,6 +20,7 @@
 #include "Resource.h"
 #include "ResourceTable.h"
 #include "ResourceValues.h"
+#include "filter/ConfigFilter.h"
 #include "io/File.h"
 #include "process/IResourceTableConsumer.h"
 #include "util/Util.h"
@@ -51,6 +52,11 @@
      * If true, resources in overlays can be added without previously having existed.
      */
     bool autoAddOverlay = false;
+
+    /**
+     * A filter that removes resources whose configurations don't match.
+     */
+    IConfigFilter* filter = nullptr;
 };
 
 /**
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index fa4afd3..45c8c98 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "filter/ConfigFilter.h"
 #include "io/FileSystem.h"
 #include "link/TableMerger.h"
 #include "test/Builders.h"
@@ -243,4 +244,36 @@
     ASSERT_FALSE(merger.mergeOverlay({}, tableB.get()));
 }
 
+TEST_F(TableMergerTest, MergeAndStripResourcesNotMatchingFilter) {
+    ResourceTable finalTable;
+    TableMergerOptions options;
+    options.autoAddOverlay = false;
+
+    AxisConfigFilter filter;
+    filter.addConfig(test::parseConfigOrDie("en"));
+    options.filter = &filter;
+
+    test::TestFile fileA("res/layout-en/main.xml"), fileB("res/layout-fr-rFR/main.xml");
+    const ResourceName name = test::parseNameOrDie(u"@com.app.a:layout/main");
+    const ConfigDescription configEn = test::parseConfigOrDie("en");
+    const ConfigDescription configFr = test::parseConfigOrDie("fr-rFR");
+
+    TableMerger merger(mContext.get(), &finalTable, options);
+    ASSERT_TRUE(merger.mergeFile(ResourceFile{ name, configEn }, &fileA));
+    ASSERT_TRUE(merger.mergeFile(ResourceFile{ name, configFr }, &fileB));
+
+    EXPECT_NE(nullptr, test::getValueForConfig<FileReference>(&finalTable,
+                                                              u"@com.app.a:layout/main",
+                                                              configEn));
+    EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(&finalTable,
+                                                              u"@com.app.a:layout/main",
+                                                              configFr));
+
+    EXPECT_NE(merger.getFilesToMerge().end(),
+              merger.getFilesToMerge().find(ResourceKeyRef(name, configEn)));
+
+    EXPECT_EQ(merger.getFilesToMerge().end(),
+              merger.getFilesToMerge().find(ResourceKeyRef(name, configFr)));
+}
+
 } // namespace aapt
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 93a11b9..579a46e 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -84,6 +84,11 @@
                         util::make_unique<FileReference>(mTable->stringPool.makeRef(path)));
     }
 
+    ResourceTableBuilder& addFileReference(const StringPiece16& name, const StringPiece16& path,
+                                           const ConfigDescription& config) {
+        return addValue(name, {}, config,
+                        util::make_unique<FileReference>(mTable->stringPool.makeRef(path)));
+    }
 
     ResourceTableBuilder& addValue(const StringPiece16& name,
                                    std::unique_ptr<Value> value) {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 38eb5ee..2560c31 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -557,4 +557,8 @@
     @Override
     public void requestAppKeyboardShortcuts(IResultReceiver receiver) throws RemoteException {
     }
+
+    @Override
+    public void getStableInsets(Rect outInsets) throws RemoteException {
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index a833ebe..4e4fcd0 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -380,23 +380,17 @@
             config.orientation = Configuration.ORIENTATION_UNDEFINED;
         }
 
-        try {
-            ScreenRound roundness = hardwareConfig.getScreenRoundness();
-            if (roundness != null) {
-                switch (roundness) {
-                    case ROUND:
-                        config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_YES;
-                        break;
-                    case NOTROUND:
-                        config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_NO;
-                }
-            } else {
-                config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_UNDEFINED;
+        ScreenRound roundness = hardwareConfig.getScreenRoundness();
+        if (roundness != null) {
+            switch (roundness) {
+                case ROUND:
+                    config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_YES;
+                    break;
+                case NOTROUND:
+                    config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_NO;
             }
-        } catch (NoSuchMethodError ignored) {
-            // getScreenRoundness was added in later stages of API 15. So, it's not present on some
-            // preview releases of API 15.
-            // TODO: Remove the try catch around Oct 2015.
+        } else {
+            config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_UNDEFINED;
         }
         String locale = getParams().getLocale();
         if (locale != null && !locale.isEmpty()) config.locale = new Locale(locale);
diff --git a/wifi/java/android/net/wifi/AnqpInformationElement.java b/wifi/java/android/net/wifi/AnqpInformationElement.java
new file mode 100644
index 0000000..47b7129
--- /dev/null
+++ b/wifi/java/android/net/wifi/AnqpInformationElement.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.wifi;
+
+/**
+ * This object contains the payload of an ANQP element.
+ * Vendor id is the vendor ID for the element, or 0 if it is an 802.11(u) element.
+ * Hotspot 2.0 uses the WFA Vendor ID which is 0x506f9a
+ * The payload contains the bytes of the payload, starting after the length octet(s).
+ * @hide
+ */
+public class AnqpInformationElement {
+    public static final int HOTSPOT20_VENDOR_ID = 0x506f9a;
+
+    public static final int ANQP_QUERY_LIST = 256;
+    public static final int ANQP_CAPABILITY_LIST = 257;
+    public static final int ANQP_VENUE_NAME = 258;
+    public static final int ANQP_EMERGENCY_NUMBER = 259;
+    public static final int ANQP_NWK_AUTH_TYPE = 260;
+    public static final int ANQP_ROAMING_CONSORTIUM = 261;
+    public static final int ANQP_IP_ADDR_AVAILABILITY = 262;
+    public static final int ANQP_NAI_REALM = 263;
+    public static final int ANQP_3GPP_NETWORK = 264;
+    public static final int ANQP_GEO_LOC = 265;
+    public static final int ANQP_CIVIC_LOC = 266;
+    public static final int ANQP_LOC_URI = 267;
+    public static final int ANQP_DOM_NAME = 268;
+    public static final int ANQP_EMERGENCY_ALERT = 269;
+    public static final int ANQP_TDLS_CAP = 270;
+    public static final int ANQP_EMERGENCY_NAI = 271;
+    public static final int ANQP_NEIGHBOR_REPORT = 272;
+    public static final int ANQP_VENDOR_SPEC = 56797;
+
+    public static final int HS_QUERY_LIST = 1;
+    public static final int HS_CAPABILITY_LIST = 2;
+    public static final int HS_FRIENDLY_NAME = 3;
+    public static final int HS_WAN_METRICS = 4;
+    public static final int HS_CONN_CAPABILITY = 5;
+    public static final int HS_NAI_HOME_REALM_QUERY = 6;
+    public static final int HS_OPERATING_CLASS = 7;
+    public static final int HS_OSU_PROVIDERS = 8;
+    public static final int HS_ICON_REQUEST = 10;
+    public static final int HS_ICON_FILE = 11;
+
+    private final int mVendorId;
+    private final int mElementId;
+    private final byte[] mPayload;
+
+    public AnqpInformationElement(int vendorId, int elementId, byte[] payload) {
+        mVendorId = vendorId;
+        mElementId = elementId;
+        mPayload = payload;
+    }
+
+    public int getVendorId() {
+        return mVendorId;
+    }
+
+    public int getElementId() {
+        return mElementId;
+    }
+
+    public byte[] getPayload() {
+        return mPayload;
+    }
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index bad4e9c..1c7a308 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -20,7 +20,7 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.ScanSettings;
 import android.net.wifi.ScanResult;
-import android.net.wifi.ScanInfo;
+import android.net.wifi.PasspointManagementObjectDefinition;
 import android.net.wifi.WifiConnectionStatistics;
 import android.net.wifi.WifiActivityEnergyInfo;
 import android.net.Network;
@@ -50,6 +50,17 @@
 
     int addOrUpdateNetwork(in WifiConfiguration config);
 
+    int addPasspointManagementObject(String mo);
+
+    int modifyPasspointManagementObject(String fqdn,
+                                        in List<PasspointManagementObjectDefinition> mos);
+
+    void queryPasspointIcon(long bssid, String fileName);
+
+    int matchProviderWithCurrentNetwork(String fqdn);
+
+    void deauthenticateNetwork(long holdoff, boolean ess);
+
     boolean removeNetwork(int netId);
 
     boolean enableNetwork(int netId, boolean disableOthers);
@@ -64,10 +75,6 @@
 
     void disconnect();
 
-    List<ScanInfo> getScanInfos(String callingPackage);
-
-    void setOsuSelection(int osuID);
-
     void reconnect();
 
     void reassociate();
diff --git a/wifi/java/android/net/wifi/ScanInfo.aidl b/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.aidl
similarity index 84%
rename from wifi/java/android/net/wifi/ScanInfo.aidl
rename to wifi/java/android/net/wifi/PasspointManagementObjectDefinition.aidl
index 18ae508..eb7cc39 100644
--- a/wifi/java/android/net/wifi/ScanInfo.aidl
+++ b/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.aidl
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2015, The Android Open Source Project
+ * Copyright (c) 2008, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,4 +16,4 @@
 
 package android.net.wifi;
 
-parcelable ScanInfo;
+parcelable PasspointManagementObjectDefinition;
diff --git a/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java b/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java
new file mode 100644
index 0000000..611ed15
--- /dev/null
+++ b/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.wifi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This object describes a partial tree structure in the Hotspot 2.0 release 2 management object.
+ * The object is used during subscription remediation to modify parts of an existing PPS MO
+ * tree (Hotspot 2.0 specification section 9.1).
+ * @hide
+ */
+public class PasspointManagementObjectDefinition implements Parcelable {
+    private final String mBaseUri;
+    private final String mUrn;
+    private final String mMoTree;
+
+    public PasspointManagementObjectDefinition(String baseUri, String urn, String moTree) {
+        mBaseUri = baseUri;
+        mUrn = urn;
+        mMoTree = moTree;
+    }
+
+    public String getmBaseUri() {
+        return mBaseUri;
+    }
+
+    public String getmUrn() {
+        return mUrn;
+    }
+
+    public String getmMoTree() {
+        return mMoTree;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mBaseUri);
+        dest.writeString(mUrn);
+        dest.writeString(mMoTree);
+    }
+
+    /**
+     * Implement the Parcelable interface {@hide}
+     */
+    public static final Creator<PasspointManagementObjectDefinition> CREATOR =
+            new Creator<PasspointManagementObjectDefinition>() {
+                public PasspointManagementObjectDefinition createFromParcel(Parcel in) {
+                    return new PasspointManagementObjectDefinition(
+                            in.readString(),    /* base URI */
+                            in.readString(),    /* URN */
+                            in.readString()     /* Tree XML */
+                    );
+                }
+
+                public PasspointManagementObjectDefinition[] newArray(int size) {
+                    return new PasspointManagementObjectDefinition[size];
+                }
+            };
+}
+
diff --git a/wifi/java/android/net/wifi/ScanInfo.java b/wifi/java/android/net/wifi/ScanInfo.java
deleted file mode 100644
index 39186fa..0000000
--- a/wifi/java/android/net/wifi/ScanInfo.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package android.net.wifi;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class ScanInfo implements Parcelable {
-    private final ScanResult mScanResult;
-
-    private final long mBSSID;          // The BSSID of the best AP with an SSID matching the OSU
-    private final int mRSSI;            // RSSI of the AP with BSSID
-    private final String mSSID;         // The SSID to connect to for an OSU connection.
-    private final String mName;
-    private final String mServiceDescription;
-    private final String mIconType;
-    private final byte[] mIconData;
-    private final int mOSUIdentity;
-
-    public ScanInfo(ScanResult scanResult) {
-        mScanResult = scanResult;
-
-        mBSSID = -1;
-        mRSSI = -1;
-        mSSID = null;
-        mName = null;
-        mServiceDescription = null;
-        mIconType = null;
-        mIconData = null;
-        mOSUIdentity = -1;
-    }
-
-    public ScanInfo(long BSSID, int rssi, String SSID, String name, String serviceDescription,
-                    String iconType, byte[] iconData, int OSUIdentity) {
-        mBSSID = BSSID;
-        mRSSI = rssi;
-        mSSID = SSID;
-        mName = name;
-        mServiceDescription = serviceDescription;
-        mIconType = iconType;
-        mIconData = iconData;
-        mOSUIdentity = OSUIdentity;
-
-        mScanResult = null;
-    }
-
-    /**
-     * Get the scan result of this ScanInfo.
-     * @return The ScanResult, if this ScanInfo contains a one. If the ScanInfo contains
-     * OSU information getScanResult will return null.
-     */
-    public ScanResult getScanResult() {
-        return mScanResult;
-    }
-
-    /**
-     * OSU only: The BSSID of the AP who advertises the OSU SSID. This value is not guaranteed to
-     * be correct; In the somewhat unlikely case that multiple APs advertise OSU SSIDs that matches
-     * an OSU information element returned through ANQP and one of those is not related to an OSU
-     * there is a (slight) risk that the BSSID is for a "spoof" OSU.
-     * The matching algorithm that produces the ScanInfo objects makes a best effort to get the
-     * matching right though and since it is (a) fair to assume that the OSU SSID resides on the
-     * same AP as the one advertising the OSU information, and (b) BSSIDs for multi-SSID APs are
-     * typically adjacent to each other, matching will prefer the BSSID closest to the advertising
-     * APs BSSID if multiple SSIDs match.
-     * @return The BSSID.
-     */
-    public long getBssid() {
-        return mBSSID;
-    }
-
-    /**
-     * OSU only.
-     * @return The signal level of the AP associated with the BSSID from getBSSID.
-     */
-    public int getRssi() {
-        return mRSSI;
-    }
-
-    /**
-     * OSU only.
-     * @return The SSID of the AP to which to associate to establish an OSU connection.
-     */
-    public String getSsid() {
-        return mSSID;
-    }
-
-    /**
-     * OSU only.
-     * @return The name of the Service Provider of the OSU.
-     */
-    public String getName() {
-        return mName;
-    }
-
-    /**
-     * OSU only.
-     * @return The service description of the OSU.
-     */
-    public String getServiceDescription() {
-        return mServiceDescription;
-    }
-
-    /**
-     * OSU only.
-     * Get the type of icon that icon data represents, e.g. JPG, PNG etc. This field is formatted
-     * using standard MIME encodings per RFC-4288 and IANA MIME media types.
-     * @return The icon type in icon data.
-     */
-    public String getIconType() {
-        return mIconType;
-    }
-
-    /**
-     * OSU only.
-     * @return The binary data of the icon.
-     */
-    public byte[] getIconData() {
-        return mIconData;
-    }
-
-    /**
-     * OSU only.
-     * @return a unique identity for the OSU. This value is generated by the framework and should
-     * be used to uniquely identify a specific OSU. Please note that values may be reused after
-     * a very long time-span (in any normal scenario, likely years) and implementations should make
-     * sure to not rely on any long term persisted values.
-     */
-    public int getOsuIdentity() {
-        return mOSUIdentity;
-    }
-
-    private static final int ScanResultMarker = 0;
-    private static final int OSUMarker = 1;
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<ScanInfo> CREATOR =
-            new Creator<ScanInfo>() {
-                @Override
-                public ScanInfo createFromParcel(Parcel source) {
-                    int marker = source.readInt();
-                    if (marker == ScanResultMarker) {
-                        return new ScanInfo(ScanResult.CREATOR.createFromParcel(source));
-                    }
-                    else if (marker == OSUMarker) {
-                        return new ScanInfo(
-                                source.readLong(),
-                                source.readInt(),
-                                source.readString(),
-                                source.readString(),
-                                source.readString(),
-                                source.readString(),
-                                source.createByteArray(),
-                                source.readInt()
-                                );
-                    }
-                    else {
-                        throw new RuntimeException("Bad ScanInfo data");
-                    }
-                }
-
-                @Override
-                public ScanInfo[] newArray(int size) {
-                    return new ScanInfo[0];
-                }
-            };
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        if (mScanResult != null) {
-            dest.writeInt(ScanResultMarker);
-            mScanResult.writeToParcel(dest, flags);
-            return;
-        }
-
-        dest.writeInt(OSUMarker);
-        dest.writeLong(mBSSID);
-        dest.writeInt(mRSSI);
-        dest.writeString(mSSID);
-        dest.writeString(mName);
-        dest.writeString(mServiceDescription);
-        dest.writeString(mIconType);
-        dest.writeByteArray(mIconData);
-        dest.writeInt(mOSUIdentity);
-    }
-}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 1f05339..4a86c59 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -43,6 +43,19 @@
      * The address of the access point.
      */
     public String BSSID;
+
+    /**
+     * The HESSID from the beacon.
+     * @hide
+     */
+    public long hessid;
+
+    /**
+     * The ANQP Domain ID from the Hotspot 2.0 Indication element, if present.
+     * @hide
+     */
+    public int anqpDomainId;
+
     /**
      * Describes the authentication, key management, and encryption schemes
      * supported by the access point.
@@ -341,14 +354,27 @@
     /** information elements found in the beacon
      * @hide
      */
-    public InformationElement informationElements[];
+    public InformationElement[] informationElements;
+
+    /** ANQP response elements.
+     * @hide
+     */
+    public AnqpInformationElement[] anqpElements;
 
     /** {@hide} */
-    public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
-            long tsf) {
+    public ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId,
+            byte[] osuProviders, String caps, int level, int frequency, long tsf) {
         this.wifiSsid = wifiSsid;
         this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
         this.BSSID = BSSID;
+        this.hessid = hessid;
+        this.anqpDomainId = anqpDomainId;
+        if (osuProviders != null) {
+            this.anqpElements = new AnqpInformationElement[1];
+            this.anqpElements[0] =
+                    new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID,
+                            AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders);
+        }
         this.capabilities = caps;
         this.level = level;
         this.frequency = frequency;
@@ -380,11 +406,14 @@
     }
 
     /** {@hide} */
-    public ScanResult(String Ssid, String BSSID, String caps, int level, int frequency,
+    public ScanResult(String Ssid, String BSSID, long hessid, int anqpDomainId, String caps,
+            int level, int frequency,
             long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1,
             boolean is80211McRTTResponder) {
         this.SSID = Ssid;
         this.BSSID = BSSID;
+        this.hessid = hessid;
+        this.anqpDomainId = anqpDomainId;
         this.capabilities = caps;
         this.level = level;
         this.frequency = frequency;
@@ -402,11 +431,12 @@
     }
 
     /** {@hide} */
-    public ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, String caps, int level,
+    public ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, long hessid, int anqpDomainId,
+                  String caps, int level,
                   int frequency, long tsf, int distCm, int distSdCm, int channelWidth,
                   int centerFreq0, int centerFreq1, boolean is80211McRTTResponder) {
-        this(Ssid, BSSID, caps,level, frequency, tsf, distCm, distSdCm, channelWidth, centerFreq0,
-                centerFreq1, is80211McRTTResponder);
+        this(Ssid, BSSID, hessid, anqpDomainId, caps, level, frequency, tsf, distCm,
+                distSdCm, channelWidth, centerFreq0, centerFreq1, is80211McRTTResponder);
         this.wifiSsid = wifiSsid;
     }
 
@@ -416,6 +446,10 @@
             wifiSsid = source.wifiSsid;
             SSID = source.SSID;
             BSSID = source.BSSID;
+            hessid = source.hessid;
+            anqpDomainId = source.anqpDomainId;
+            informationElements = source.informationElements;
+            anqpElements = source.anqpElements;
             capabilities = source.capabilities;
             level = source.level;
             frequency = source.frequency;
@@ -496,6 +530,8 @@
         }
         dest.writeString(SSID);
         dest.writeString(BSSID);
+        dest.writeLong(hessid);
+        dest.writeInt(anqpDomainId);
         dest.writeString(capabilities);
         dest.writeInt(level);
         dest.writeInt(frequency);
@@ -532,6 +568,18 @@
             for (int i = 0; i < anqpLines.size(); i++) {
                 dest.writeString(anqpLines.get(i));
             }
+        }
+        else {
+            dest.writeInt(0);
+        }
+        if (anqpElements != null) {
+            dest.writeInt(anqpElements.length);
+            for (AnqpInformationElement element : anqpElements) {
+                dest.writeInt(element.getVendorId());
+                dest.writeInt(element.getElementId());
+                dest.writeInt(element.getPayload().length);
+                dest.writeByteArray(element.getPayload());
+            }
         } else {
             dest.writeInt(0);
         }
@@ -546,19 +594,22 @@
                     wifiSsid = WifiSsid.CREATOR.createFromParcel(in);
                 }
                 ScanResult sr = new ScanResult(
-                    wifiSsid,
-                    in.readString(),                    /* SSID  */
-                    in.readString(),                    /* BSSID */
-                    in.readString(),                    /* capabilities */
-                    in.readInt(),                       /* level */
-                    in.readInt(),                       /* frequency */
-                    in.readLong(),                      /* timestamp */
-                    in.readInt(),                       /* distanceCm */
-                    in.readInt(),                       /* distanceSdCm */
-                    in.readInt(),                       /* channelWidth */
-                    in.readInt(),                       /* centerFreq0 */
-                    in.readInt(),                       /* centerFreq1 */
-                    false                               /* rtt responder, fixed with flags below */
+                        wifiSsid,
+                        in.readString(),                    /* SSID  */
+                        in.readString(),                    /* BSSID */
+                        in.readLong(),                      /* HESSID */
+                        in.readInt(),                       /* ANQP Domain ID */
+                        in.readString(),                    /* capabilities */
+                        in.readInt(),                       /* level */
+                        in.readInt(),                       /* frequency */
+                        in.readLong(),                      /* timestamp */
+                        in.readInt(),                       /* distanceCm */
+                        in.readInt(),                       /* distanceSdCm */
+                        in.readInt(),                       /* channelWidth */
+                        in.readInt(),                       /* centerFreq0 */
+                        in.readInt(),                       /* centerFreq1 */
+                        false                               /* rtt responder,
+                                                               fixed with flags below */
                 );
 
                 sr.seen = in.readLong();
@@ -590,6 +641,19 @@
                         sr.anqpLines.add(in.readString());
                     }
                 }
+                n = in.readInt();
+                if (n != 0) {
+                    sr.anqpElements = new AnqpInformationElement[n];
+                    for (int i = 0; i < n; i++) {
+                        int vendorId = in.readInt();
+                        int elementId = in.readInt();
+                        int len = in.readInt();
+                        byte[] payload = new byte[len];
+                        in.readByteArray(payload);
+                        sr.anqpElements[i] =
+                                new AnqpInformationElement(vendorId, elementId, payload);
+                    }
+                }
                 return sr;
             }
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 4c22460..a9132a5 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -58,6 +58,9 @@
     /** {@hide} */
     public static final int INVALID_NETWORK_ID = -1;
 
+    /** {@hide} */
+    private String mPasspointManagementObjectTree;
+
     /**
      * Recognized key management schemes.
      */
@@ -80,11 +83,16 @@
           */
         @SystemApi
         public static final int WPA2_PSK = 4;
+        /**
+         * Hotspot 2.0 r2 OSEN:
+         * @hide
+         */
+        public static final int OSEN = 5;
 
         public static final String varName = "key_mgmt";
 
         public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X",
-                "WPA2_PSK" };
+                "WPA2_PSK", "OSEN" };
     }
 
     /**
@@ -97,10 +105,14 @@
         public static final int WPA = 0;
         /** WPA2/IEEE 802.11i */
         public static final int RSN = 1;
+        /** HS2.0 r2 OSEN
+         * @hide
+         */
+        public static final int OSEN = 2;
 
         public static final String varName = "proto";
 
-        public static final String[] strings = { "WPA", "RSN" };
+        public static final String[] strings = { "WPA", "RSN", "OSEN" };
     }
 
     /**
@@ -159,10 +171,15 @@
         public static final int TKIP = 2;
         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
         public static final int CCMP = 3;
+        /** Hotspot 2.0 r2 OSEN
+         * @hide
+         */
+        public static final int GTK_NOT_USED = 4;
 
         public static final String varName = "group";
 
-        public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" };
+        public static final String[] strings =
+                { "WEP40", "WEP104", "TKIP", "CCMP", "GTK_NOT_USED" };
     }
 
     /** Possible status of a network configuration. */
@@ -1735,6 +1752,16 @@
         return shared || (UserHandle.getUserId(creatorUid) == userId);
     }
 
+    /** @hide */
+    public void setPasspointManagementObjectTree(String passpointManagementObjectTree) {
+        mPasspointManagementObjectTree = passpointManagementObjectTree;
+    }
+
+    /** @hide */
+    public String getMoTree() {
+        return mPasspointManagementObjectTree;
+    }
+
     /** copy constructor {@hide} */
     public WifiConfiguration(WifiConfiguration source) {
         if (source != null) {
@@ -1886,6 +1913,7 @@
         dest.writeInt(numNoInternetAccessReports);
         dest.writeInt(noInternetAccessExpected ? 1 : 0);
         dest.writeInt(shared ? 1 : 0);
+        dest.writeString(mPasspointManagementObjectTree);
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -1954,6 +1982,7 @@
                 config.numNoInternetAccessReports = in.readInt();
                 config.noInternetAccessExpected = in.readInt() != 0;
                 config.shared = in.readInt() != 0;
+                config.mPasspointManagementObjectTree = in.readString();
                 return config;
             }
 
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 605e8c0..a0dbd85 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -273,8 +273,11 @@
         public static final int AKA     = 5;
         /** EAP-Authentication and Key Agreement Prime */
         public static final int AKA_PRIME = 6;
+        /** Hotspot 2.0 r2 OSEN */
+        public static final int UNAUTH_TLS = 7;
         /** @hide */
-        public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'" };
+        public static final String[] strings =
+                { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'", "WFA-UNAUTH-TLS" };
 
         /** Prevent initialization */
         private Eap() {}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index db40cd8..2ad3c2e 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -26,28 +26,26 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
-import android.net.wifi.ScanSettings;
 import android.os.Binder;
 import android.os.Build;
-import android.os.IBinder;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Messenger;
 import android.os.RemoteException;
 import android.os.WorkSource;
-import android.os.Messenger;
 import android.util.Log;
 import android.util.SparseArray;
 
-import java.net.InetAddress;
-import java.util.concurrent.CountDownLatch;
-
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
+import java.net.InetAddress;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 
 /**
  * This class provides the primary API for managing all aspects of Wi-Fi
@@ -114,6 +112,51 @@
     public static final int WIFI_CREDENTIAL_FORGOT = 1;
 
     /**
+     * Broadcast intent action indicating that the a Passpoint release 2 icon has been received.
+     * @hide
+     */
+    public static final String PASSPOINT_ICON_RECEIVED_ACTION =
+            "android.net.wifi.PASSPOINT_ICON_RECEIVED";
+    /** @hide */
+    public static final String EXTRA_PASSPOINT_ICON_BSSID = "bssid";
+    /** @hide */
+    public static final String EXTRA_PASSPOINT_ICON_FILE = "file";
+    /** @hide */
+    public static final String EXTRA_PASSPOINT_ICON_DATA = "icon";
+
+    /**
+     * Broadcast intent action indicating that the a Passpoint release
+     * 2 WNM frame has been received.
+     * @hide
+     */
+    public static final String PASSPOINT_WNM_FRAME_RECEIVED_ACTION =
+            "android.net.wifi.PASSPOINT_WNM_FRAME_RECEIVED";
+    /**
+     * Originating BSS
+     * @hide */
+    public static final String EXTRA_PASSPOINT_WNM_BSSID = "bssid";
+    /**
+     * SOAP-XML or OMA-DM
+     * @hide */
+    public static final String EXTRA_PASSPOINT_WNM_METHOD = "method";
+    /**
+     * Type of Passpoint match
+     * @hide */
+    public static final String EXTRA_PASSPOINT_WNM_PPOINT_MATCH = "match";
+    /**
+     * String
+     * @hide */
+    public static final String EXTRA_PASSPOINT_WNM_URL = "url";
+    /**
+     * Boolean true=ess, false=bss
+     * @hide */
+    public static final String EXTRA_PASSPOINT_WNM_ESS = "ess";
+    /**
+     * Delay in seconds
+     * @hide */
+    public static final String EXTRA_PASSPOINT_WNM_DELAY = "delay";
+
+    /**
      * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
      * enabling, disabling, or unknown. One extra provides this state as an int.
      * Another extra provides the previous state, if available.
@@ -779,6 +822,76 @@
     }
 
     /**
+     * Add a Hotspot 2.0 release 2 Management Object
+     * @param mo The MO in XML form
+     * @return -1 for failure
+     * @hide
+     */
+    public int addPasspointManagementObject(String mo) {
+        try {
+            return mService.addPasspointManagementObject(mo);
+        } catch (RemoteException e) {
+            return -1;
+        }
+    }
+
+    /**
+     * Modify a Hotspot 2.0 release 2 Management Object
+     * @param fqdn The FQDN of the service provider
+     * @param mos A List of MO definitions to be updated
+     * @return the number of nodes updated, or -1 for failure
+     * @hide
+     */
+    public int modifyPasspointManagementObject(String fqdn,
+                                               List<PasspointManagementObjectDefinition> mos) {
+        try {
+            return mService.modifyPasspointManagementObject(fqdn, mos);
+        } catch (RemoteException e) {
+            return -1;
+        }
+    }
+
+    /**
+     * Query for a Hotspot 2.0 release 2 OSU icon
+     * @param bssid The BSSID of the AP
+     * @param fileName Icon file name
+     * @hide
+     */
+    public void queryPasspointIcon(long bssid, String fileName) {
+        try {
+            mService.queryPasspointIcon(bssid, fileName);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Match the currently associated network against the SP matching the given FQDN
+     * @param fqdn FQDN of the SP
+     * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined]
+     * @hide
+     */
+    public int matchProviderWithCurrentNetwork(String fqdn) {
+        try {
+            return mService.matchProviderWithCurrentNetwork(fqdn);
+        } catch (RemoteException e) {
+            return -1;
+        }
+    }
+
+    /**
+     * Deauthenticate and set the re-authentication hold off time for the current network
+     * @param holdoff hold off time in milliseconds
+     * @param ess set if the hold off pertains to an ESS rather than a BSS
+     * @hide
+     */
+    public void deauthenticateNetwork(long holdoff, boolean ess) {
+        try {
+            mService.deauthenticateNetwork(holdoff, ess);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Remove the specified network from the list of configured networks.
      * This may result in the asynchronous delivery of state change
      * events.
@@ -1199,30 +1312,6 @@
     }
 
     /**
-     * An augmented version of getScanResults that returns ScanResults as well as OSU information
-     * wrapped in ScanInfo objects.
-     * @return
-     */
-    public List<ScanInfo> getScanInfos() {
-        try {
-            return mService.getScanInfos(mContext.getOpPackageName());
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Notify the OSU framework about the currently selected OSU.
-     * @param osuID The OSU ID from ScanInfo.getOsuIdentity()
-     */
-    public void setOsuSelection(int osuID) {
-        try {
-            mService.setOsuSelection(osuID);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
      * Check if scanning is always available.
      *
      * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanEventListener.aidl b/wifi/java/android/net/wifi/nan/IWifiNanEventListener.aidl
index 13efc36..fa666af 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanEventListener.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanEventListener.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,
@@ -26,7 +26,7 @@
 oneway interface IWifiNanEventListener
 {
     void onConfigCompleted(in ConfigRequest completedConfig);
-    void onConfigFailed(int reason);
+    void onConfigFailed(in ConfigRequest failedConfig, int reason);
     void onNanDown(int reason);
     void onIdentityChanged();
 }
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
index ec9e462..f382d97 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanManager.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,
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl b/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
index 50c34d9..d60d8ca 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.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,
diff --git a/wifi/java/android/net/wifi/nan/WifiNanEventListener.java b/wifi/java/android/net/wifi/nan/WifiNanEventListener.java
index eae0a55..5c18bd7 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanEventListener.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanEventListener.java
@@ -47,7 +47,8 @@
 
     /**
      * Configuration failed callback event registration flag. Corresponding
-     * callback is {@link WifiNanEventListener#onConfigFailed(int)}.
+     * callback is
+     * {@link WifiNanEventListener#onConfigFailed(ConfigRequest, int)}.
      */
     public static final int LISTEN_CONFIG_FAILED = 0x1 << 1;
 
@@ -93,7 +94,7 @@
                         WifiNanEventListener.this.onConfigCompleted((ConfigRequest) msg.obj);
                         break;
                     case LISTEN_CONFIG_FAILED:
-                        WifiNanEventListener.this.onConfigFailed(msg.arg1);
+                        WifiNanEventListener.this.onConfigFailed((ConfigRequest) msg.obj, msg.arg1);
                         break;
                     case LISTEN_NAN_DOWN:
                         WifiNanEventListener.this.onNanDown(msg.arg1);
@@ -129,7 +130,7 @@
      *
      * @param reason Failure reason code, see {@code NanSessionListener.FAIL_*}.
      */
-    public void onConfigFailed(int reason) {
+    public void onConfigFailed(ConfigRequest failedConfig, int reason) {
         Log.w(TAG, "onConfigFailed: called in stub - override if interested or disable");
     }
 
@@ -173,11 +174,14 @@
         }
 
         @Override
-        public void onConfigFailed(int reason) {
-            if (VDBG) Log.v(TAG, "onConfigFailed: reason=" + reason);
+        public void onConfigFailed(ConfigRequest failedConfig, int reason) {
+            if (VDBG) {
+                Log.v(TAG, "onConfigFailed: failedConfig=" + failedConfig + ", reason=" + reason);
+            }
 
             Message msg = mHandler.obtainMessage(LISTEN_CONFIG_FAILED);
             msg.arg1 = reason;
+            msg.obj = failedConfig;
             mHandler.sendMessage(msg);
         }
 
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java b/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
index d5e59f0..0925087 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
@@ -303,8 +303,8 @@
      * message). Override to implement your custom response.
      * <p>
      * Note that either this callback or
-     * {@link WifiNanSessionListener#onMessageSendFail(int)} will be received -
-     * never both.
+     * {@link WifiNanSessionListener#onMessageSendFail(int, int)} will be
+     * received - never both.
      */
     public void onMessageSendSuccess(int messageId) {
         if (VDBG) Log.v(TAG, "onMessageSendSuccess: called in stub - override if interested");
@@ -319,8 +319,8 @@
      * message). Override to implement your custom response.
      * <p>
      * Note that either this callback or
-     * {@link WifiNanSessionListener#onMessageSendSuccess()} will be received -
-     * never both
+     * {@link WifiNanSessionListener#onMessageSendSuccess(int)} will be received
+     * - never both
      *
      * @param reason The failure reason using {@code NanSessionListener.FAIL_*}
      *            codes.